새로운 기능을 수용 (또는 무시)하여 ML 모델 (피클 파일)을 더 강력하게 만들 수 있습니까?

Nov 19 2020
  • ML 모델을 훈련하고 Pickle 파일에 저장했습니다.
  • 새 대본에서 나는 예측을하고 싶은 새로운 '실제 데이터'를 읽고 있습니다.

그러나 나는 고군분투하고있다. 다음과 같은 열 (문자열 값 포함)이 있습니다.

Sex       
Male       
Female
# This is just as example, in real it is having much more unique values

이제 문제가 발생합니다. 새로운 (고유) 값을 받았는데 이제 더 이상 예측을 할 수 없습니다 (예 : 'Neutral'추가됨).

'Sex'컬럼을 Dummies로 변환하기 때문에 모델이 더 이상 입력을 받아들이지 않는다는 문제가 있습니다.

모델의 기능 수가 입력과 일치해야합니다. 모델 n_features는 2이고 입력 n_features는 3입니다.

따라서 내 질문 : 내 모델을 견고하게 만들고이 클래스를 무시할 수있는 방법이 있습니까? 그러나 특정 정보없이 예측을합니까?

내가 시도한 것 :

df = pd.read_csv('dataset_that_i_want_to_predict.csv')
model = pickle.load(open("model_trained.sav", 'rb'))

# I have an 'example_df' containing just 1 row of training data (this is exactly what the model needs)
example_df = pd.read_csv('reading_one_row_of_trainings_data.csv')

# Checking for missing columns, and adding that to the new dataset 
missing_cols = set(example_df.columns) - set(df.columns)
for column in missing_cols:
    df[column] = 0 #adding the missing columns, with 0 values (Which is ok. since everything is dummy)

# make sure that we have the same order 
df = df[example_df.columns] 

# The prediction will lead to an error!
results = model.predict(df)

# ValueError: Number of features of the model must match the input. Model n_features is X and n_features is Y

참고로 검색했지만 유용한 솔루션을 찾을 수 없습니다 ( 여기 , 여기 또는 여기가 아님).

최신 정보

이 기사 도 찾았습니다 . 하지만 여기서도 같은 문제입니다. 학습 세트와 동일한 열로 테스트 세트를 만들 수 있습니다.하지만 새로운 실제 데이터 (예 : 새로운 값 'Neutral')는 어떻습니까?

답변

7 Venkatachalam Nov 23 2020 at 07:56

예, 학습 부분이 완료된 후에는 새 카테고리 또는 기능을 데이터 세트에 포함 (모델 업데이트) 할 수 없습니다. OneHotEncoder테스트 데이터의 일부 기능 내에 새 카테고리가있는 문제를 처리 할 수 ​​있습니다. 범주 형 변수와 관련하여 학습 및 테스트 데이터에서 열을 일관되게 유지합니다.

from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import OneHotEncoder
import numpy as np
import pandas as pd
from sklearn import set_config
set_config(print_changed_only=True)
df = pd.DataFrame({'feature_1': np.random.rand(20),
                   'feature_2': np.random.choice(['male', 'female'], (20,))})
target = pd.Series(np.random.choice(['yes', 'no'], (20,)))

model = Pipeline([('preprocess',
                   ColumnTransformer([('ohe',
                                       OneHotEncoder(handle_unknown='ignore'), [1])],
                                       remainder='passthrough')),
                  ('lr', LogisticRegression())])

model.fit(df, target)

# let us introduce new categories in feature_2 in test data
test_df = pd.DataFrame({'feature_1': np.random.rand(20),
                        'feature_2': np.random.choice(['male', 'female', 'neutral', 'unknown'], (20,))})
model.predict(test_df)
# array(['yes', 'yes', 'yes', 'yes', 'yes', 'yes', 'yes', 'yes', 'yes',
#       'yes', 'yes', 'yes', 'yes', 'yes', 'yes', 'yes', 'yes', 'yes',
#       'yes', 'yes'], dtype=object)