19

我想了解 Spark 的 OneHotEncoder 默认删除最后一个类别的原因。

例如:

>>> fd = spark.createDataFrame( [(1.0, "a"), (1.5, "a"), (10.0, "b"), (3.2, "c")], ["x","c"])
>>> ss = StringIndexer(inputCol="c",outputCol="c_idx")
>>> ff = ss.fit(fd).transform(fd)
>>> ff.show()
+----+---+-----+
|   x|  c|c_idx|
+----+---+-----+
| 1.0|  a|  0.0|
| 1.5|  a|  0.0|
|10.0|  b|  1.0|
| 3.2|  c|  2.0|
+----+---+-----+

默认情况下,OneHotEncoder 将丢弃最后一个类别:

>>> oe = OneHotEncoder(inputCol="c_idx",outputCol="c_idx_vec")
>>> fe = oe.transform(ff)
>>> fe.show()
+----+---+-----+-------------+
|   x|  c|c_idx|    c_idx_vec|
+----+---+-----+-------------+
| 1.0|  a|  0.0|(2,[0],[1.0])|
| 1.5|  a|  0.0|(2,[0],[1.0])|
|10.0|  b|  1.0|(2,[1],[1.0])|
| 3.2|  c|  2.0|    (2,[],[])|
+----+---+-----+-------------+

当然,这种行为是可以改变的:

>>> oe.setDropLast(False)
>>> fl = oe.transform(ff)
>>> fl.show()
+----+---+-----+-------------+
|   x|  c|c_idx|    c_idx_vec|
+----+---+-----+-------------+
| 1.0|  a|  0.0|(3,[0],[1.0])|
| 1.5|  a|  0.0|(3,[0],[1.0])|
|10.0|  b|  1.0|(3,[1],[1.0])|
| 3.2|  c|  2.0|(3,[2],[1.0])|
+----+---+-----+-------------+

问题::

  • 在什么情况下需要默认行为?
  • 盲目调用可能会忽略哪些问题setDropLast(False)
  • 作者在文档中的以下陈述是什么意思?

默认情况下不包括最后一个类别(可通过 dropLast 配置),因为它使向量条目总和为 1,因此线性相关。

4

1 回答 1

11

根据文档,它是保持列独立:

一种单热编码器,将一列类别索引映射到一列二进制向量,每行最多有一个单值表示输入类别索引。例如,对于 5 个类别,输入值 2.0 将映射到 [0.0, 0.0, 1.0, 0.0] 的输出向量。默认情况下不包括最后一个类别(可通过 OneHotEncoder!.dropLast 配置,因为它使向量条目总和为 1,因此线性相关。因此输入值 4.0 映射到 [0.0, 0.0, 0.0, 0.0]。注意这与 scikit-learn 的 OneHotEncoder 不同,OneHotEncoder 保留所有类别。输出向量是稀疏的。

https://spark.apache.org/docs/1.5.2/api/java/org/apache/spark/ml/feature/OneHotEncoder.html

于 2017-03-23T11:27:08.863 回答