ValueError:X 每个样本有 29 个特征;期待 84
Posted
技术标签:
【中文标题】ValueError:X 每个样本有 29 个特征;期待 84【英文标题】:ValueError: X has 29 features per sample; expecting 84 【发布时间】:2019-12-17 16:28:40 【问题描述】:我正在编写一个脚本,使用 Lending Club API 来预测一笔贷款是“全额支付”还是“注销”。为此,我使用 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
【问题讨论】:
【参考方案1】:您的新数据应该与您用于训练和保留原始模型的数据具有完全相同的列。如果新数据中分类变量的唯一值数量较少,请在执行 pd.get_dummies() 后手动为这些变量添加列,并将所有数据点的列设置为零。
模型只有在获得所需的列数时才会起作用。如果 pd.get_dummies 未能在较新的数据上创建所有这些列,您应该手动进行。
编辑
如果您想在 pd.get_dummies() 步骤之后自动插入缺失的列,可以使用以下方法。 假设 df_newdata 是在新数据集上应用 pd.get_dummies() 后的数据帧,而 df_olddata 是在旧数据集(用于训练)上应用 pd.get_dummies() 时得到的 df,您可以简单地执行此操作:
df_newdata = df_newdata.reindex(labels=df_olddata.columns,axis=1)
这将自动在 df_newdata 中创建缺失的列(与 df_olddata 相比),并将所有行的这些列的值设置为 NaN。所以现在,您的新数据框具有与原始数据框相同的 exct 列。
希望对你有帮助
【讨论】:
新数据的变量在调用 API 作为训练/测试中使用的数据时是相同的,但是 pd.get_dummies/onehotencoder 显然不会为不在新数据中的值插入列.由于我正在尝试自动化该过程,因此手动执行此操作将不起作用。我不知道的是如何以简单的方式创建缺失的列。 我已经想到了类似的方法来创建必要的列,但试图获得一种不使用蛮力的更有效方式的响应。特别是因为我每次都需要创建超过 40 列。必须有某种方法来解决这个问题,因为大多数模型都会处理虚拟编码,但到目前为止还没有找到解决方案。【参考方案2】:只使用 Transform 而不是 fit_transform。这应该可以解决问题。希望对您有所帮助。
x_scbcd = scaler.transform(dfbcd)
【讨论】:
【参考方案3】:您能否尝试在您的测试数据对象lrbcd_test
上使用x_scbcd
[StandardScaler 对象] 的transform
方法?这将为您的测试数据创建一个特征表示。
ypredbcdfinal = lrbcd_test.predict(x_scbcd.transform(x_scbcd))
【讨论】:
尝试了您的建议,但收到以下错误:AttributeError: 'numpy.ndarray' object has no attribute 'transform'。此外,我尝试持久化并加载在训练/测试期间使用的缩放器并收到此错误:ValueError: operands could not be broadcast together with shapes (3,26) (84,) (3,26)。以上是关于ValueError:X 每个样本有 29 个特征;期待 84的主要内容,如果未能解决你的问题,请参考以下文章
ValueError:X每个样本具有231个特征;期待1228
ValueError:发现样本数量不一致的输入变量:[1, 74]
ValueError:检查输入时出错:预期 lstm_16_input 有 3 个维度,但得到的数组形状为 (836, 400, 3, 1)