我正在处理一些关于人的数据,这些数据包含几十个二进制特征,基本上可以归结为“这个人有特征x”[True/False]。
根据我在网上找到的信息,分类数据应该进行独热编码,而不是为每个类别分配一个任意值,因为你不能说“类别1小于类别2”。因此,解决方案是为每个类别创建一个虚拟变量:
Cat || dummy 1 | dummy 2 | dummy 3____||_________|_________|________ 1 || 1 | 0 | 0 2 || 0 | 1 | 0 3 || 0 | 0 | 1
现在对于二进制特征,可以选择直接使用变量(真为1,假为0),或者使用两个虚拟变量(真为(1, 0),假为(0, 1))。但我找不到任何来源显示/解释最佳方法是什么。
我自己也很矛盾,因为一方面,虚拟变量降低了每个独立变量的重要性,并且在某些情况下已显示模型的准确性会受到影响,来源。但另一方面,这也可以编码缺失数据(以(0, 0)的形式)。此外,能否说“假小于真”?
我实际上是在Python中使用随机森林,并且我知道基于树的分类器如随机森林支持分类数据,但Sklearn包尚未实现这一功能。
我在Sklearn的digits数据集上进行了一个小测试。这个数据集包含许多8×8的数字图像(0-9),每个像素的值在0到16之间,一个简单的模型可以使用这些数据来学习识别数字。
在我的测试中,我将值> 8更改为True,<= 8更改为False。与原始数据相比,准确性当然会受到影响,但当我实现独热编码,将True更改为(1, 0),False更改为(0, 1)时,我找不到与二进制编码相比的显著差异。
对推荐方法的解释将不胜感激!
回答:
将取值为[0, 1]的二进制变量转换为[(0, 1), (1, 0)]的独热编码是多余的,不建议这样做,原因如下(其中一些在上面的评论中已经提到,但只是为了进一步扩展):
-
这是多余的,因为二进制变量已经处于类似于独热编码的形式,其中最后一列被删除了,因为有它与没有它没有区别,因为它可以从第一列推断出来:如果我给你[(0, ), (1,)],你可以知道互补列[(, 1), (, 0)]。
-
假设你有多个二进制变量,例如4个。如果你将它们转换为独热编码形式,维度将从4增加到8。后者不推荐,原因如下:
-
维度灾难:高维数据可能非常麻烦。这是因为很多算法(例如聚类算法)使用欧几里得距离,由于平方项的存在,对噪声敏感。事实上,随着维度的增加,数据点会变得非常稀疏,使数据变得极其嘈杂。此外,邻域的概念变得毫无意义,基于寻找数据点之间距离相对对比的方法变得不可靠。
-
时间和内存复杂度:直观地,增加特征数量会使算法的执行时间和内存空间需求增加。举几个例子,使用协方差矩阵进行计算的算法会受到影响。多项式算法将结束于太多的项…等等。一般来说,特征较少时学习通常更快,尤其是如果额外的特征是多余的。
-
多重共线性:由于二进制变量的独热编码形式中的最后一列是多余的,并且与第一列100%相关,这将给基于线性回归的算法带来麻烦。例如,由于普通最小二乘估计涉及矩阵求逆,如果有很多特征是相关的,计算机算法可能无法成功获得近似逆,因此逆可能在数值上不准确。此外,线性模型通过观察在保持所有其他独立变量为常数的情况下,一个独立变量的单位变化对因变量
y
的变化进行观察,然而在独立变量高度相关的情况下,后者将失效(多重共线性的其他后果还有更多)(尽管其他一些算法可能对这一点不太敏感,如决策树)。 -
易过拟合:一般来说,太多特征(无论它们是否相关)可能会使你的模型过拟合,无法泛化到新的例子,因为数据集中每个数据点都会被给定的特征完全识别(搜索Andrew NG的讲座,他详细解释了这一点)
-
总结
总之,将二进制变量转换为独热编码是多余的,可能会导致不必要和不请自来的麻烦。虽然相关特征不总是会使你的模型变差,但它们也不会总是改善它。