Skip to content
This repository has been archived by the owner on Sep 18, 2024. It is now read-only.

Commit

Permalink
Support convert nested dict in TPE (#1023)
Browse files Browse the repository at this point in the history
  • Loading branch information
PurityFan authored and chicm-ms committed Apr 28, 2019
1 parent 2ea753a commit a850be4
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 26 deletions.
2 changes: 2 additions & 0 deletions docs/en_US/Builtin_Tuner.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ tuner:

> Builtin Tuner Name: **SMAC**

**Please note that SMAC doesn't support running on windows currently. The specific reason can be referred to this [github issue](https://github.com/automl/SMAC3/issues/483).**

**Installation**

SMAC need to be installed by following command before first use.
Expand Down
2 changes: 1 addition & 1 deletion examples/trials/mnist-cascading-search-space/mnist.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ def parse_init_json(data):
if value == 'Empty':
params[key] = ['Empty']
else:
params[key] = [value[0], value[1]['_value'], value[1]['_value']]
params[key] = [value[0], value[1], value[1]]
return params


Expand Down
13 changes: 12 additions & 1 deletion examples/trials/mnist-cascading-search-space/sample.json
Original file line number Diff line number Diff line change
@@ -1 +1,12 @@
{"layer2": "Empty", "layer8": ["Conv", {"_index": 0, "_value": 2}], "layer3": ["Avg_pool", {"_index": 2, "_value": 5}], "layer0": ["Max_pool", {"_index": 2, "_value": 5}], "layer1": ["Conv", {"_index": 0, "_value": 2}], "layer6": ["Max_pool", {"_index": 1, "_value": 3}], "layer7": ["Max_pool", {"_index": 2, "_value": 5}], "layer9": ["Conv", {"_index": 0, "_value": 2}], "layer4": ["Avg_pool", {"_index": 1, "_value": 3}], "layer5": ["Avg_pool", {"_index": 2, "_value": 5}]}
{
"layer2": "Empty",
"layer8": ["Conv", 2],
"layer3": ["Avg_pool", 5],
"layer0": ["Max_pool", 5],
"layer1": ["Conv", 2],
"layer6": ["Max_pool", 3],
"layer7": ["Max_pool", 5],
"layer9": ["Conv", 2],
"layer4": ["Avg_pool", 3],
"layer5": ["Avg_pool", 5]
}
58 changes: 34 additions & 24 deletions src/sdk/pynni/nni/hyperopt_tuner/hyperopt_tuner.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,40 +139,50 @@ def json2vals(in_x, vals, out_y, name=ROOT):
for i, temp in enumerate(in_x):
json2vals(temp, vals[i], out_y, name + '[%d]' % i)

def params2tuner_params(in_x, parameter):
def _add_index(in_x, parameter):
"""
change parameters in NNI format to parameters in hyperopt format.
For example, NNI receive parameters like:
change parameters in NNI format to parameters in hyperopt format(This function also support nested dict.).
For example, receive parameters like:
{'dropout_rate': 0.8, 'conv_size': 3, 'hidden_size': 512}
Will change to format in hyperopt, like:
{'dropout_rate': 0.8, 'conv_size': {'_index': 1, '_value': 3}, 'hidden_size': {'_index': 1, '_value': 512}}
"""
tuner_params = dict()
for key in parameter.keys():
value = parameter[key]
_type = in_x[key][TYPE]
if _type == 'choice':
_idx = in_x[key][VALUE].index(value)
tuner_params[key] = {
INDEX: _idx,
VALUE: value
}
if TYPE not in in_x: # if at the top level
out_y = dict()
for key, value in parameter.items():
out_y[key] = _add_index(in_x[key], value)
return out_y
elif isinstance(in_x, dict):
value_type = in_x[TYPE]
value_format = in_x[VALUE]
if value_type == "choice":
choice_name = parameter[0] if isinstance(parameter, list) else parameter
for pos, item in enumerate(value_format): # here value_format is a list
if isinstance(item, list): # this format is ["choice_key", format_dict]
choice_key = item[0]
choice_value_format = item[1]
if choice_key == choice_name:
return {INDEX: pos, VALUE: [choice_name, _add_index(choice_value_format, parameter[1])]}
elif choice_name == item:
return {INDEX: pos, VALUE: item}
else:
tuner_params[key] = value
return tuner_params
return parameter

def _split_index(params):
"""
Delete index infromation from params
"""
result = {}
for key in params:
if isinstance(params[key], dict):
value = params[key][VALUE]
else:
value = params[key]
result[key] = value
return result
if isinstance(params, list):
return [params[0], _split_index(params[1])]
elif isinstance(params, dict):
if INDEX in params.keys():
return _split_index(params[VALUE])
result = dict()
for key in params:
result[key] = _split_index(params[key])
return result
else:
return params


class HyperoptTuner(Tuner):
Expand Down Expand Up @@ -399,6 +409,6 @@ def import_data(self, data):
continue
self.supplement_data_num += 1
_parameter_id = '_'.join(["ImportData", str(self.supplement_data_num)])
self.total_data[_parameter_id] = params2tuner_params(self.json, _params)
self.total_data[_parameter_id] = _add_index(in_x=self.json, parameter=_params)
self.receive_trial_result(parameter_id=_parameter_id, parameters=_params, value=_value)
logger.info("Successfully import data to TPE/Anneal tuner.")

0 comments on commit a850be4

Please sign in to comment.