训练集和测试集上的不同标签编码值是不好的吗?

3
在我的数据集中,我有一个名为“product”的分类特征。假设在训练集中,其值为{"apple", "banana", "durian", "orange",....}。另一方面,在测试集中,现在的值可以是{"banana", "orange", pineapple"}。有一些值在训练集中没有(例如pineapple)。
我知道如果我们事先拥有所有可能的值,我们可以创建一个标签编码变量,并使用特征可以有的所有值对其进行fit。但在这种情况下,我无法确保训练集可以涵盖测试集中的所有值(即当出现一些新产品时)。
这让我非常担心,因为我担心在使用标签编码时,训练集可能会被映射为{"apple": 1, "banana": 2, "durian": 3, "orange": 4, ... (还有数千个) },但是当映射到测试集时,我们将得到{"banana": 1, "orange":2 , pineapple":3}
我的问题是:
    1. 这对分类模型有负面影响吗?例如,如果apple成为product特征中的重要值,据我所知,模型将更关注1apple的数字值)。当在测试集1banana时,这是否会误导?
    1. 是否有任何方法可以处理训练集和测试集上具有不同值的标签编码问题?
我发现一些相关的链接,如这个链接,但它并不完全是我的问题。
更新:请注意,product可能有数千个值,这就是为什么我在这里使用标签编码而不是独热编码
2个回答

4
您需要在将分类变量输入到机器学习模型中时使用 独热编码。否则,模型将会把苹果 < 香蕉 < 榴莲 < 橘子这样的顺序作为事实,但实际上并非如此。
对于测试数据集中出现的未知值,该变量的所有列都将为零,这最终会使模型理解该值在训练期间未被观察到。
X= [["apple"], ["banana"], ["durian"], ["orange"]]
from sklearn.preprocessing import OneHotEncoder
enc = OneHotEncoder(handle_unknown='ignore')
enc.fit(X)

enc.categories_

分类:

[array(['apple', 'banana', 'durian', 'orange'], dtype=object)]

在测试数据期间,

enc.transform([["banana"], ["orange"], ["pineapple"]]).toarray()

输出:

array([[0., 1., 0., 0.],
       [0., 0., 0., 1.],
       [0., 0., 0., 0.]])

1
谢谢。我明白你的意思了。在我的情况下,product 这个特征可能有成千上万个值,所以我认为使用独热编码会创建太多的列,这对模型来说很难处理。在一些分类模型中,比如决策树,当我们将类别转换为数字(比如标签编码方法)时,模型仍然可以进行分割,这意味着它仍然有用,对吗? - undefined
它可以处理。一个更好的方法可能是,在使用sklearn.feature_selection创建独热向量后,选择有用的类别,然后在最终模型中使用它。 - undefined

2
如果我处在你的位置,我会使用一个字典来作为训练数据。同样的字典也会用于测试数据中。可能会出现测试数据中有一些值/单词是训练数据没有遇到过的情况。我会使用一个特殊的索引名为未知标记来处理这些情况。因此,我的字典将是: {"UNK":0, "apple": 1, "banana": 2, "durian": 3, "orange": 4}
然后对于测试数据{"banana, orange , pineapple"},我会得到{2,4,0}。
希望这对你有所帮助。

谢谢你的有用建议。我会尝试一下。听起来很合理 :)。那第一个问题呢?你认为使用不同的标签编码器会让分类模型感到困惑吗? - undefined
1
我认为是的。因为训练时的编码和测试时的编码使用了不同的字典,所以会预测错误的值/标签。另外一件事: 你可以按照单词出现的频率对训练字典进行排序。然后将字典限制在一个合理的大小范围内。比如说,你可以剔除字典中出现次数少于3次的单词。这样可以提高分类的准确性,因为不常见的单词会导致数据稀疏。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接