Pipeline预测时X的形状与拟合时不同

我遇到了这个错误,我理解它的含义,但不知道如何处理它。

这是我所做的:

class PreProcessing(BaseEstimator, TransformerMixin):  def __init__(self):    pass  def transform(self, df):   #在这里我选择特征并进行转换,例如:   age_band=0   if age<=10     age_band=1   else #... 到90岁     age_band=9   ....   其他特征工程   ....   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 selfpipe = 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("模型已加载...现在进行预测...")predictions = loaded_model.predict(df)

我得到了错误:ValueError: X的形状与拟合时不同。

我理解的是,在我的“真实文件”中,并非所有模态都被表示,因为想象一下,在我的训练文件中,我有“couple”列,值为“yes, no, I don’t know”,那么ce.BinaryEncoder将创建所需的列数来以二进制形式存储所有模态。但在我的实际生活文件中,我需要进行预测的“couple”列只有“yes, no”这两个值。所以最终,X的形状与拟合时不同…所以我假设要做的唯一一件事是在PreProcessing中为所有缺失的模态创建值为0的列…

我觉得我错过了什么。

注意:训练和测试文件来自某个数据源。我需要预测的数据来自另一个源,所以我首先将这些实际数据“转换”为与X_train/Test相同的格式,然后我执行model.predict(df)。所以我确定在BinaryEncoder之前,我在Preprocessing.transform()中有相同数量的列(17),但在BinaryEncoder执行之后,如果我在运行model.predict(X_test)时记录df的形状,它显示df有41列,而在model.predict(realData)时只有31列。


回答:

这似乎是你的“特征选择/创建”过程中的一个问题。你每次向管道传递一组新的输入时,都会重新拟合一个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):    # ...    # 仅转换,不拟合    df = self.encoder.transform(df)    return df

更好的是,你能否直接将BinaryEncoder插入到你的Pipeline中,完全不使用PreProcessing

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

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注