大家好。我在开发一个机器学习模型时产生了一个疑问。假设我的训练数据如下所示:
ID | 动物 | 年龄 | 栖息地
0 | 鱼 | 2 | 海洋
1 | 鹰 | 1 | 山区
2 | 鱼 | 3 | 海洋
3 | 蛇 | 4 | 森林
如果我应用独热编码,它会生成以下矩阵:
ID | 动物_鱼 | 动物_鹰 | 动物_蛇 | 年龄 | …
0 | 1 | 0 | 0 | 2 | …
1 | 0 | 1 | 0 | 1 | …
2 | 1 | 0 | 0 | 3 | …
3 | 0 | 0 | 1 | 4 | …
这在大多数情况下都很好用。但是,如果我的测试集包含的特征比训练集少(或多)怎么办?如果我的测试集中没有“鱼”呢?它会生成一个少一个类别的矩阵。
你们能帮我解决这种问题吗?
谢谢
回答:
听起来你的训练集和测试集是完全分开的。以下是一个如何自动向给定数据集添加“缺失”特征的最小示例:
import pandas as pd# 虚构的训练数据集train = pd.DataFrame({'animal': ['cat', 'cat', 'dog', 'dog', 'fish', 'fish', 'bear'], 'age': [12, 13, 31, 12, 12, 32, 90]})# 虚构的测试数据集(注意训练集中有两个类别在测试集中完全缺失)test = pd.DataFrame({'animal': ['fish', 'fish', 'dog'], 'age': [15, 62, 1]})# 要进行独热编码的离散列col = 'animal'# 为`col`的每个级别创建虚拟变量train_animal_dummies = pd.get_dummies(train[col], prefix=col)train = train.join(train_animal_dummies)test_animal_dummies = pd.get_dummies(test[col], prefix=col)test = test.join(test_animal_dummies)# 找出两个数据集之间的列差异# 这在简单情况下有效,但如果你只想限制到一个特征# 使用这个:f = lambda c: col in c; feature_difference = set(filter(f, train)) - set(filter(f, test))feature_difference = set(train) - set(test)# 创建一个零填充矩阵,其中行数等于`test`的行数# 列数等于缺失的类别数(即相关`train`和`test`列之间的集合差异)feature_difference_df = pd.DataFrame(data=np.zeros((test.shape[0], len(feature_difference))), columns=list(feature_difference))# 将“缺失”的特征添加回`testtest = test.join(feature_difference_df)
test
从这个:
age animal animal_dog animal_fish0 15 fish 0.0 1.01 62 fish 0.0 1.02 1 dog 1.0 0.0
变成这个:
age animal animal_dog animal_fish animal_cat animal_bear0 15 fish 0.0 1.0 0.0 0.01 62 fish 0.0 1.0 0.0 0.02 1 dog 1.0 0.0 0.0 0.0
假设每行(每种动物)只能是一种动物,我们可以添加一个animal_bear
特征(一种“是否是熊”的测试/特征),因为我们假设如果test
中有熊,那信息会在animal
列中体现。
作为一个经验法则,在构建/训练模型时,尽量考虑所有可能的特征(例如,animal
的所有可能值)是个好主意。正如评论中提到的,一些方法比其他方法更能处理缺失数据,但如果从一开始就能做到这一点,那可能是最好的。现在,如果你接受的是自由文本输入(因为可能的输入数量是无穷的),这将很难做到。