ValueError: X имеет 29 функций на выборку; ожидая 84

Я работаю над сценарием, используя API-интерфейс Lending Club, чтобы предсказать, будет ли кредит «выплачиваться полностью» или «списываться». Для этого я использую scikit-learn для построения модели и продолжаю использовать joblib. Я столкнулся с ошибкой ValueError из-за разницы между количеством столбцов в сохраненной модели и количеством столбцов из новых необработанных данных. Ошибка ValueError возникает из-за создания фиктивных переменных для категориальных переменных. Количество столбцов, используемых в модели, равно 84, а в этом примере количество столбцов, использующих новые данные, равно 29.

Количество столбцов должно быть 84 для новых данных при создании фиктивных переменных, но я не уверен, как действовать, поскольку присутствует только подмножество всех возможных значений для категориальных переменных «homeOwnership», «addrState» и «цель». при получении новых данных из API.

Вот код, который я сейчас тестирую, начиная с момента, когда категориальные переменные преобразуются в фиктивные переменные, и заканчивая реализацией модели.

#......continued

df['mthsSinceLastDelinq'].notnull().astype('int')
df['mthsSinceLastRecord'].notnull().astype('int')
df['grade_num'] = df['grade'].map({'A':0,'B':1,'C':2,'D':3})
df['emp_length_num'] = df['empLength']
df = pd.get_dummies(df,columns=['homeOwnership','addrState','purpose'])
# df = pd.get_dummies(df,columns=['home_ownership','addr_state','verification_status','purpose'])

# step 3.5 transform data before making predictions

df.drop(['id','grade','empLength','isIncV'],axis=1,inplace=True)
dfbcd = df[df['grade_num'] != 0]
scaler = StandardScaler()
x_scbcd = scaler.fit_transform(dfbcd)

# step 4 predicting

lrbcd_test = load('lrbcd_test.joblib')
ypredbcdfinal = lrbcd_test.predict(x_scbcd)

Вот сообщение об ошибке

ValueError                                Traceback (most recent call last)
<ipython-input-239-c99611b2e48a> in <module>
     11 # change name of model and file name
     12 lrbcd_test = load('lrbcd_test.joblib')
---> 13 ypredbcdfinal = lrbcd_test.predict(x_scbcd)
     14 
     15     #add model

~\Anaconda3\lib\site-packages\sklearn\linear_model\base.py in predict(self, X)
    287             Predicted class label per sample.
    288         """
--> 289         scores = self.decision_function(X)
    290         if len(scores.shape) == 1:
    291             indices = (scores > 0).astype(np.int)

~\Anaconda3\lib\site-packages\sklearn\linear_model\base.py in decision_function(self, X)
    268         if X.shape[1] != n_features:
    269             raise ValueError("X has %d features per sample; expecting %d"
--> 270                              % (X.shape[1], n_features))
    271 
    272         scores = safe_sparse_dot(X, self.coef_.T,

ValueError: X has 29 features per sample; expecting 84

person jz451    schedule 10.08.2019    source источник


Ответы (3)


Ваши новые данные должны иметь те же столбцы, что и данные, которые вы использовали для обучения и сохранения исходной модели. И если количество уникальных значений категориальных переменных меньше в более новых данных, вручную добавьте столбцы для этих переменных после выполнения pd.get_dummies() и установите их равными нулю для всех точек данных.

Модель будет работать только тогда, когда она наберет необходимое количество столбцов. Если pd.get_dummies не может создать все эти столбцы для новых данных, вы должны сделать это вручную.

Редактировать

Если вы хотите автоматически вставить отсутствующие столбцы после шага pd.get_dummies(), вы можете использовать следующий подход. Предполагая, что df_newdata — это кадр данных после применения pd.get_dummies() к новому набору данных, а df_olddata — это df, который вы получили, когда применили pd.get_dummies() к старому набору данных (который использовался для обучения), вы можете просто сделать это :

df_newdata = df_newdata.reindex(labels=df_olddata.columns,axis=1)

Это автоматически создаст отсутствующие столбцы в df_newdata (по сравнению с df_olddata) и установит значения этих столбцов в NaN для всех строк. Итак, теперь ваш новый фрейм данных имеет те же столбцы ext, что и исходный фрейм данных.

Надеюсь это поможет

person Amit    schedule 12.08.2019
comment
Переменные для новых данных одинаковы, когда API вызывается как данные, используемые при обучении/тестировании, но pd.get_dummies/onehotencoder, очевидно, не вставляет столбцы для значений, не входящих в новые данные. Делать это вручную не получится, так как я пытаюсь автоматизировать процесс. Чего я не знаю, так это как создать недостающие столбцы простым способом. - person jz451; 14.08.2019
comment
Я думал о чем-то подобном, чтобы создать необходимые столбцы, но пытался получить ответ более эффективным способом, не используя грубую силу. Тем более что каждый раз мне нужно будет создавать более 40 столбцов. Должен быть какой-то способ справиться с этим, поскольку большинство моделей будут иметь дело с фиктивным кодированием, но до сих пор не нашли решения. - person jz451; 16.08.2019

Не могли бы вы попробовать использовать метод transform объекта x_scbcd [объект StandardScaler] для вашего объекта данных тестирования lrbcd_test? Это создаст функциональное представление ваших данных тестирования.

ypredbcdfinal = lrbcd_test.predict(x_scbcd.transform(x_scbcd))
person Nidhin Bose J.    schedule 10.08.2019
comment
Попробовал ваше предложение, но получил следующую ошибку: AttributeError: объект «numpy.ndarray» не имеет атрибута «преобразование». Также я попытался сохранить и загрузить скалер, используемый во время обучения/тестирования, и получил эту ошибку: ValueError: операнды не могут быть переданы вместе с формами (3,26) (84,) (3,26). - person jz451; 10.08.2019

Используйте только Transform вместо fit_transform. Это должно сработать. Надеюсь, поможет.

    x_scbcd = scaler.transform(dfbcd)
person Sherin Jayanand    schedule 13.01.2020