activitysim
activitysim copied to clipboard
Estimation Enhancements
Estimation work as part of ActivitySim's Phase 9B development effort.
- [x] Implement multiprocessing for estimation mode
- [x] Implement destination choice sampling in estimation mode
- [x] Change the formatting and data written to EDBs
- [x] Update Larch integration to accept new file formats
- [x] Functionality to quickly test different specifications
- [x] Improved larch reporting on estimated models
- [x] Adding "predict" functionality with estimated models in larch
- [x] Unit testing for the above features
- [x] Updated documentation
Hi @dhensle, do you have an ETA for when this PR will be completed? Has it been decided which version will include this enhancement? I have been testing it with our Victoria ActivitySim implementation, so I have a vested interest in your PR. Thank you! :)
Hi @asiripanich, thank you for your interest and testing! We are just putting the finishing touches on this and hope to have it pulled in by the end of the month.
Any feedback from you on the new features? Now's the time to get any changes you might want put in!
Hi @asiripanich, thank you for your interest and testing! We are just putting the finishing touches on this and hope to have it pulled in by the end of the month.
Any feedback from you on the new features? Now's the time to get any changes you might want put in!
I have been able to get this enhanced estimation mode to work with our travel survey. The parquet EBDs are definitely a huge improvement over the CSVs. Thanks for the work!
A few comments:
- I remember the CDAP estimation function wasn't working because my ActivitySim outputs were in Parquet format. I had to add a line to reset the index when reading in Parquet inputs; this is not an issue if you are reading in CSV files.
- I feel like the specification files could be more compact if the coefficient values weren't separated into another file just to specify their constraint values. I understand this would require some work and planning, but how about adding a symbol (e.g., an asterisk *) in front of the coefficient values in the specification file if you want to fix their value? Creating a new label column and coefficient names feels unnecessary and just increases the number of input files that one has to manage, which means a higher chance of making errors. If the label field is required in the specification file, I think it could be automatically generated from the description field by converting the description to underscore case.
Example:
| Description | Expression | M | N | H |
|---|---|---|---|---|
| Full-time worker alternative-specific constants | ptype == 1 | *0.885080091 | 0.531583624 | |
| Part-time worker alternative-specific constants | ptype == 2 | *-0.920808727 | 1.117988879 | |
| University student alternative-specific constants | ptype == 3 | 1.898468936 | -0.380144113 |
Hi @dhensle
I tested the new estimation tool. Great work! I did notice a minor bug related to the file naming. When generating the EDB for school_location, for example, the tool creates a CSV file named school_location_school_location_coeffs.csv instead of school_location_coefficients.csv
For now, Iām manually renaming the file, but it might be a small bug worth checking in the naming logic. Thanks!
Hi @dhensle
I tested the new estimation tool. Great work! I did notice a minor bug related to the file naming. When generating the EDB for school_location, for example, the tool creates a CSV file named school_location_school_location_coeffs.csv instead of school_location_coefficients.csv
For now, Iām manually renaming the file, but it might be a small bug worth checking in the naming logic. Thanks!
Hi @AmirSamimi-TfNSW, thanks for your testing!
The code should be writing the coefficients file with the file name specified in the model yaml settings file. Can you please check the COEFFICIENT setting in your school_location.yaml and see if this naming issue stems from that file? I do not see this issue in any of my outputs.
Hi @asiripanich, thank you for your interest and testing! We are just putting the finishing touches on this and hope to have it pulled in by the end of the month. Any feedback from you on the new features? Now's the time to get any changes you might want put in!
I have been able to get this enhanced estimation mode to work with our travel survey. The parquet EBDs are definitely a huge improvement over the CSVs. Thanks for the work!
A few comments:
- I remember the CDAP estimation function wasn't working because my ActivitySim outputs were in Parquet format. I had to add a line to reset the index when reading in Parquet inputs; this is not an issue if you are reading in CSV files.
- I feel like the specification files could be more compact if the coefficient values weren't separated into another file just to specify their constraint values. I understand this would require some work and planning, but how about adding a symbol (e.g., an asterisk *) in front of the coefficient values in the specification file if you want to fix their value? Creating a new label column and coefficient names feels unnecessary and just increases the number of input files that one has to manage, which means a higher chance of making errors. If the label field is required in the specification file, I think it could be automatically generated from the description field by converting the description to underscore case.
Example:
Description Expression M N H Full-time worker alternative-specific constants ptype == 1 *0.885080091 0.531583624 Part-time worker alternative-specific constants ptype == 2 *-0.920808727 1.117988879 University student alternative-specific constants ptype == 3 1.898468936 -0.380144113
Hi @asiripanich glad the new EDBs have been working for you! In response to your comments:
- CDAP is unique in that it also will read the person and household files. I have updated the parquet read code that exists in this model to handle that indexing issue. Thanks for flagging.
- The decision to move coefficients into a separate file was made when estimation mode was first implemented. I agree that the coefficient values are much harder to see with them being stored in a different file. However, having coefficient names that can be used and estimated across multiple utility terms is the primary reason this change was done. Take for example the cost and in-vehicle time coefficients in mode choice --- they are used numerous times across modes and utility terms. Specifying the coefficient values separately from the spec makes this much easier to see and much easier to estimate. If you would like to have a broader discussion around how we handle coefficient values in ActivitySim configs, I would welcome that discussion in a separate issue as it is outside the scope of this PR. (Perhaps we just need to create a little utility that will output a spec with coefficient values applied for human-readability?)
Thanks for your comments!
Thanks @dhensle for your response.
I ran into an issue today while trying to add a new utility term to the tour mode choice spec of my tour mode choice EDB. This might be a bug or something that needs to be explained a bit more in the documentation. (However, I didn't have any issues modifying or adding new terms to the auto_ownership model. Despite this minor issue, I'm loving this new capability!)
When I tried to add a new line to my tour mode choice spec file, I kept getting this error:
modelname = "tour_mode_choice"
from activitysim.estimation.larch import component_model
model, data = component_model(
modelname,
edb_directory=f"output/estimation_data_bundle/{modelname}/",
return_data=True,
)
> loading from output/estimation_data_bundle/tour_mode_choice/tour_mode_choice_coefficients.csv
> loading from output/estimation_data_bundle/tour_mode_choice/tour_mode_choice_coefficients_template.csv
> loading spec from output/estimation_data_bundle/tour_mode_choice/tour_mode_choice_SPEC.csv
> loading from output/estimation_data_bundle/tour_mode_choice/tour_mode_choice_values_combined.parquet
> unable to rewrite 'util_test' to itself
I tested this using example_estimation and 17_tour_mode_choice.ipynb from this PR.
I added these following lines:
tour_mode_choice_SPEC.csv
util_test,Drive alone not available for escort tours,1,coef_test,,,,,,,,,,,,,,,,,,,,
tour_mode_choice_coefficients_template.csv
coef_test,coef_test_eatout_escort_othdiscr_othmaint_shopping_social_work_atwork,coef_test_eatout_escort_othdiscr_othmaint_shopping_social_work_atwork,coef_test_eatout_escort_othdiscr_othmaint_shopping_social_work_atwork,coef_test_eatout_escort_othdiscr_othmaint_shopping_social_work_atwork,coef_test_school_univ,coef_test_eatout_escort_othdiscr_othmaint_shopping_social_work_atwork,coef_test_eatout_escort_othdiscr_othmaint_shopping_social_work_atwork,coef_test_school_univ,coef_test_eatout_escort_othdiscr_othmaint_shopping_social_work_atwork,coef_test_eatout_escort_othdiscr_othmaint_shopping_social_work_atwork
tour_mode_choice_coefficients.csv
coef_test_eatout_escort_othdiscr_othmaint_shopping_social_work_atwork,0,F
coef_test_school_univ,0,F
Any advice on what I might be doing wrong would be greatly appreciated. š
See full error
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
File /opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/sharrow/relationships.py:942, in DataTree.get_expr(self, expression, engine, allow_native, dtype, with_coords, parser)
941 else:
--> [942](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/sharrow/relationships.py:942) raise KeyError
943 except (KeyError, IndexError):
KeyError:
During handling of the above exception, another exception occurred:
KeyError Traceback (most recent call last)
File /opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/sharrow/relationships.py:958, in DataTree.get_expr(self, expression, engine, allow_native, dtype, with_coords, parser)
956 try:
957 result = DataArray(
--> [958](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/sharrow/relationships.py:958) ne.evaluate(expression, local_dict=CachedTree(self)),
959 )
960 except Exception:
File /opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/numexpr/necompiler.py:975, in evaluate(ex, local_dict, global_dict, out, order, casting, sanitize, _frame_depth, **kwargs)
974 else:
--> [975](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/numexpr/necompiler.py:975) raise e
File /opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/numexpr/necompiler.py:874, in validate(ex, local_dict, global_dict, out, order, casting, _frame_depth, sanitize, **kwargs)
873 names, ex_uses_vml = _names_cache[expr_key]
--> [874](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/numexpr/necompiler.py:874) arguments = getArguments(names, local_dict, global_dict, _frame_depth=_frame_depth)
876 # Create a signature
File /opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/numexpr/necompiler.py:764, in getArguments(names, local_dict, global_dict, _frame_depth)
763 except KeyError:
--> [764](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/numexpr/necompiler.py:764) a = global_dict[name]
765 arguments.append(numpy.asarray(a))
KeyError: 'util_test'
During handling of the above exception, another exception occurred:
ValueError Traceback (most recent call last)
File /opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/larch/dataset/__init__.py:422, in DataTree.setup_flow(self, *args, **kwargs)
421 try:
--> [422](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/larch/dataset/__init__.py:422) return super().setup_flow(*args, **kwargs)
423 except ValueError as err:
File /opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/sharrow/relationships.py:1535, in DataTree.setup_flow(self, definition_spec, cache_dir, name, dtype, boundscheck, error_model, nopython, fastmath, parallel, readme, flow_library, extra_hash_data, write_hash_audit, hashing_level, dim_exclude, with_root_node_name)
1533 from .flows import Flow
-> [1535](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/sharrow/relationships.py:1535) return Flow(
1536 self,
1537 definition_spec,
1538 cache_dir=cache_dir or self.cache_dir,
1539 name=name,
1540 dtype=dtype,
1541 boundscheck=boundscheck,
1542 nopython=nopython,
1543 fastmath=fastmath,
1544 parallel=parallel,
1545 readme=readme,
1546 flow_library=flow_library,
1547 extra_hash_data=extra_hash_data,
1548 hashing_level=hashing_level,
1549 error_model=error_model,
1550 write_hash_audit=write_hash_audit,
1551 dim_order=self.dim_order,
1552 dim_exclude=dim_exclude,
1553 with_root_node_name=with_root_node_name,
1554 )
File /opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/sharrow/flows.py:1053, in Flow.__new__(cls, tree, defs, error_model, cache_dir, name, dtype, boundscheck, nopython, fastmath, parallel, readme, flow_library, extra_hash_data, write_hash_audit, hashing_level, dim_order, dim_exclude, bool_wrapping, with_root_node_name, parallel_irunner, parallel_idotter)
1052 # otherwise finish normal init
-> [1053](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/sharrow/flows.py:1053) self.__initialize_2(
1054 defs,
1055 error_model=error_model,
1056 name=name,
1057 dtype=dtype,
1058 boundscheck=boundscheck,
1059 nopython=nopython,
1060 fastmath=fastmath,
1061 readme=readme,
1062 parallel=parallel,
1063 extra_hash_data=extra_hash_data,
1064 write_hash_audit=write_hash_audit,
1065 with_root_node_name=with_root_node_name,
1066 parallel_idotter=parallel_idotter,
1067 parallel_irunner=parallel_irunner,
1068 )
1069 if flow_library is not None:
File /opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/sharrow/flows.py:1620, in Flow.__initialize_2(self, defs, error_model, name, dtype, boundscheck, nopython, fastmath, readme, parallel, extra_hash_data, write_hash_audit, with_root_node_name, parallel_irunner, parallel_idotter)
1619 if self._hashing_level <= 1:
-> [1620](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/sharrow/flows.py:1620) func_code, all_name_tokens = self.init_sub_funcs(
1621 defs,
1622 error_model=error_model,
1623 boundscheck=boundscheck,
1624 nopython=nopython,
1625 fastmath=fastmath,
1626 )
1627 self._func_code = func_code
File /opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/sharrow/flows.py:1546, in Flow.init_sub_funcs(self, defs, error_model, boundscheck, nopython, fastmath)
1545 logger.error(f"unable to rewrite '{k}' to itself")
-> [1546](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/sharrow/flows.py:1546) raise ValueError(f"unable to rewrite '{k}' to itself")
1547 logger.debug(f"[{k}] rewrite {init_expr} -> {expr}")
ValueError: unable to rewrite 'util_test' to itself
The above exception was the direct cause of the following exception:
ValueError Traceback (most recent call last)
File /opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/sharrow/relationships.py:1073, in DataTree.eval(self, expression, engine, dtype, name, with_coords)
1072 try:
-> [1073](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/sharrow/relationships.py:1073) result = self.get_expr(
1074 expression,
1075 "numexpr",
1076 allow_native=False,
1077 dtype=dtype,
1078 with_coords=with_coords,
1079 )
1080 except Exception:
File /opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/sharrow/relationships.py:964, in DataTree.get_expr(self, expression, engine, allow_native, dtype, with_coords, parser)
962 dtype = "float32"
963 result = (
--> [964](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/sharrow/relationships.py:964) self.setup_flow({expression: expression}, dtype=dtype)
965 .load_dataarray()
966 .isel(expressions=0)
967 )
968 else:
File /opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/larch/dataset/__init__.py:426, in DataTree.setup_flow(self, *args, **kwargs)
425 if regex:
--> [426](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/larch/dataset/__init__.py:426) raise ValueError(
427 f"Setup failed for variable {regex.group(1)}. Check the expression "
428 f"and the names of the variables in the dataset."
429 ) from err
430 else:
ValueError: Setup failed for variable 'util_test'. Check the expression and the names of the variables in the dataset.
During handling of the above exception, another exception occurred:
KeyError Traceback (most recent call last)
File /opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/sharrow/relationships.py:942, in DataTree.get_expr(self, expression, engine, allow_native, dtype, with_coords, parser)
941 else:
--> [942](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/sharrow/relationships.py:942) raise KeyError
943 except (KeyError, IndexError):
KeyError:
During handling of the above exception, another exception occurred:
ValueError Traceback (most recent call last)
File /opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/larch/dataset/__init__.py:422, in DataTree.setup_flow(self, *args, **kwargs)
421 try:
--> [422](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/larch/dataset/__init__.py:422) return super().setup_flow(*args, **kwargs)
423 except ValueError as err:
File /opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/sharrow/relationships.py:1535, in DataTree.setup_flow(self, definition_spec, cache_dir, name, dtype, boundscheck, error_model, nopython, fastmath, parallel, readme, flow_library, extra_hash_data, write_hash_audit, hashing_level, dim_exclude, with_root_node_name)
1533 from .flows import Flow
-> [1535](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/sharrow/relationships.py:1535) return Flow(
1536 self,
1537 definition_spec,
1538 cache_dir=cache_dir or self.cache_dir,
1539 name=name,
1540 dtype=dtype,
1541 boundscheck=boundscheck,
1542 nopython=nopython,
1543 fastmath=fastmath,
1544 parallel=parallel,
1545 readme=readme,
1546 flow_library=flow_library,
1547 extra_hash_data=extra_hash_data,
1548 hashing_level=hashing_level,
1549 error_model=error_model,
1550 write_hash_audit=write_hash_audit,
1551 dim_order=self.dim_order,
1552 dim_exclude=dim_exclude,
1553 with_root_node_name=with_root_node_name,
1554 )
File /opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/sharrow/flows.py:1053, in Flow.__new__(cls, tree, defs, error_model, cache_dir, name, dtype, boundscheck, nopython, fastmath, parallel, readme, flow_library, extra_hash_data, write_hash_audit, hashing_level, dim_order, dim_exclude, bool_wrapping, with_root_node_name, parallel_irunner, parallel_idotter)
1052 # otherwise finish normal init
-> [1053](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/sharrow/flows.py:1053) self.__initialize_2(
1054 defs,
1055 error_model=error_model,
1056 name=name,
1057 dtype=dtype,
1058 boundscheck=boundscheck,
1059 nopython=nopython,
1060 fastmath=fastmath,
1061 readme=readme,
1062 parallel=parallel,
1063 extra_hash_data=extra_hash_data,
1064 write_hash_audit=write_hash_audit,
1065 with_root_node_name=with_root_node_name,
1066 parallel_idotter=parallel_idotter,
1067 parallel_irunner=parallel_irunner,
1068 )
1069 if flow_library is not None:
File /opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/sharrow/flows.py:1620, in Flow.__initialize_2(self, defs, error_model, name, dtype, boundscheck, nopython, fastmath, readme, parallel, extra_hash_data, write_hash_audit, with_root_node_name, parallel_irunner, parallel_idotter)
1619 if self._hashing_level <= 1:
-> [1620](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/sharrow/flows.py:1620) func_code, all_name_tokens = self.init_sub_funcs(
1621 defs,
1622 error_model=error_model,
1623 boundscheck=boundscheck,
1624 nopython=nopython,
1625 fastmath=fastmath,
1626 )
1627 self._func_code = func_code
File /opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/sharrow/flows.py:1546, in Flow.init_sub_funcs(self, defs, error_model, boundscheck, nopython, fastmath)
1545 logger.error(f"unable to rewrite '{k}' to itself")
-> [1546](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/sharrow/flows.py:1546) raise ValueError(f"unable to rewrite '{k}' to itself")
1547 logger.debug(f"[{k}] rewrite {init_expr} -> {expr}")
ValueError: unable to rewrite 'util_test' to itself
The above exception was the direct cause of the following exception:
ValueError Traceback (most recent call last)
Cell In[20], [line 5](vscode-notebook-cell:?execution_count=20&line=5)
1 modelname = "tour_mode_choice"
3 from activitysim.estimation.larch import component_model
----> [5](vscode-notebook-cell:?execution_count=20&line=5) model, data = component_model(
6 modelname,
7 edb_directory=f"output/estimation_data_bundle/{modelname}/",
8 return_data=True,
9 )
File ~/GitHub/tmp/activitysim/activitysim/estimation/larch/__init__.py:64, in component_model(name, *args, **kwargs)
62 m = globals().get(f"{name}_model")
63 if m:
---> [64](https://file+.vscode-resource.vscode-cdn.net/Users/amarin/GitHub/tmp/activitysim/example_estimation/~/GitHub/tmp/activitysim/activitysim/estimation/larch/__init__.py:64) return m(*args, **kwargs)
65 raise KeyError(f"no known {name}_model")
66 else:
File ~/GitHub/tmp/activitysim/activitysim/estimation/larch/mode_choice.py:136, in tour_mode_choice_model(name, edb_directory, return_data)
131 def tour_mode_choice_model(
132 name="tour_mode_choice",
133 edb_directory="output/estimation_data_bundle/{name}/",
134 return_data=False,
135 ):
--> [136](https://file+.vscode-resource.vscode-cdn.net/Users/amarin/GitHub/tmp/activitysim/example_estimation/~/GitHub/tmp/activitysim/activitysim/estimation/larch/mode_choice.py:136) return mode_choice_model(
137 name=name,
138 edb_directory=edb_directory,
139 return_data=return_data,
140 )
File ~/GitHub/tmp/activitysim/activitysim/estimation/larch/mode_choice.py:110, in mode_choice_model(name, edb_directory, return_data, override_filenames)
107 model.datatree = d
108 model.choice_co_code = "override_choice_code"
--> [110](https://file+.vscode-resource.vscode-cdn.net/Users/amarin/GitHub/tmp/activitysim/example_estimation/~/GitHub/tmp/activitysim/activitysim/estimation/larch/mode_choice.py:110) mg = lx.ModelGroup(m.values())
111 explicit_value_parameters(mg)
112 apply_coefficients(coefficients, mg)
File /opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/larch/model/model_group.py:62, in ModelGroup.__init__(self, models, title)
60 else:
61 self._submodels.append(model)
---> [62](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/larch/model/model_group.py:62) self._parameter_bucket.attach_model(model)
File /opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/larch/model/param_core.py:104, in ParameterBucket.attach_model(self, model, name, agg, unmangle)
102 model.unmangle(structure_only=True)
103 elif unmangle:
--> [104](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/larch/model/param_core.py:104) model.unmangle()
105 self._models[name] = model
107 # collect parameters from the incoming model to be attached, to be able
108 # to update the bucket's parameters if they are not already present
File /opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/larch/model/jaxmodel.py:165, in Model.unmangle(self, force, structure_only)
163 try:
164 setattr(self, marker, True)
--> [165](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/larch/model/jaxmodel.py:165) super().unmangle(force=force, structure_only=structure_only)
166 for mix in self.mixtures:
167 mix.prep(self._parameter_bucket)
File /opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/larch/model/numbamodel.py:1192, in NumbaModel.unmangle(self, force, structure_only)
1190 if not structure_only:
1191 if self._dataset is None or force:
-> [1192](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/larch/model/numbamodel.py:1192) self.reflow_data_arrays()
1193 if self._fixed_arrays is None or force:
1194 self._rebuild_fixed_arrays()
File /opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/larch/model/jaxmodel.py:177, in Model.reflow_data_arrays(self)
175 """Reload the internal data_arrays so they are consistent with the datatree."""
176 if self.compute_engine != "jax":
--> [177](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/larch/model/jaxmodel.py:177) return super().reflow_data_arrays()
179 if self.graph is None:
180 self._data_arrays = None
File /opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/larch/model/numbamodel.py:1058, in NumbaModel.reflow_data_arrays(self)
1055 from .data_arrays import prepare_data
1057 logger.debug(f"Model.datatree.cache_dir = {datatree.cache_dir}")
-> [1058](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/larch/model/numbamodel.py:1058) self.dataset, self.dataflows = prepare_data(
1059 datasource=datatree,
1060 request=self,
1061 float_dtype=self.float_dtype,
1062 cache_dir=datatree.cache_dir,
1063 flows=self.dataflows,
1064 make_unused_flows=self.use_streaming,
1065 )
1066 if self.use_streaming:
1067 # when streaming the dataset created above is a vestigial
1068 # one-case dataset, really we just want the flows, so we
1069 # get rid of the dataset now
1070 self._dataset = None
File /opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/larch/model/data_arrays.py:159, in prepare_data(datasource, request, float_dtype, cache_dir, flows, make_unused_flows)
157 if "co" in request:
158 log.debug(f"requested co data: {request['co']}")
--> [159](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/larch/model/data_arrays.py:159) model_dataset, flows["co"] = _prep_co(
160 model_dataset,
161 datatree_co,
162 request["co"],
163 tag="co",
164 dtype=float_dtype,
165 cache_dir=cache_dir,
166 flow=flows.get("co"),
167 )
168 if "ca" in request:
169 log.debug(f"requested ca data: {request['ca']}")
File /opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/larch/model/data_arrays.py:637, in _prep_co(model_dataset, shared_data_co, vars_co, tag, preserve_vars, dtype, dim_name, cache_dir, flow, use_array_maker, use_eval)
635 return model_dataset, None
636 if use_eval:
--> [637](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/larch/model/data_arrays.py:637) arr = shared_data_co.eval_many(
638 vars_co, dtype=dtype, result_type="dataarray", with_coords=False
639 ).values
640 else:
641 flowname = flownamer(tag, vars_co, shared_data_co._hash_features())
File /opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/sharrow/relationships.py:1158, in DataTree.eval_many(self, expressions, engine, dtype, result_type, with_coords)
1156 arrays = {}
1157 for k, v in expressions.items():
-> [1158](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/sharrow/relationships.py:1158) a = self.eval(
1159 v, engine=engine, dtype=dtype, name=k, with_coords=with_coords
1160 )
1161 if "expressions" in a.coords:
1162 a = a.drop_vars("expressions")
File /opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/sharrow/relationships.py:1081, in DataTree.eval(self, expression, engine, dtype, name, with_coords)
1073 result = self.get_expr(
1074 expression,
1075 "numexpr",
(...)
1078 with_coords=with_coords,
1079 )
1080 except Exception:
-> [1081](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/sharrow/relationships.py:1081) result = self.get_expr(
1082 expression,
1083 "sharrow",
1084 allow_native=False,
1085 dtype=dtype,
1086 with_coords=with_coords,
1087 )
1088 else:
1089 result = self.get_expr(
1090 expression,
1091 engine,
(...)
1094 with_coords=with_coords,
1095 )
File /opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/sharrow/relationships.py:[948](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/sharrow/relationships.py:948), in DataTree.get_expr(self, expression, engine, allow_native, dtype, with_coords, parser)
945 if dtype is None:
946 dtype = "float32"
947 result = (
--> 948 self.setup_flow({expression: expression}, dtype=dtype)
949 .load_dataarray()
950 .isel(expressions=0)
951 )
952 elif engine == "numexpr":
953 import numexpr as ne
File /opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/larch/dataset/__init__.py:[426](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/Caskroom/miniforge/base/envs/asim-dev/lib/python3.10/site-packages/larch/dataset/__init__.py:426), in DataTree.setup_flow(self, *args, **kwargs)
424 regex = re.match("^unable to rewrite (.*) to itself$", str(err))
425 if regex:
--> 426 raise ValueError(
427 f"Setup failed for variable {regex.group(1)}. Check the expression "
428 f"and the names of the variables in the dataset."
429 ) from err
430 else:
431 raise err
ValueError: Setup failed for variable 'util_test'. Check the expression and the names of the variables in the dataset.
@asiripanich, this is a sharrow-related error. I'll take a look at it and see if I can figure out what's wrong...
Thanks @dhensle for your response.
I ran into an issue today while trying to add a new utility term to the tour mode choice spec of my tour mode choice EDB. This might be a bug or something that needs to be explained a bit more in the documentation. (However, I didn't have any issues modifying or adding new terms to the auto_ownership model. Despite this minor issue, I'm loving this new capability!)
When I tried to add a new line to my tour mode choice spec file, I kept getting this error:
modelname = "tour_mode_choice" from activitysim.estimation.larch import component_model model, data = component_model( modelname, edb_directory=f"output/estimation_data_bundle/{modelname}/", return_data=True, ) > loading from output/estimation_data_bundle/tour_mode_choice/tour_mode_choice_coefficients.csv > loading from output/estimation_data_bundle/tour_mode_choice/tour_mode_choice_coefficients_template.csv > loading spec from output/estimation_data_bundle/tour_mode_choice/tour_mode_choice_SPEC.csv > loading from output/estimation_data_bundle/tour_mode_choice/tour_mode_choice_values_combined.parquet > unable to rewrite 'util_test' to itselfI tested this using
example_estimationand17_tour_mode_choice.ipynbfrom this PR.I added these following lines:
tour_mode_choice_SPEC.csvutil_test,Drive alone not available for escort tours,1,coef_test,,,,,,,,,,,,,,,,,,,,
tour_mode_choice_coefficients_template.csvcoef_test,coef_test_eatout_escort_othdiscr_othmaint_shopping_social_work_atwork,coef_test_eatout_escort_othdiscr_othmaint_shopping_social_work_atwork,coef_test_eatout_escort_othdiscr_othmaint_shopping_social_work_atwork,coef_test_eatout_escort_othdiscr_othmaint_shopping_social_work_atwork,coef_test_school_univ,coef_test_eatout_escort_othdiscr_othmaint_shopping_social_work_atwork,coef_test_eatout_escort_othdiscr_othmaint_shopping_social_work_atwork,coef_test_school_univ,coef_test_eatout_escort_othdiscr_othmaint_shopping_social_work_atwork,coef_test_eatout_escort_othdiscr_othmaint_shopping_social_work_atwork
tour_mode_choice_coefficients.csvcoef_test_eatout_escort_othdiscr_othmaint_shopping_social_work_atwork,0,F coef_test_school_univ,0,FAny advice on what I might be doing wrong would be greatly appreciated. š
See full error
@asiripanich, turns out you were doing nothing wrong, you just happened to find a bug -- a couple arguments were missing from the code to re-estimate the mode choice models. I've fixed it, and taken your edits to create an example / unit test of re-estimation on the tour mode choice notebook. If you try again it should work now. š
@asiripanich, turns out you were doing nothing wrong, you just happened to find a bug -- a couple arguments were missing from the code to re-estimate the mode choice models. I've fixed it, and taken your edits to create an example / unit test of re-estimation on the tour mode choice notebook. If you try again it should work now. š
@jpn-- Brilliant! I was away and haven't had a chance to test the new changes in this PR yet, but I'm looking forward to trying it out. I remember seeing this feature was planned for v1.4.0... is there an updated timeline for its release?
Would it be possible to confirm that this issue still exists #595 ? Also #752 please.
@dhensle please confirm that this PR fixes #897
@dhensle please confirm that this PR fixes #897
Yes, closed that issue under the assumption this will be pulled in shortly.