automl / ConfigSpace

Domain specific language for configuration spaces in Python. Useful for hyperparameter optimization and algorithm configuration.
https://automl.github.io/ConfigSpace/
Other
202 stars 93 forks source link

Read ForbiddenRelations clauses from json #356

Closed JosuaCarl closed 2 months ago

JosuaCarl commented 5 months ago

As mentioned in #352, there still is some work to be done on the documentation side of things for ForbiddenRelations. Today I encountered another problem when trying to read in a ConfigurationSpace from a .json file, created with ConfigSpace.

Version: 0.7.1

Error:

"name": "KeyError", "message": "'name'", "stack": "--------------------------------------------------------------------------- KeyError Traceback (most recent call last) Cell In[3], line 20 18 with open('configspace.json', 'r') as f: 19 json_string = f.read() ---> 20 config = cs_json.read(json_string)

File XYZ/.conda/envs/MStoML/lib/python3.11/site-packages/ConfigSpace/read_and_write/json.py:459, in read(jason_string) 450 configuration_space.add_condition( 451 _construct_condition( 452 condition, 453 configuration_space, 454 ), 455 ) 457 for forbidden in jason[\"forbiddens\"]: 458 configuration_space.add_forbidden_clause( --> 459 _construct_forbidden( 460 forbidden, 461 configuration_space, 462 ), 463 ) 465 return configuration_space

File XYZ/.conda/envs/MStoML/lib/python3.11/site-packages/ConfigSpace/read_and_write/json.py:668, in _construct_forbidden(clause, cs) 661 forbidden_type = clause[\"type\"] 662 methods = { 663 \"EQUALS\": _construct_forbidden_equals, 664 \"IN\": _construct_forbidden_in, 665 \"AND\": _construct_forbidden_and, 666 \"RELATION\": _construct_forbidden_equals, 667 } --> 668 return methods[forbidden_type](clause, cs)

File XYZ/.conda/envs/MStoML/lib/python3.11/site-packages/ConfigSpace/read_and_write/json.py:675, in _construct_forbidden_equals(clause, cs) 671 def _construct_forbidden_equals( 672 clause: dict, 673 cs: ConfigurationSpace, 674 ) -> ForbiddenEqualsClause: --> 675 return ForbiddenEqualsClause(hyperparameter=cs[clause[\"name\"]], value=clause[\"value\"])

KeyError: 'name'"

Code to reproduce:

ConfigSpace import ConfigurationSpace, Integer, ForbiddenGreaterThanRelation
from ConfigSpace.read_and_write import json as cs_json

configuration_space = ConfigurationSpace(seed=42)
hyperparameters = [
    Integer(        "intermediate_dimension",   (100, 200), log=True, default=200),
    Integer(        "latent_dimension",         (10, 200), log=False, default=50),
]
configuration_space.add_hyperparameters(hyperparameters)
forbidden_clauses = [
    ForbiddenGreaterThanRelation(configuration_space["latent_dimension"], configuration_space["intermediate_dimension"])
]
configuration_space.add_forbidden_clauses(forbidden_clauses)

cs_string = cs_json.write(configuration_space)
with open('configspace.json', 'w') as f:
     f.write(cs_string)

with open('configspace.json', 'r') as f:
    json_string = f.read()
    config = cs_json.read(json_string)

Tracing: It seems like the following constructor: https://github.com/automl/ConfigSpace/blob/ce27ba26e1cf27a5b9fe242519cb622327c82420/ConfigSpace/read_and_write/json.py#L705-L721

is never called, which should happen at https://github.com/automl/ConfigSpace/blob/ce27ba26e1cf27a5b9fe242519cb622327c82420/ConfigSpace/read_and_write/json.py#L678

Instead, https://github.com/automl/ConfigSpace/blob/ce27ba26e1cf27a5b9fe242519cb622327c82420/ConfigSpace/read_and_write/json.py#L683-L687 is called, which in turn causes the accession attempt of 'name', which is not present in the ForbiddenRelations clause

JosuaCarl commented 5 months ago

Replacing _construct_forbidden_equals with _construct_forbidden_relation in https://github.com/automl/ConfigSpace/blob/ce27ba26e1cf27a5b9fe242519cb622327c82420/ConfigSpace/read_and_write/json.py#L678 fixed my issue.

The bug also seemed to affect the read-in of the Runhistory in SMAC3, when using ForbiddenRelations, this also fixed it for me.

eddiebergman commented 5 months ago

Thanks for the issue and solution!

This has been addressed in #346 which we hope to release next week. I'm not sure when SMAC will udpdate to it as they'll likely want to benchmark that nothing is silently broken. That might take another little bit of time