scikit-learn:如果经过一次热编码后新数据的特征少于 training/testing 集,如何预测新数据

scikit-learn: how to predict new data if after one hot encoding it has fewer features than the training/testing sets

我正在尝试在我的第一个 ML 项目中使用 scikit-learn,将其 DecisionTreeClassifier 与包含数字和分类特征的数据样本一起使用,例如: ['High', 33, 'No', 4].

我已经可以做到了。

  1. 从 .csv 文件读取训练和测试数据。

    physio = pd.read_csv('data.csv', header=None, names=['HR', 'M', 'T', 'W', 'D'])

  2. 提取目标class:
    labels = physio.pop('D')

  3. 使用 pandas.get_dummies 对分类特征进行一次性热编码。这也将特征数量从 4 增加到 6(因为 'HR' 和 'T' 分别变为 'HR_High'/'HR_Low' 和 'T_Yes'/'T_No') )

    for col in physio.dtypes[physio.dtypes == 'object'].index:
        for_dummy = physio.pop(col)
        physio = pd.concat([physio, pd.get_dummies(for_dummy, prefix=col)], axis=1)
    
  4. 将集合拆分为训练和测试子集。

    x_train, x_test, y_train, y_test = train_test_split(physio, labels, test_size=0.25)
    
  5. 实例化并拟合树

    dt = DecisionTreeClassifier(max_depth=8, min_samples_split=.3, min_samples_leaf=.26, max_features=4)
    dt.fit(x_train, y_train)
    
  6. 在第一次测试拆分中对测试集进行分类

    y_pred = dt.predict(x_test)
    
  7. 并使用y_testy_pred使用混淆矩阵(也是ROC的AUC)评估class化

    conf_matrix = confusion_matrix(y_true=y_test, y_pred=y_pred, labels=['Yes', 'No'])
    

如果我使用了错误的术语,我很抱歉,但是,现在我正在尝试做这一切应该做的事情,即 class 验证传入数据,不幸的是,这就是我见过的所有教程都不尽如人意,一旦所有拆分、训练和测试都发生了,它们就永远不会涉及class验证新数据的过程。

我天真的尝试过的方式:

  1. 由于实际数据将来自命令行参数,我想我会将它们存储在一个数组中并将其传递给 DataFrame。

    newSample = [['Low', 2, 'No', 8]]
    newSampleDF = pd.DataFrame(newSample, columns=['HR', 'M', 'T', 'W'])
    
  2. 然后我尝试对其进行单热编码。这就是问题所在,因为编码完成后,仍然有 4 个特征,因为只是一个数据样本,它不知道 'High' 和 'Yes',所以 'HR' 和'T'就分别变成了'HR_Low'和'T_No'

    for col in newSampleDF.dtypes[newSampleDF.dtypes == 'object'].index:
        for_dummy = newSampleDF.pop(col)
        newSampleDF = pd.concat([newSampleDF, pd.get_dummies(for_dummy, prefix=col)], axis=1)
    

当我打印 newSampleDF 时,它显示:

M  W  HR_Low  T_No
2  8    1      1

而我尝试class验证它的数据是

 M   W  HR_High  HR_Low  T_No  T_Yes
12  48     0       1      0      1

这就是我收到错误的原因:

ValueError:模型的特征数必须与输入匹配。模型n_features为6,输入n_features为4

这是不言自明的,我只是不知道如何解决。如何让我的新数据以 意识到 缺失值的方式进行编码,在本例中为 'High' 和 'Yes'。

我希望我说得有道理,请随时指出错误和改进,但请记住,这里是初学者。

谢谢

我认为整个方法有点问题。我们不需要使用 pd.get_dummies,因为我们已经知道类别列。那么为什么我们不直接使用呢?

因此我更喜欢如下解决方案:

import pandas as pd

cats = ["HR", "T"]

training_data = pd.DataFrame([[12, 48, 0, 1, 0, 1]], columns=["M","W", "HR_High", "HR_Low", "T_No", "T_Yes"])

raw_cols = ['HR', 'M', 'T', 'W']
newSample = [['Low', 2, 'No', 8]]
newSampleDF = pd.DataFrame(newSample, columns=raw_cols)

cols = ["M","W", "HR_High", "HR_Low", "T_No", "T_Yes"]
template = pd.DataFrame([6 * [None]], columns=cols)

for col in raw_cols:
    if col in cats:
        template.loc[0, col + "_" + newSampleDF.loc[0, col]] = 1
    else:
        template.loc[0, col] = newSampleDF.loc[0, col]

# replace Nans with 0
newSampleDF = template.fillna(0)
print(newSampleDF)

输出:

   M  W  HR_High  HR_Low  T_No  T_Yes
0  2  8        0       1     1      0