pyspark OneHotEncoded向量似乎缺少类别?

时间:2018-07-31 01:09:13

标签: pyspark apache-spark-mllib

在尝试使用pyspark的OneHotEncoderhttps://spark.apache.org/docs/2.1.0/ml-features.html#onehotencoder)为分类特征生成一热编码矢量时看到一个奇怪的问题,其中一热矢量似乎缺少某些类别(或者可能格式奇怪)显示时?)。

现在回答了这个问题(或提供了 答案)后,下面的详细信息似乎与理解问题并不完全相关

具有以下形式的数据集

1. Wife's age                     (numerical)
2. Wife's education               (categorical)      1=low, 2, 3, 4=high
3. Husband's education            (categorical)      1=low, 2, 3, 4=high
4. Number of children ever born   (numerical)
5. Wife's religion                (binary)           0=Non-Islam, 1=Islam
6. Wife's now working?            (binary)           0=Yes, 1=No
7. Husband's occupation           (categorical)      1, 2, 3, 4
8. Standard-of-living index       (categorical)      1=low, 2, 3, 4=high
9. Media exposure                 (binary)           0=Good, 1=Not good
10. Contraceptive method used     (class attribute)  1=No-use, 2=Long-term, 3=Short-term  

实际数据类似于

wife_age,wife_edu,husband_edu,num_children,wife_religion,wife_working,husband_occupation,SoL_index,media_exposure,contraceptive
24,2,3,3,1,1,2,3,0,1
45,1,3,10,1,1,3,4,0,1

来源:https://archive.ics.uci.edu/ml/datasets/Contraceptive+Method+Choice

在对数据进行了其他一些预处理之后,然后尝试通过...将分类和二进制(仅出于实践目的)特征编码为1hot向量。

for inds in ['wife_edu', 'husband_edu', 'husband_occupation', 'SoL_index', 'wife_religion', 'wife_working', 'media_exposure', 'contraceptive']:
    encoder = OneHotEncoder(inputCol=inds, outputCol='%s_1hot' % inds)
    print encoder.k
    dataset = encoder.transform(dataset)

产生的行看起来像

Row(
    ...., 
    numeric_features=DenseVector([24.0, 3.0]), numeric_features_normalized=DenseVector([-1.0378, -0.1108]), 
    wife_edu_1hot=SparseVector(4, {2: 1.0}), 
    husband_edu_1hot=SparseVector(4, {3: 1.0}), 
    husband_occupation_1hot=SparseVector(4, {2: 1.0}), 
    SoL_index_1hot=SparseVector(4, {3: 1.0}), 
    wife_religion_1hot=SparseVector(1, {0: 1.0}),
    wife_working_1hot=SparseVector(1, {0: 1.0}),
    media_exposure_1hot=SparseVector(1, {0: 1.0}),
    contraceptive_1hot=SparseVector(2, {0: 1.0})
)

我对稀疏矢量格式的理解是SparseVector(S, {i1: v1}, {i2: v2}, ..., {in: vn})表示一个长度为S的矢量,其中所有值都是0,期望索引i1,...具有对应的值v1,...,vn({ {3}})。

基于此,看来在 this 情况下的SparseVector实际上表示矢量中的最高索引(而不是大小)。此外,结合所有功能(通过pyspark的VectorAssembler)并检查所得dataset.head(n=1)向量的数组版本是否显示

input_features=SparseVector(23, {0: -1.0378, 1: -0.1108, 4: 1.0, 9: 1.0, 12: 1.0, 17: 1.0, 18: 1.0, 19: 1.0, 20: 1.0, 21: 1.0})

indicates a vector looking like

indices:  0        1       2  3  4...           9        12             17 18 19 20 21
        [-1.0378, -0.1108, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0]

我认为应该不可能有一个大于等于3个连续1s的序列(如在上述向量的尾部附近可以看到的那样),因为这将表明一个热门向量(例如中间向量) 1)的大小仅为1,对于任何数据功能都没有意义。

对于机器学习的东西来说是新手,所以这里可能对一些基本概念感到困惑,但是有人知道这里会发生什么吗?

1 个答案:

答案 0 :(得分:0)

在pyspark文档(https://spark.apache.org/docs/2.1.0/api/python/pyspark.ml.html#pyspark.ml.feature.OneHotEncoder)中发现了这一点:

  

...具有5个类别,输入值2.0将映射到[0.0,0.0,1.0,0.0]的输出向量。 默认情况下不包括最后一个类别(可通过dropLast进行配置),因为它使向量项的总和为1,因此线性相关。因此输入值4.0映射为[0.0,0.0,0.0,0.0]。

可以在此处(http://www.algosome.com/articles/dummy-variable-trap-regression.html和此处(https://stats.stackexchange.com/q/290526/167299)中找到有关为什么要进行最后一类丢弃的更多讨论。

我对任何类型的机器学习都是相当陌生的,但基本上(对于回归模型而言)删除最后一个分类值是为了避免发生称为dummy variable trap的事情,其中​​“自变量是多重共线性的,在这种情况下,两个或多个变量高度相关;简单来说,一个变量可以从其他变量中预测出来”(因此,基本上,您将具有冗余功能(我认为这对加权a不利。 ML模型))。

例如。当[isBoy, isGirl, unspecified]的编码可以传达有关某人性别的相同信息时,则不需要[isBoy, isGirl]的1hot编码,此处为[1,0]=isBoy[0,1]=isGirl[0,0]=unspecified

此链接(http://www.algosome.com/articles/dummy-variable-trap-regression.html)提供了一个很好的例子,结论是

  

伪变量陷阱的解决方案是删除分类变量之一(或者删除截距常量)-如果存在m个类别,则在模型中使用m-1,则可以忽略掉值被认为是参考值,其余类别的拟合值表示此参考的更改。

**注意:在寻找原始问题的答案时,找到了类似的SO帖子(Why does Spark's OneHotEncoder drop the last category by default?)。但是,我认为,由于提到的帖子是关于为什么的行为,而本帖子即将与最初发生的事情相混淆,因此当前的帖子值得存在>,以及当前的问题标题在粘贴到Google时找不到所提到的帖子的事实。