Я пытаюсь создать свой собственный метод сохранения и загрузки моделей Sklearn DecisionTreeRegressor в и из JSON. Сортировка моделей больше не является хорошим вариантом, так как я столкнулся с проблемами совместимости с файлами pickle. Моя работа основана на уроке Себастьяна Рашки: http://nbviewer.jupyter.org/github/rasbt/python-machine-learning-book/blob/master/code/bonus/scikit-model-to-json.ipynb
Я столкнулся с проблемой некоторых атрибутов модели, доступных только для чтения, при попытке присвоить им значения. Похоже, они были настроены таким образом в родительском классе.
class DecisionTreeRegressor_json(DecisionTreeRegressor):
def save_json(self):
# create main parameter dictionary
list_main_exclude = ['_get_param_names', '_validate_X_predict', 'apply', 'fit',
'fit_transform', 'get_params', 'predict', 'presort', 'splitter',
'tree_', 'decision_path', 'score', 'set_params', 'transform', '_save_json_w_ndarray',
'save_json', 'load_json', '_set_params']
list_main = [i for i in dir(self) if not i.endswith('__') and
not i.startswith('_abc') and not i in list_main_exclude]
attrs_main = {i: getattr(self, i) for i in list_main}
# create tree parameter dictionary
list_tree_exclude = ['apply', 'compute_feature_importances', 'decision_path', 'predict']
list_tree = [i for i in dir(self.tree_) if not i.endswith('__') and not i in list_tree_exclude]
attrs_tree = {i: getattr(self.tree_, i) for i in list_tree}
# dump dictionaries to json
with codecs.open(medir + '/params.json', 'w', encoding='utf-8') as outfile:
self._save_json_w_ndarray(attrs_main, outfile)
with codecs.open(medir + '/tree.json', 'w', encoding='utf-8') as outfile:
self._save_json_w_ndarray(attrs_tree, outfile)
def _save_json_w_ndarray(self, dict, outfile):
for k in dict:
if isinstance(dict[k], np.ndarray):
dict[k] = dict[k].tolist()
json.dump(dict,
outfile,
separators=(',', ':'),
sort_keys=True,
indent=4)
def load_json(self):
dtr = DecisionTreeRegressor()
main_text = codecs.open(medir + '/params.json', 'r', encoding='utf-8').read()
tree_text = codecs.open(medir + '/tree.json', 'r', encoding='utf-8').read()
main_params = json.loads(main_text)
tree_params = json.loads(tree_text)
self._set_params(self, **main_params)
self.tree_ = Tree(tree_params['n_features'], np.array(tree_params['n_classes']), tree_params['n_outputs'])
self._set_params(self.tree_, **tree_params)
def _set_params(self, obj, **param_dict):
for k in param_dict:
print k
print param_dict[k]
if isinstance(param_dict[k], list):
setattr(obj, k, np.array(param_dict[k]))
else:
setattr(obj, k, param_dict[k])
Один из атрибутов, которые я не могу изменить, это «feature_importances_», который имеет тип ndarray. Если я загружаю рассол, атрибут получает ожидаемый массив numpy. Как рассол делает это? Как я могу сделать это для JSON?
Вот как выглядит подобранный объект модели, который я пытаюсь воссоздать из JSON:
реж (объект)
Ошибка при попытке установить "feature_importances _":
setattr (obj, k, np.array (param_dict [k]))
AttributeError: невозможно установить атрибут