Присвоение значений атрибутам только для чтения при десериализации объектов модели sklearn с использованием json - PullRequest
0 голосов
/ 13 мая 2018

Я пытаюсь создать свой собственный метод сохранения и загрузки моделей 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: невозможно установить атрибут

...