Трубопроводный прогноз X имеет другую форму, чем при установке - PullRequest
0 голосов
/ 07 мая 2018

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

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

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 имеет другую форму, чем во время подгонки.

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

Я думаю, что что-то упустил.

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

1 Ответ

0 голосов
/ 07 мая 2018

Это, похоже, проблема с вашим процессом "выбора / создания функции". Вы переустанавливаете 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())
...