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].
我已经可以做到了。
从 .csv 文件读取训练和测试数据。
physio = pd.read_csv('data.csv', header=None, names=['HR', 'M', 'T', 'W', 'D'])
提取目标class:
labels = physio.pop('D')
使用 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)
将集合拆分为训练和测试子集。
x_train, x_test, y_train, y_test = train_test_split(physio, labels, test_size=0.25)
实例化并拟合树
dt = DecisionTreeClassifier(max_depth=8, min_samples_split=.3, min_samples_leaf=.26, max_features=4)
dt.fit(x_train, y_train)
在第一次测试拆分中对测试集进行分类
y_pred = dt.predict(x_test)
并使用y_test
和y_pred
使用混淆矩阵(也是ROC的AUC)评估class化
conf_matrix = confusion_matrix(y_true=y_test, y_pred=y_pred, labels=['Yes', 'No'])
如果我使用了错误的术语,我很抱歉,但是,现在我正在尝试做这一切应该做的事情,即 class 验证传入数据,不幸的是,这就是我见过的所有教程都不尽如人意,一旦所有拆分、训练和测试都发生了,它们就永远不会涉及class验证新数据的过程。
我天真的尝试过的方式:
由于实际数据将来自命令行参数,我想我会将它们存储在一个数组中并将其传递给 DataFrame。
newSample = [['Low', 2, 'No', 8]]
newSampleDF = pd.DataFrame(newSample, columns=['HR', 'M', 'T', 'W'])
然后我尝试对其进行单热编码。这就是问题所在,因为编码完成后,仍然有 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
我正在尝试在我的第一个 ML 项目中使用 scikit-learn,将其 DecisionTreeClassifier
与包含数字和分类特征的数据样本一起使用,例如: ['High', 33, 'No', 4].
我已经可以做到了。
从 .csv 文件读取训练和测试数据。
physio = pd.read_csv('data.csv', header=None, names=['HR', 'M', 'T', 'W', 'D'])
提取目标class:
labels = physio.pop('D')
使用
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)
将集合拆分为训练和测试子集。
x_train, x_test, y_train, y_test = train_test_split(physio, labels, test_size=0.25)
实例化并拟合树
dt = DecisionTreeClassifier(max_depth=8, min_samples_split=.3, min_samples_leaf=.26, max_features=4) dt.fit(x_train, y_train)
在第一次测试拆分中对测试集进行分类
y_pred = dt.predict(x_test)
并使用
y_test
和y_pred
使用混淆矩阵(也是ROC的AUC)评估class化conf_matrix = confusion_matrix(y_true=y_test, y_pred=y_pred, labels=['Yes', 'No'])
如果我使用了错误的术语,我很抱歉,但是,现在我正在尝试做这一切应该做的事情,即 class 验证传入数据,不幸的是,这就是我见过的所有教程都不尽如人意,一旦所有拆分、训练和测试都发生了,它们就永远不会涉及class验证新数据的过程。
我天真的尝试过的方式:
由于实际数据将来自命令行参数,我想我会将它们存储在一个数组中并将其传递给 DataFrame。
newSample = [['Low', 2, 'No', 8]] newSampleDF = pd.DataFrame(newSample, columns=['HR', 'M', 'T', 'W'])
然后我尝试对其进行单热编码。这就是问题所在,因为编码完成后,仍然有 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