什么是 One-Hot 编码?
在机器学习中,一般需要对非数值型的特征进行编码处理,将其转化为数值型的特征。其中,One-Hot 编码是一种常见的特征编码方式。
One-Hot 编码是将一个离散特征的每个取值映射为一个唯一的整数编号,并将该编号表示成一个二进制向量的形式。具体来说,对于一个有
k
k
k 个不同取值的离散特征,其 One-Hot 编码将会得到一个
k
k
k 维的向量,其中只有一个元素为
1
,其余元素为
0
,该元素的下标对应着特征取值的编号。
例如,对于一个颜色特征,其可能的取值为红、绿、蓝三种,可以将其编码为:
- 红色:
[1, 0, 0]
- 绿色:
[0, 1, 0]
- 蓝色:
[0, 0, 1]
为什么需要 One-Hot 编码?
One-Hot 编码主要用于将离散特征转化为数值特征,并且避免了特征之间的大小关系,方便在机器学习模型中使用。
- 避免数值型特征带来的大小关系:如果对于一个本质上是离散的特征,使用数值型的编码方式,就可能会导致不同取值之间带来了大小关系,这可能会影响机器学习模型的训练效果。而使用 One-Hot 编码,每个取值都是独立的,不存在大小关系,不会对模型产生影响。
- 方便使用分类器:在机器学习中,一些分类器(比如决策树、支持向量机等)需要将数据转换为数值型的输入,One-Hot 编码可以将离散特征转换为数值特征,方便这些分类器进行训练和预测。
- 增加特征的独立性:在一些情况下,原始的离散特征可能存在相关性,One-Hot 编码可以将这些特征转化为互相独立的数值特征,便于在模型中使用。
需要注意的是,对于具有大量不同取值的离散特征,进行 One-Hot 编码可能会导致特征维度爆炸,影响模型的训练效率和性能。在这种情况下,可以考虑使用其他特征编码方式,比如哈希编码。
Spark ML 之 One-Hot
在 Spark MLlib 中,我们通过 OneHotEncoder 特征转换器,用于将类别特征转换为二元向量,其实现基于 One-Hot 编码,将每个类别特征映射到唯一的整数索引,并将索引编码为二元向量。该转换器适用于逻辑回归、朴素贝叶斯等需要数值特征作为输入的算法。
OneHotEncoder 转换器有两个主要参数:
inputCol
:需要转换为二元向量的输入列名。outputCol
:转换后的二元向量输出列名。
那么什么是二元向量呢?
二元向量是指只包含两个元素的向量。在数学中,一个二元向量可以表示为
(
x
,
y
)
(x, y)
(x,y),其中
x
x
x 和
y
y
y 是向量的两个分量。这样的向量也可以被看作是二维坐标系中的一个点,其中
x
x
x 和
y
y
y 分别表示该点在
x
x
x 轴和
y
y
y 轴上的坐标。
在机器学习和数据分析中,二元向量通常被用来表示二元特征,例如某个物品是否被购买,某个用户是否点击了某个广告等等。在这种情况下,向量的两个分量通常分别表示某个特征的取值为
0
或
1
。
Spark ML 应用示例
在
maven
中引入 Spark ML 的依赖。
<dependency><groupId>org.apache.spark</groupId><artifactId>spark-mllib_2.12</artifactId><version>3.0.0</version></dependency>
1.创建
SparkSession
对象
val spark: SparkSession = SparkSession
.builder().master("local[*]").appName("One_Hot").getOrCreate()
2.创建一个示例数据集,格式为 DataFrame
importspark.implicits._
val data: DataFrame = Seq((0,"red"),(1,"blue"),(2,"green"),(3,"red"),(4,"red"),(5,"blue")).toDF("id","color")
生成了一个包含
"id"
和
"color"
两个字段的 DataFrame。其中
"color"
是一个字符串类型的类别特征,包括
"red"
、
"blue"
和
"green"
三种取值。
3.创建
StringIndexer
对象,对特征进行索引编码
val indexer: StringIndexerModel =new StringIndexer().setInputCol("color").setOutputCol("index_color").fit(data)val indexData: DataFrame = indexer.transform(data)
该编码会将
"color"
特征中的三种取值分别编码为
0
、
1
和
2
。
StringIndexer 是 Spark 中常用的一种特征工程模型,它的作用是将字符串类型的特征值转换成数值类型的特征值。在机器学习和数据分析中,通常需要将非数值类型的特征值转换成数值类型,这样才能够使用各种算法进行训练和预测等等。
StringIndexer 可以将某个字符串特征的所有取值按照出现的次数进行排序,并为每个取值分配一个整数编号,从而将字符串类型的特征值转换成整数类型的特征值。
例如,如果某个字符串特征的取值为
["cat", "dog", "bird", "dog", "cat"]
,那么经过 StringIndexer 处理后,取值
"cat"
将被编号为
0
,
"dog"
将被编号为
1
,
"bird"
将被编号为
2
,转换后的特征值为
[0, 1, 2, 1, 0]
(出现次数一样会按照 ASCII 码等规则进行编号)。
4.使用 OneHotEncoder 对特征进行 One-Hot 编码
val encoder: OneHotEncoder =new OneHotEncoder().setInputCol("index_color").setOutputCol("encoded_color").setDropLast(false)val encoderModel: OneHotEncoderModel = encoder.fit(indexData)val encoderData: DataFrame = encoderModel.transform(indexData)
将编码后的
"index_color"
特征作为输入,将输出列设置为
"encoded_color"
,对其进行 One-Hot 编码,并保留每个特征中的所有取值。
这意味着对于
"color"
特征,由于有三种取值,因此编码后的结果会生成一个长度为
3
的向量,其中每个元素对应一种取值,元素值为
1
表示该取值出现,为
0
表示该取值未出现。
setDropLast
是 OneHotEncoder 类的一个方法,它用于设置是否省略最后一个编码值,其默认值为
true
。
如果将setDropLast
设置为
false
,则会为每个不同的类别创建一个编码列,这样最后一个类别将具有全部
1
的编码向量。如果将其设置为
true
,则会为每个不同的类别创建一个编码列,但最后一个编码列将被省略。
5.输出结果
encoderData.show(false)
输出结果如下所示:
+---+-----+-----------+-------------+|id |color|index_color|encoded_color|+---+-----+-----------+-------------+|0|red |0.0|(3,[0],[1.0])||1|blue |1.0|(3,[1],[1.0])||2|green|2.0|(3,[2],[1.0])||3|red |0.0|(3,[0],[1.0])||4|red |0.0|(3,[0],[1.0])||5|blue |1.0|(3,[1],[1.0])|+---+-----+-----------+-------------+
encoded_color
列是进行 One-Hot 编码完成后的特征向量。
我们拿 ID 为
0
的数据来对
encoded_color
列进行说明,即:
(3,[0],[1.0])
,解析如下:
3
表示特征数量,即:red
、blue
、green
。[0]
表示特征的编码,这里red
的编码为0
。[1.0]
表示该列是否为red
(其它列对应其它的颜色),1
表示是,0
表示否。
6.进行向量拆分
encoderData.withColumn("new_encoded_color",vector_to_array(col("encoded_color"))).show(false)
结果如下:
+---+-----+-----------+-------------+-----------------+|id |color|index_color|encoded_color|new_encoded_color|+---+-----+-----------+-------------+-----------------+|0|red |0.0|(3,[0],[1.0])|[1.0,0.0,0.0]||1|blue |1.0|(3,[1],[1.0])|[0.0,1.0,0.0]||2|green|2.0|(3,[2],[1.0])|[0.0,0.0,1.0]||3|red |0.0|(3,[0],[1.0])|[1.0,0.0,0.0]||4|red |0.0|(3,[0],[1.0])|[1.0,0.0,0.0]||5|blue |1.0|(3,[1],[1.0])|[0.0,1.0,0.0]|+---+-----+-----------+-------------+-----------------+
我们拿 ID 为
0
的数据来对
encoded_color
、
new_encoded_color
列进行说明,它们的值分别为:
(3,[0],[1.0])
、
[1.0, 0.0, 0.0]
。
这里主要说明
new_encoded_color
列数据,可以发现,对 One-Hot 特征向量结果
encoded_color
进行转换后,结果为
[1.0, 0.0, 0.0]
,它分别对应着
[red,blue,green]
。
那么为什么是这个顺序呢?这就要提到我们上面的特征编码了,因为它是按照 StringIndexer 编码后的顺序进行排列的。
从数据中可以看出, ID 为
0
的数据属于
red
,而不属于其它两个特征,所以结果为:
[1.0, 0.0, 0.0]
。
One-Hot 编码,仅此而已。
版权归原作者 月亮给我抄代码 所有, 如有侵权,请联系我们删除。