Прогноз X конвейера имеет другую форму, чем во время подгонки

Я застрял с этой ошибкой, я понимаю ее значение, но не знаю, как с ней бороться.

Вот что я делаю:

class PreProcessing(BaseEstimator, TransformerMixin):
  def __init__(self):
    pass

  def transform(self, df):

   #Here i select the features and transform them for exemple:
   age_band=0
   if age<=10
     age_band=1
   else #... etc to 90
     age_band=9
   ....
   other feature engineering
   ....
   encoder = ce.BinaryEncoder(cols=selectedCols)
   encoder.fit(df)
   df = encoder.transform(df)

   return df.as_matrix()

  def fit(self, df, y=None, **fit_params):

    return self

pipe = make_pipeline(PreProcessing(),
                     SelectKBest(f_classif,k=23),
                    RandomForestClassifier())

param_grid = {"randomforestclassifier__n_estimators" : [100,400],
              "randomforestclassifier__max_depth" : [None],
              "randomforestclassifier__max_leaf_nodes": [2,3,5], 
              "randomforestclassifier__min_samples_leaf":[3,5,8],
              "randomforestclassifier__class_weight":['balanced'],
              "randomforestclassifier__n_jobs":[-1]
             }

grid_search = GridSearchCV(pipe,param_grid,cv=5,scoring='recall',verbose=1,n_jobs=15)

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

grid_search.fit(X_train,y_train)
grid_search.predict(X_test)

filename = 'myModel.pk'
with open(filename, 'wb') as file:
    pickle.dump(grid_search, file)

Так что здесь все работает как шарм. Но с данными реального мира: (не файлы тестов поезда)

modelfile = 'MyModel.pk'
with open(modelfile,'rb') as f:
    loaded_model = pickle.load(f)

print("The model has been loaded...doing predictions now...")
predictions = loaded_model.predict(df)

Я получил ошибку: ValueError: X имеет другую форму, чем при подгонке.

Я понимаю, что не все модальности представлены в моем «реальном файле», потому что представьте, что в моем файле поезда у меня есть столбец «пара» со значениями «да, нет, я не знаю», тогда ce.BinaryEncoder создаст столько столбцов, сколько необходимо для хранения всех модальностей в двоичном формате. Но в моем реальном жизненном файле, который я должен делать прогнозы, у меня есть только для этих "парных" значений столбца "да, нет" Итак, в конце X не имеет той же формы, что и во время подгонки ... Итак, единственный то, что я предполагаю сделать, - это создать в PreProcessing все отсутствующие модальности со значением cols 0 ...

Думаю, что-то упускаю.

Примечание: обучающие и тестовые файлы взяты из определенного источника данных. Данные, которые мне нужно предсказать, взяты из другого источника, поэтому я сначала "преобразую" реальные данные в тот же формат X_train / Test, а затем выполняю model.predit (df). Итак, я уверен, что до BinaryEncoder у меня такое же количество столбцов (17) в Preprocessing.transform (), но после BinaryEncoder выполняется, если я регистрирую форму df во время работы model.predict (X_test) показывает, что df составляет 41 столбец, а в model.predict (realData) только 31 столбец.


person rednight    schedule 07.05.2018    source источник
comment
Для получения дополнительных сведений я следовал этому руководству: analyticsvidhya.com/blog/2017/09/   -  person rednight    schedule 07.05.2018


Ответы (1)


Похоже, это проблема с вашим процессом "выбора / создания функций". Вы переустанавливаете BinaryEncoder каждый раз, когда в ваш конвейер передается новый набор входных данных. Это означает, что каждый раз, когда у вас есть другое количество уникальных значений в указанном столбце, ваш код сломается с этой ошибкой.

Я предполагаю, что если вы сохраните BinaryEncoder как часть экземпляра PreProcessing, это не будет проблемой, при условии, что ваши обучающие данные имеют все возможные значения, которые может принимать этот столбец.

class PreProcessing(BaseEstimator, TransformerMixin):
  def __init__(self):
    self.encoder = ce.BinaryEncoder(cols=selectedCols)

  def fit(self, df, **kwargs):
    self.encoder.fit(df)

  def transform(self, df):
    # ...
    # No fitting, just transform
    df = self.encoder.transform(df)
    return df

А еще лучше, не могли бы вы просто вставить BinaryEncoder в свой конвейер и полностью исключить его из PreProcessing?

pipe = make_pipeline(PreProcessing(),
                     BinaryEncoder(cols=selectedCols),
                     SelectKBest(f_classif,k=23),
                     RandomForestClassifier())
person scnerd    schedule 07.05.2018
comment
Хорошо, я попробую оба, спасибо! Я действительно не знаю, выполняю ли я стандартный процесс, все, что мне нужно, это конвейер, который принимает данные строки, преобразует их в формат Xtrain, двоичный (потому что это лучшее, что я нашел во время моего исследования и статистики), выберите 23 лучших ( это тоже оптимизированное число), а затем используйте регрессор. - person rednight; 07.05.2018
comment
Хорошо, тогда первое решение не работает, потому что я создаю несколько новых столбцов в преобразовании, например age_band, поэтому я не могу использовать BinaryEncoder (cols = ['Age_band', ...]) и encoder.fit (df) в моем Preprocess.fit () Потому что Age_band col еще не существует. Второе решение, похоже, работает, я пробую разные случаи, похоже, он выполняет свою работу. Спасибо ! - person rednight; 08.05.2018