机器学习,如何理解sklearn的独热编码器OneHotEncoder?
发布于 作者:苏南大叔 来源:程序如此灵动~
在本文中,苏南大叔准备讲解一下sklearn比较常用的独热编码器,英文名是OneHotEncoder。独热编码主要用于分类特征的各个取值之间是无序的情况,各种特征之间理论上并没有顺序或者大小的关系。但是为了机器学习,可能还是需要把这些特征的取值进行数字化。

苏南大叔的“程序如此灵动”博客,记录苏南大叔的编程学习故事。本文测试环境:win10,python@3.12.0,scikit-learn@1.3.2。
独热编码器
下面的内容是网络上关于One-Hot编码的解释:
One-Hot编码,又称为一位有效编码,主要是采用N位状态寄存器来对N个状态进行编码,每个状态都由他独立的寄存器位,并且在任意时候只有一位有效。
One-Hot编码是分类变量作为二进制向量的表示。这首先要求将分类值映射到整数值。然后,每个整数值被表示为二进制向量,除了整数的索引之外,它都是零值,它被标记为1。
苏南大叔的理解上:
- 不同的特征值越多,所需要的值长度越多。有多少特征值,就会有多长的编码结果。
- 某个特征的最终编码结果里面,位数为
count(所有特征值),其中只有一个为1,其余都是0。 - 所有特征值按顺序排序后,其编码结果也是有规律的。
1【从左到右】依次转移。 - 随着特征值的不断增多,编码结果也会不断变化,其结果也会大量增加。所以...
测试代码
from sklearn import preprocessing
one = preprocessing.OneHotEncoder()
X = [
["老许", 3, "cat"],
["虎子", 5, "dog"],
# ["二赖子", 3, "dog"],
# ["老白", 8, "cat"],
# ["小黑", 10, "dog"],
]
one.fit(X)
print(one.transform([["虎子",5,"dog"]]).toarray())
# [[0. 1. 0. 1. 0. 1.]]
print(one.transform([["老许",5,"dog"]]).toarray())
# [[1. 0. 0. 1. 0. 1.]]
print(one.inverse_transform([[1,0,0,1,0,1]])) # [['老许' 5 'dog']]字典功能属性 .categories_
虽然没有.classes_属性,但是存在一个类似的.categories_属性。
# print(one.classes_) # 'OneHotEncoder' object has no attribute 'classes_'
print(one.categories_)输出:
[
array(['老许', '虎子'], dtype=object),
array([3, 5], dtype=object),
array(['cat', 'dog'], dtype=object)
]输出项 toarray()
这种OneHotEncoder的编码结果实际是:
a = one.transform([["虎子",5,"dog"]])
print(a,type(a))输出:
(0, 1) 1.0
(0, 3) 1.0
(0, 5) 1.0 <class 'scipy.sparse._csr.csr_matrix'>但是通过.toarray()才能看到以前其它编码器的类似结果。
b = one.transform([["虎子",5,"dog"]]).toarray()
print(b,type(b))输出:
[[0. 1. 0. 1. 0. 1.]] <class 'numpy.ndarray'>这个scipy.sparse._csr.csr_matrix类型,留到后续文章说明。
编码顺序
这里的编码顺序,很显然还是按照unicode编码的数字来排序的。
| 第几列特征 | 特征值 | unicode数字 | 独特编码 |
|---|---|---|---|
| 第一列 | [老]许 | 32769 | 10 |
| 第一列 | [虎]子 | 34382 | 01 |
| 第二列 | 3 | 51 | 10 |
| 第二列 | 5 | 53 | 01 |
| 第三列 | [c]at | 99 | 10 |
| 第三列 | [d]og | 100 | 01 |
输入项
输入只接受二维数组,不接受一维向量。可以接受二维list/二维ndarray/dataframe。但是,输入是二维ndarray或者dataframe的话,可能会面临变量类型转换的问题。例如:
from sklearn import preprocessing
one = preprocessing.OneHotEncoder()
X = [
["老许", 3, "cat"],
["虎子", 5, "dog"],
]
##########################
# 注意这里有转化
##########################
one.fit(X)
print(one.transform([["虎子",5,"dog"]]).toarray())转化为ndarray:
import numpy as np
X = np.array(X)转化为dataframe:
import pandas as pd
X = pd.DataFrame(X)都会报错:
ValueError: Found unknown categories ['5'] in column 1 during transform实际上就是数字5被强制转化为字符串5,所导致的问题。但是,这并不是说dataframe或者ndarray不能转化为独热。而是可能会有一些类型上的变化,可能会做一些简单的变化。
其它结论
- 输入只接受二维数组,不接受一维向量。可以接受二维
list/二维ndarray/dataframe。 - 既然输入项是二维的,则一样不存在
.classes_了。会报错: - 这个
OneHotEncoder的编码结果可以翻转,倒是很意外的事情。毕竟0和1的组合还是很多的。
后续内容
如果某一列定义了CategoricalDtype,那么独热码结果还是会有较大的变化。这种情况待后续补充。
相关文章
结语
苏南大叔的更多sklearn的机器学习文章,请参考苏南大叔的文章: