From 6b040551a66a5c9fcf068ea657f29d73f463e057 Mon Sep 17 00:00:00 2001 From: Nicholas Reinicke Date: Fri, 17 Nov 2023 11:45:38 -0700 Subject: [PATCH 1/2] bump version; add multi-energy targets for phev; mypy fix --- .github/workflows/test.yaml | 2 +- mypy.ini | 7 ------- nrel/routee/powertrain/core/powertrain_type.py | 2 ++ .../powertrain/core/real_world_adjustments.py | 2 ++ .../default_models/external_model_links.json | 10 +++++----- .../powertrain/trainers/sklearn_random_forest.py | 13 +++++++++++-- nrel/routee/powertrain/validation/errors.py | 8 ++++---- pyproject.toml | 11 +++++++++-- setup.py | 3 --- 9 files changed, 34 insertions(+), 24 deletions(-) delete mode 100644 mypy.ini delete mode 100644 setup.py diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 104ef4c..6fbc583 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -37,7 +37,7 @@ jobs: pip install ".[dev]" - name: Run mypy - run: mypy . + run: mypy . - name: Run black run: | diff --git a/mypy.ini b/mypy.ini deleted file mode 100644 index a2955b2..0000000 --- a/mypy.ini +++ /dev/null @@ -1,7 +0,0 @@ -[mypy] -ignore_missing_imports = True -exclude = (?x)( - docs/ - | build/ - | dist/ - ) \ No newline at end of file diff --git a/nrel/routee/powertrain/core/powertrain_type.py b/nrel/routee/powertrain/core/powertrain_type.py index 6ff724f..0d84775 100644 --- a/nrel/routee/powertrain/core/powertrain_type.py +++ b/nrel/routee/powertrain/core/powertrain_type.py @@ -9,6 +9,8 @@ class PowertrainType(Enum): ICE = 1 HEV = 2 BEV = 3 + PHEV_EV_MODE = 4 + PHEV_HEV_MODE = 5 @classmethod def from_string(cls, s: Optional[str]) -> PowertrainType: diff --git a/nrel/routee/powertrain/core/real_world_adjustments.py b/nrel/routee/powertrain/core/real_world_adjustments.py index 4a293a8..5f87907 100644 --- a/nrel/routee/powertrain/core/real_world_adjustments.py +++ b/nrel/routee/powertrain/core/real_world_adjustments.py @@ -7,4 +7,6 @@ PowertrainType.ICE: 1.166, PowertrainType.HEV: 1.1252, PowertrainType.BEV: 1.3958, + PowertrainType.PHEV_EV_MODE: 1.3958, + PowertrainType.PHEV_HEV_MODE: 1.1252, } diff --git a/nrel/routee/powertrain/resources/default_models/external_model_links.json b/nrel/routee/powertrain/resources/default_models/external_model_links.json index 4da720f..18dab14 100644 --- a/nrel/routee/powertrain/resources/default_models/external_model_links.json +++ b/nrel/routee/powertrain/resources/default_models/external_model_links.json @@ -4,19 +4,19 @@ "2016_AUDI_A3_4cyl_2WD": "https://app.box.com/shared/static/msdkke3xtdpknmu6a26j08ol8vxiw0hu.json", "2016_BMW_328d_4cyl_2WD": "https://app.box.com/shared/static/1710cj655y0t5rtclh1ogo0eqt8subr7.json", "2016_BMW_i3_REx_PHEV_Charge_Depleting": "https://app.box.com/shared/static/oe6tbw2mlx35ak3m39ms6anxaeulheph.json", - "2016_BMW_i3_REx_PHEV_Charge_Sustaining": "https://app.box.com/shared/static/wjrmdj9ec6vb9mhtovsqe5bhi67ot4h9.json", + "2016_BMW_i3_REx_PHEV_Charge_Sustaining": "https://app.box.com/shared/static/tzhyb99ch98s3wofwld6vhu4ylbfuq8j.json", "2016_CHEVROLET_Malibu_4cyl_2WD": "https://app.box.com/shared/static/hi0k3dsnliru8bf3ho4tygnz7o2bbc39.json", "2016_CHEVROLET_Spark_EV": "https://app.box.com/shared/static/p3w6sifsaf924hm4xr0fcnyvq5f735sb.json", "2016_CHEVROLET_Volt_Charge_Depleting": "https://app.box.com/shared/static/refg47ekep5anyq41cvd5e347w5bglv4.json", - "2016_CHEVROLET_Volt_Charge_Sustaining": "https://app.box.com/shared/static/gtduyd1vhfm55lk3je18zsjb5e75dxcb.json", + "2016_CHEVROLET_Volt_Charge_Sustaining": "https://app.box.com/shared/static/v90zippsq2gbenzevk6tktjh20skm5rb.json", "2016_FORD_C-MAX_(PHEV)_Charge_Depleting": "https://app.box.com/shared/static/8xzw1joi4z75146wosob55z0v4t56s0t.json", - "2016_FORD_C-MAX_(PHEV)_Charge_Sustaining": "https://app.box.com/shared/static/5e2tbg1lxhbb8xpgg9xpjee8po0vuile.json", + "2016_FORD_C-MAX_(PHEV)_Charge_Sustaining": "https://app.box.com/shared/static/ejgyl2ye0j0d88p99t8tjs7xqpmfute9.json", "2016_FORD_C-MAX_HEV": "https://app.box.com/shared/static/1g0ut3e8dux98wupucrqnlhcrqb4pg2q.json", "2016_FORD_Escape_4cyl_2WD": "https://app.box.com/shared/static/co9prrqzfqk4lj8860zwpah1n6lmethz.json", "2016_FORD_Explorer_4cyl_2WD": "https://app.box.com/shared/static/odlr0di4avsyk09sgt98oifuekemkluw.json", "2016_HYUNDAI_Elantra_4cyl_2WD": "https://app.box.com/shared/static/gou1vtt6ii5npr65o834iz1xsn1wxx1h.json", "2016_HYUNDAI_Sonata_PHEV_Charge_Depleting": "https://app.box.com/shared/static/s802i81gce7zgue9bqksx7qhupbuq30i.json", - "2016_HYUNDAI_Sonata_PHEV_Charge_Sustaining": "https://app.box.com/shared/static/4clk59eyyxebg4jcrok5xhyfbykzjee4.json", + "2016_HYUNDAI_Sonata_PHEV_Charge_Sustaining": "https://app.box.com/shared/static/m7cskbeppcug6ekwx0dpt7btvza01d8m.json", "2016_KIA_Optima_Hybrid": "https://app.box.com/shared/static/iavjn7x93umljvtmuwtbplsbxd1nrjbm.json", "2016_Leaf_24_kWh": "https://app.box.com/shared/static/gl7ap1czp6cihsil29wwaktindqyfzk4.json", "2016_MITSUBISHI_i-MiEV": "https://app.box.com/shared/static/93khsx238l3b3emq36ui8yj0rnmf737w.json", @@ -29,7 +29,7 @@ "2017_CHEVROLET_Bolt": "https://app.box.com/shared/static/6yg9ed4gixrp7q5irze2w4ud5h3nthme.json", "2017_Maruti_Dzire_VDI": "https://app.box.com/shared/static/luyzs74knk7yowjbuer5zb88getfstjx.json", "2017_Prius_Prime_Charge_Depleting": "https://app.box.com/shared/static/5m6mnxtg0bpb8to19570nikcxa7mryn3.json", - "2017_Prius_Prime_Charge_Sustaining": "https://app.box.com/shared/static/84yx66loytq79of7w528m68ehibs16ze.json", + "2017_Prius_Prime_Charge_Sustaining": "https://app.box.com/shared/static/cxtts7pj9hi2n8om2xcx2d1i0rpsa6pw.json", "2017_Toyota_Highlander_3": "https://app.box.com/shared/static/ihmhqsy2myfceh25xhhld8jhv995np2d.json", "2020_Chevrolet_Colorado_2WD_Diesel": "https://app.box.com/shared/static/i969w1bc6p1uvvubtxtiugvnh56ib1dq.json", "2020_VW_Golf_1": "https://app.box.com/shared/static/u3ya0kc5ehol7qcv7ecov6992839cn9g.json", diff --git a/nrel/routee/powertrain/trainers/sklearn_random_forest.py b/nrel/routee/powertrain/trainers/sklearn_random_forest.py index 047c114..7937820 100644 --- a/nrel/routee/powertrain/trainers/sklearn_random_forest.py +++ b/nrel/routee/powertrain/trainers/sklearn_random_forest.py @@ -1,6 +1,6 @@ from enum import Enum import pandas as pd -from skl2onnx import to_onnx +from skl2onnx import convert_sklearn from skl2onnx.common.data_types import FloatTensorType from sklearn.ensemble import RandomForestRegressor @@ -55,10 +55,19 @@ def inner_train( if self.output_type == RandomForestTrainerOutput.ONNX: # convert to ONNX n_features = len(features.columns) + n_targets = len(target.columns) + + # explicity specify the output shape since skl2onnx was not able to infer it + def custom_transform_shape_calculator(operator): + operator.outputs[0].type = FloatTensorType([None, n_targets]) + initial_type = [(ONNX_INPUT_NAME, FloatTensorType([None, n_features]))] - onnx_model = to_onnx( + onnx_model = convert_sklearn( rf, initial_types=initial_type, + custom_shape_calculators={ + rf.__class__: custom_transform_shape_calculator + }, ) estimator = ONNXEstimator(onnx_model) diff --git a/nrel/routee/powertrain/validation/errors.py b/nrel/routee/powertrain/validation/errors.py index cae94f8..9739a15 100644 --- a/nrel/routee/powertrain/validation/errors.py +++ b/nrel/routee/powertrain/validation/errors.py @@ -29,12 +29,12 @@ def mean_squared_error( - A: np.ndarray, B: np.ndarray, axis: Optional[int] = None + A, B, axis: Optional[int] = None ) -> float: return np.square(A - B).mean(axis=axis) -def net_energy_error(target: np.ndarray, target_pred: np.ndarray) -> float: +def net_energy_error(target, target_pred) -> float: net_e = np.sum(target) net_e_pred = np.sum(target_pred) net_error = (net_e_pred - net_e) / net_e @@ -42,7 +42,7 @@ def net_energy_error(target: np.ndarray, target_pred: np.ndarray) -> float: def weighted_relative_percent_difference( - target: np.ndarray, target_pred: np.ndarray + target, target_pred ) -> float: epsilon = np.finfo(np.float64).eps @@ -61,7 +61,7 @@ def weighted_relative_percent_difference( return mean_error -def relative_percent_difference(target: np.ndarray, target_pred: np.ndarray) -> float: +def relative_percent_difference(target, target_pred) -> float: epsilon = np.finfo(np.float64).eps error_norm = np.abs( diff --git a/pyproject.toml b/pyproject.toml index 056a405..6ab1a4a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "nrel.routee.powertrain" -version = "1.0.2" +version = "1.0.3" description = "RouteE-Powertrain is a tool for predicting energy usage over a set of road links." readme = "README.md" authors = [{ name = "National Renewable Energy Laboratory" }] @@ -39,7 +39,8 @@ dev = [ "types-protobuf", "types-python-dateutil", "types-redis", - "types-requests" + "types-requests", + "pandas-stubs", ] [project.urls] @@ -56,3 +57,9 @@ include = [ [tool.ruff.per-file-ignores] "__init__.py" = ["F401"] + +[tool.mypy] +ignore_missing_imports = true +namespace_packages = true +explicit_package_bases = true +exclude = ["docs/", "build/", "dist/"] diff --git a/setup.py b/setup.py deleted file mode 100644 index 6068493..0000000 --- a/setup.py +++ /dev/null @@ -1,3 +0,0 @@ -from setuptools import setup - -setup() From 084031b48e4bfc976f565539fd3595154de9e9e4 Mon Sep 17 00:00:00 2001 From: Nicholas Reinicke Date: Fri, 17 Nov 2023 11:55:27 -0700 Subject: [PATCH 2/2] formatting --- nrel/routee/powertrain/validation/errors.py | 8 ++------ scripts/developers/train_model_catalog.py | 8 ++++---- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/nrel/routee/powertrain/validation/errors.py b/nrel/routee/powertrain/validation/errors.py index 9739a15..9920fc9 100644 --- a/nrel/routee/powertrain/validation/errors.py +++ b/nrel/routee/powertrain/validation/errors.py @@ -28,9 +28,7 @@ } -def mean_squared_error( - A, B, axis: Optional[int] = None -) -> float: +def mean_squared_error(A, B, axis: Optional[int] = None) -> float: return np.square(A - B).mean(axis=axis) @@ -41,9 +39,7 @@ def net_energy_error(target, target_pred) -> float: return net_error -def weighted_relative_percent_difference( - target, target_pred -) -> float: +def weighted_relative_percent_difference(target, target_pred) -> float: epsilon = np.finfo(np.float64).eps w = np.array(np.abs(target) / np.sum(np.abs(target))) diff --git a/scripts/developers/train_model_catalog.py b/scripts/developers/train_model_catalog.py index 20991ed..391a5e2 100644 --- a/scripts/developers/train_model_catalog.py +++ b/scripts/developers/train_model_catalog.py @@ -312,17 +312,17 @@ def load_all_files(files, file_limit=FILE_LIMIT): pt.DataColumn(name="grade_dec", units="decimal"), pt.DataColumn(name="entry_angle", units="degrees"), ] -features = [ +features = [ [pt.DataColumn(name="speed_mph", units="mph")], [ pt.DataColumn(name="speed_mph", units="mph"), - pt.DataColumn(name="grade_dec", units="decimal") + pt.DataColumn(name="grade_dec", units="decimal"), ], [ pt.DataColumn(name="speed_mph", units="mph"), pt.DataColumn(name="previous_speed_mph", units="mph"), pt.DataColumn(name="grade_dec", units="decimal"), - pt.DataColumn(name="previous_grade_dec", units="decimal") + pt.DataColumn(name="previous_grade_dec", units="decimal"), ], [ pt.DataColumn(name="previous_speed_mph", units="mph"), @@ -330,7 +330,7 @@ def load_all_files(files, file_limit=FILE_LIMIT): pt.DataColumn(name="previous_grade_dec", units="decimal"), pt.DataColumn(name="grade_dec", units="decimal"), pt.DataColumn(name="entry_angle", units="degrees"), - pt.DataColumn(name="exit_angle", units="degrees") + pt.DataColumn(name="exit_angle", units="degrees"), ], ]