Scikit-learn Python机器学习 - 类别特征提取- OneHotEncoder
锋哥原创的Scikit-learn Python机器学习视频教程:
2026版 Scikit-learn Python机器学习 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili
课程介绍
本课程主要讲解基于Scikit-learn的Python机器学习知识,包括机器学习概述,特征工程(数据集,特征抽取,特征预处理,特征降维等),分类算法(K-临近算法,朴素贝叶斯算法,决策树等),回归与聚类算法(线性回归,欠拟合,逻辑回归与二分类,K-means算法)等。
类别特征提取- OneHotEncoder
用于处理离散的、无序的类别特征(如国家、颜色、品牌)。它将每个类别特征转换为一个二进制列(0/1)。
独热编码OneHotEncoder:将一个有 N
个不同取值的类别型特征,转换为 N
个二进制特征(0或1)。对于原始特征的每一个样本值,只有对应的那个新特征是 1(“热”),其他所有新特征都是 0(“冷”)。
“独热”这个名字非常形象地描述了它的形式:在众多位中,只有一位是“热”的(1),其余都是“冷”的(0)。
简单举例:我们将 "动物"
这一个特征,扩展为三个新的二进制特征:"是否是猫"
、"是否是狗"
、"是否是兔子"
。
样本 | 动物(原始) | 是否是猫 | 是否是狗 | 是否是兔子 |
---|---|---|---|---|
1 | 猫 | 1 | 0 | 0 |
2 | 狗 | 0 | 1 | 0 |
3 | 兔子 | 0 | 0 | 1 |
4 | 狗 | 0 | 1 | 0 |
这样,对于“猫”这个类别,它的向量表示就是 [1, 0, 0]
;“狗”是 [0, 1, 0]
;“兔子”是 [0, 0, 1]
。这三个向量在数学空间中是相互正交的,完全没有顺序或大小关系,完美地表达了类别之间的独立性。
核心参数详解
-
categories
(默认‘auto’
)
-
作用: 指定每个特征(列)有哪些类别(唯一值)。
-
可选值:
-
‘auto’
(默认): 自动从训练集数据中推断每个特征的类别。这是最常用的模式。 -
‘list’
: 手动指定。需要一个列表的列表,其中每个内部列表对应一个特征的类别。-
例如:
categories=[['猫', '狗'], ['红', '蓝']]
表示第一个特征有‘猫’和‘狗’两个类别,第二个特征有‘红’和‘蓝’两个类别。
-
-
-
为什么重要:
-
确保训练集和测试集编码的维度一致。如果测试集出现了训练集中从未见过的类别(‘未知’类别),
handle_unknown
参数会决定如何处理。 -
手动指定可以固定编码的维度,即使某些类别在训练集中没有出现。
-
-
drop
(默认None
)
-
作用: 指定一种方法来“丢弃”每个特征的一个类别。用于避免多重共线性(即特征向量不是独立的),这对于某些线性模型非常重要。
-
可选值:
-
None
(默认): 不丢弃任何类别,保留所有编码后的特征列。 -
‘first’
: 丢弃每个特征的第一个类别。如果某个特征有k
个类别,则会生成k-1
列。 -
‘if_binary’
: 仅当特征是二分类(只有两个类别)时,丢弃其中一类。对于多分类特征,则保留所有类别。 -
array
: 可以传递一个数组,指定要丢弃的特定类别。例如drop=[‘猫’]
会丢弃类别‘猫’对应的列。
-
-
示例:
-
特征‘颜色’有 [‘红’, ‘蓝’, ‘绿’] 三个类别。
-
drop=None
: 生成三列:颜色_红
,颜色_蓝
,颜色_绿
。 -
drop=‘first’
: 生成两列:颜色_蓝
,颜色_绿
(丢弃了‘红’)。此时,全为0的向量就代表被丢弃的‘红’类别。
-
-
sparse_output
(默认False
)
-
作用: 决定编码后的输出是稀疏矩阵还是密集矩阵(numpy数组)。
-
可选值:
-
True
: 返回scipy.sparse
稀疏矩阵。当类别数量非常多时(例如几万种),这可以极大地节省内存,因为只有0和1,而大部分都是0。 -
False
: 返回常规的numpy.ndarray
密集数组。更易于查看和理解,但类别多时会消耗大量内存。
-
-
历史变化: 在 1.2 版本之前,此参数名为
sparse
,现已弃用。
-
dtype
(默认numpy.float64
)
-
作用: 指定输出数组的数据类型。因为One-Hot编码的结果只有0和1,通常使用较小的数据类型来节省内存,例如
np.int8
或bool
。 -
常用值:
np.float64
,np.int8
,bool
。
-
handle_unknown
(默认‘error’
)
-
作用: 当转换过程中(例如在预测时处理测试集数据)遇到了训练时未见过的类别(
categories
参数中未定义的类别)时,应采取的策略。 -
可选值:
-
‘error’
(默认): 抛出错误ValueError
。 -
‘ignore’
: 将未知类别全部编码为0向量。这是非常危险的做法,因为它会让模型误以为这个样本在所有类别特征上都属于“基准”类别。 -
‘infrequent_if_exist’
(v1.1新增): 将未知类别视为“不常见”类别进行处理。这需要与min_frequency
或max_categories
参数配合使用。这是最推荐的处理未知类别的方式,因为它更合理。
-
-
min_frequency
与max_categories
(v1.1新增)
这两个参数用于自动将不常见的类别分组到一个“不常见”类别中,从而限制输出维度,防止类别过多导致维度爆炸。
-
min_frequency
:-
可以是一个整数或浮点数。
-
如果为整数,表示类别出现次数小于等于这个值的将被归为“不常见”类别。
-
如果为浮点数(0.0到1.0之间),表示类别出现频率小于等于这个比例的将被归为“不常见”类别。
-
-
max_categories
:-
一个整数。
-
为每个特征保留的最大类别数(不包括“不常见”类别)。频率最高的
n-1
个类别会被保留,剩下的所有类别(第n
名及以后)都会被归入一个“不常见”类别。
-
注意: 这两个参数不能同时使用。
我们看一个示例:
from sklearn.preprocessing import OneHotEncoder
import numpy as np# 示例类别数据
data = [['Red'], ['Blue'], ['Green'], ['Blue'], ['Red']]# 初始化 OneHotEncoder
# handle_unknown='ignore' 防止遇到未知类别时报错
encoder = OneHotEncoder(sparse_output=False, handle_unknown='ignore')# 学习并转换数据
# fit() :用于从训练数据生成学习模型参数
# transform():从fit()方法生成的参数,应用于模型以生成转换数据集。
# fit_transform():在同一数据集上组合fit()和transform() api
X_encoded = encoder.fit_transform(data)print("编码后的特征矩阵:")
print(X_encoded)
# 输出:
# [[1. 0. 0.] # Red -> [1, 0, 0]
# [0. 1. 0.] # Blue -> [0, 1, 0]
# [0. 0. 1.] # Green -> [0, 0, 1]
# [0. 1. 0.] # Blue
# [1. 0. 0.]] # Redprint("\n特征名称:")
print(encoder.get_feature_names_out())
# 输出:['x0_Blue' 'x0_Green' 'x0_Red']# 处理新数据(包含未知类别 ‘Yellow’)
new_data = [['Blue'], ['Red'], ['Yellow']]
X_new_encoded = encoder.transform(new_data)
print("\n新数据编码后的特征矩阵:")
print(X_new_encoded)
# 输出:
# [[0. 1. 0. 0.] # Blue -> [0, 1, 0]
# [1. 0. 0. 0.] # Red -> [1, 0, 0]
# [0. 0. 0. 0.]] # Yellow (未知) -> [0, 0, 0],因为设置了 handle_unknown='ignore'
运行输出:
编码后的特征矩阵:
[[0. 0. 1.][1. 0. 0.][0. 1. 0.][1. 0. 0.][0. 0. 1.]]特征名称:
['x0_Blue' 'x0_Green' 'x0_Red']新数据编码后的特征矩阵:
[[1. 0. 0.][0. 0. 1.][0. 0. 0.]]