Я пытаюсь создать графики частичной зависимости, используя sklearn.inspection.plot_partial_dependence
для модели, которую я успешно построил, используя keras и утилиту-оболочку keras sklearn (см. Блок кода ниже). Обернутая модель успешно строится, она может использовать метод подгонки, а после подгонки она может использовать метод прогнозирования с ожидаемыми результатами. Все признаки того, что это действительная оценка. Однако, когда я пытаюсь запустить plot_partial_dependence от sklearn.inspection, я получаю некоторый текст ошибки, подразумевающий, что это не допустимая оценка, хотя я могу продемонстрировать, что это так.
I Я отредактировал это так, чтобы его было легче воспроизвести с помощью примера склеарна с данными о жилье в Бостоне.
from sklearn.datasets import load_boston
from sklearn.inspection import plot_partial_dependence, partial_dependence
from keras.wrappers.scikit_learn import KerasRegressor
import keras
import tensorflow as tf
import pandas as pd
boston = load_boston()
feature_names = boston.feature_names
X = pd.DataFrame(boston.data, columns=boston.feature_names)
y = boston.target
mean = X.describe().transpose()['mean']
std = X.describe().transpose()['std']
X_norm = (X-mean)/std
def build_model_small():
model = keras.Sequential([
keras.layers.Dense(64, activation='relu', input_shape=[len(X.keys())]),
keras.layers.Dense(64, activation='relu'),
keras.layers.Dense(1)
])
optimizer = keras.optimizers.RMSprop(0.0005)
model.compile(loss='mse',
optimizer=optimizer,
metrics=['mae', 'mse', 'mape'])
return model
kr = KerasRegressor(build_fn=build_model_small,verbose=0)
kr.fit(X_norm,y, epochs=100, validation_split = 0.2)
pdp_plot = plot_partial_dependence(kr,X_norm,feature_names)
Как я уже сказал, если я запускаю kr.predict(X.head(20))
, я получаю 20 предсказаний значений y
для первых 20 строки X
, как и следовало ожидать от действительного оценщика.
Но текст ошибки, который я получаю от plot_partial_dependence, выглядит следующим образом:
Traceback (most recent call last):
File "temp_ML_tf_sklearn_postproc.py", line 79, in <module>
pdp_plot = plot_partial_dependence(kr,X,labels[:-1])
File "/home/mymachine/anaconda3/lib/python3.7/site-packages/sklearn/inspection/_partial_dependence.py", line 678, in plot_partial_dependence
for fxs in features)
File "/home/mymachine/anaconda3/lib/python3.7/site-packages/joblib/parallel.py", line 921, in __call__
if self.dispatch_one_batch(iterator):
File "/home/mymachine/anaconda3/lib/python3.7/site-packages/joblib/parallel.py", line 759, in dispatch_one_batch
self._dispatch(tasks)
File "/home/mymachine/anaconda3/lib/python3.7/site-packages/joblib/parallel.py", line 716, in _dispatch
job = self._backend.apply_async(batch, callback=cb)
File "/home/mymachine/anaconda3/lib/python3.7/site-packages/joblib/_parallel_backends.py", line 182, in apply_async
result = ImmediateResult(func)
File "/home/mymachine/anaconda3/lib/python3.7/site-packages/joblib/_parallel_backends.py", line 549, in __init__
self.results = batch()
File "/home/mymachine/anaconda3/lib/python3.7/site-packages/joblib/parallel.py", line 225, in __call__
for func, args, kwargs in self.items]
File "/home/mymachine/anaconda3/lib/python3.7/site-packages/joblib/parallel.py", line 225, in <listcomp>
for func, args, kwargs in self.items]
File "/home/mymachine/anaconda3/lib/python3.7/site-packages/sklearn/inspection/_partial_dependence.py", line 307, in partial_dependence
"'estimator' must be a fitted regressor or classifier."
ValueError: 'estimator' must be a fitted regressor or classifier.
Я посмотрел исходный код для plot_partial_dependence и он должен был сказать следующее. Во-первых, в строке документации написано, что первый вход estimator
должен быть ...
A fitted estimator object implementing :term:`predict`,
:term:`predict_proba`, or :term:`decision_function`.
Multioutput-multiclass classifiers are not supported.
Мой оценщик делает на самом деле реализацию .predict.
Второй строка, вызванная в трассировке errr, вызывает средство проверки, которое проверяет, является ли оно регрессором или классификатором:
if not (is_classifier(estimator) or is_regressor(estimator)):
raise ValueError(
"'estimator' must be a fitted regressor or classifier."
)
Я посмотрел исходный код is_regressor (), и он похож на один строчный :
return getattr(estimator, "_estimator_type", None) == "regressor"
Поэтому я попытался взломать его, выполнив setattr(mp,'_estimator_type','regressor')
, и он просто сказал Attribute Error: can't set attribute
, так что это один дешевый обходной путь, который не сработал.
Я даже попробовал еще более хакерское исправление и временно закомментировал оскорбительную проверку в источнике _partial_dependence.py (оператор if, который я скопировал выше), и получил следующую ошибку:
Traceback (most recent call last):
File "temp_ML_tf_sklearn_postproc.py", line 79, in <module>
pdp_plot = plot_partial_dependence(kr,X,labels[:-1])
File "/home/billy/anaconda3/lib/python3.7/site-packages/sklearn/inspection/_partial_dependence.py", line 678, in plot_partial_dependence
for fxs in features)
File "/home/billy/anaconda3/lib/python3.7/site-packages/joblib/parallel.py", line 921, in __call__
if self.dispatch_one_batch(iterator):
File "/home/billy/anaconda3/lib/python3.7/site-packages/joblib/parallel.py", line 759, in dispatch_one_batch
self._dispatch(tasks)
File "/home/billy/anaconda3/lib/python3.7/site-packages/joblib/parallel.py", line 716, in _dispatch
job = self._backend.apply_async(batch, callback=cb)
File "/home/billy/anaconda3/lib/python3.7/site-packages/joblib/_parallel_backends.py", line 182, in apply_async
result = ImmediateResult(func)
File "/home/billy/anaconda3/lib/python3.7/site-packages/joblib/_parallel_backends.py", line 549, in __init__
self.results = batch()
File "/home/billy/anaconda3/lib/python3.7/site-packages/joblib/parallel.py", line 225, in __call__
for func, args, kwargs in self.items]
File "/home/billy/anaconda3/lib/python3.7/site-packages/joblib/parallel.py", line 225, in <listcomp>
for func, args, kwargs in self.items]
File "/home/billy/anaconda3/lib/python3.7/site-packages/sklearn/inspection/_partial_dependence.py", line 317, in partial_dependence
check_is_fitted(est)
File "/home/billy/anaconda3/lib/python3.7/site-packages/sklearn/utils/validation.py", line 967, in check_is_fitted
raise NotFittedError(msg % {'name': type(estimator).__name__})
sklearn.exceptions.NotFittedError: This KerasRegressor instance is not fitted yet. Call 'fit' with appropriate arguments before using this estimator.
, которая повторяется к проблеме функций склеарна, не думая, что эта модель подходит, когда она действительно есть. В любом случае, в этот момент я решил не пытаться использовать более опасные, хакерские исправления, связанные с манипулированием исходным кодом.
Я также попытался передать kr.fit(X,y,etc...)
непосредственно в качестве первого аргумента plot_partial_dependence. Компьютер вращался в течение нескольких минут, показывая, что на самом деле выполнялась подгонка, но затем я получил ту же ошибку, когда попытался запустить график частичной зависимости.
Еще одна довольно запутанная подсказка. Я попытался полностью использовать конвейер keras / sklearn в другой функции sklearn, чтобы посмотреть, будет ли он работать с какими-либо утилитами sklearn. На этот раз я сделал:
from sklearn.model_selection import cross_validate
cv_scores = cross_validate(kr,X_norm,y, cv=4, return_train_score=True, n_jobs=-1)`
, и это сработало! Так что я не думаю, что с моим использованием keras.wrappers.scikit_learn.KerasRegressor
.
что-то не так по своей сути. Это может быть просто случай, когда я пытаюсь сделать крайний случай, не запланированный в источнике plot_partial_dependence конкретный код, и мне не повезло, но мне интересно, видел ли кто-либо еще подобные проблемы и есть ли решение или обходной путь.
Я использую sklearn 0.22.1 и Python 3.7 .3 (Анаконда) кстати. И чтобы было ясно, я использовал plot_partial_dependence на моделях, построенных на sklearn, и даже на конвейерах. Эта проблема возникает только с моделью на основе керас. Большое спасибо за любые комментарии, которые могут иметь люди.
Редактировать:
Предыдущая версия этого вопроса включала построение конвейера с помощью StandardScaler () и затем обернутого объекта KerasRegressor. С тех пор я обнаружил, что это происходит даже с одним объектом KerasRegressor, то есть я выделил проблему, а не конвейер. Поэтому, как предложил один из комментаторов, я исключил часть конвейера, чтобы сделать его проще и ближе к делу.