【深度学习】独热编码(One-Hot Encoding)

独热编码(One-Hot Encoding)

在机器学习中,数据预处理是不可或缺的关键一步。面对各种非数值类型的分类数据(Categorical Data),如何将其转换为机器学习模型能够“理解”的语言呢?独热编码(One-Hot Encoding)便是解决这一问题的方法之一。本文将从独热编码的定义、原理出发,详细介绍其优缺点,并通过Python中的pandasscikit-learn库进行实战演示,助你轻松掌握这一数据预处理技术。

文章目录

  • 独热编码(One-Hot Encoding)
    • 1 什么是独热编码?
    • 2 为什么需要独热编码?
    • 3 独热编码与Softmax输出:从预测概率到最终决策
      • 3.1 分类模型的推理
      • 3.2 分类模型推理中独热编码的应用
      • 3.3 分类模型训练中独热编码的应用
    • 4 独热编码的优缺点
      • 4.1 优点
      • 4.2 缺点
    • 5 Python实战:玩转独热编码
      • 5.1 使用 `pandas.get_dummies()`
      • 5.2 使用 `scikit-learn.preprocessing.OneHotEncoder`
    • 6 何时选择独热编码?
    • 7 总结
  • 参考资料

1 什么是独热编码?

独热编码(One-Hot Encoding),又称一位有效编码,是一种将分类变量转换为数值形式的常用方法。其核心思想是,将一个具有N个不同类别的分类特征转换为N个二元(0或1)特征,其中每个新特征对应原始特征中的一个类别。对于每一个样本,只有代表其原始类别的那个新特征值为1,其余所有新特征值均为0。

举个例子:

假设我们有一个图像分类的任务,其标签有“猫”、“狗”、“兔”。

样本ID类别
1
2
3

经过独热编码后,这个“类别”特征会被转换成三个新的二元特征:“类别猫类别_猫”、“类别狗类别_狗”和“类别兔类别_兔”。

样本ID类别猫类别_猫类别狗类别_狗类别兔类别_兔
1100
2010
3001

正如其名“One-Hot”,在每一行数据中,只有一个新特征是“热”的(值为1)。

2 为什么需要独热编码?

在机器学习中,许多算法,特别是线性模型(如线性回归、逻辑回归)和距离度量相关的算法(如K近邻),都是基于数值计算的。如果直接将“猫”、“狗”、“兔”用数字1、2、3来表示(这种方法称为标签编码 Label Encoding),模型可能会错误地学习到这些类别之间存在有序关系,例如“兔”(3)是“猫”(1)的三倍,或者“狗”(2)大于“猫”(1)。这显然是荒谬的,因为不同类别之间并不存在这样的序数/倍数关系。

独热编码通过将每个类别独立表示为一个特征,完美地解决了这个问题。每个类别都处于一个正交的向量空间中,它们(例如 [1, 0, 0]、[0, 1, 0] 和 [0, 0, 1])之间的距离是相等的,从而消除了标签编码可能引入的虚假顺序关系,让模型能够更准确地学习特征与目标之间的关系。

3 独热编码与Softmax输出:从预测概率到最终决策

3.1 分类模型的推理

假设我们的模型已经训练好,用于对测试集中的猫、狗、兔图片进行三分类的推理(Inference)。
模型最后一层通常会使用Softmax激活函数,它会输出一个概率分布,表示该数据点属于每个类别的概率。
假设某一轮推理得到的Softmax得分(scores)如下:

softmax_scores=[0.1,0.2,0.7]\text{softmax\_scores} = [0.1, 0.2, 0.7]softmax_scores=[0.1,0.2,0.7]

这个列表的四个值分别对应了模型预测该图片为“猫”、“狗”、“兔”的概率。我们可以清晰地看到:

  • P(猫)=0.1(10%)P(\text{猫}) = 0.1 \quad (10\%)P()=0.1(10%)
  • P(狗)=0.2(20%)P(\text{狗}) = 0.2 \quad (20\%)P()=0.2(20%)
  • P(兔)=0.7(70%)P(\text{兔}) = 0.7 \quad (70\%)P()=0.7(70%)

为了得到一个确定的预测结果,我们通常会选择概率最高的那个类别。这通过一个简单的argmax操作即可完成,即找到最大值所在的索引。

argmax(softmax_scores)=2\text{argmax}(\text{softmax\_scores}) = 2argmax(softmax_scores)=2

这个索引 2 正好对应我们类别列表中的第三个类别“兔”。因此,模型的最终预测结果就是“兔”。

3.2 分类模型推理中独热编码的应用

关键点来了:可以将3.1中所述的预测结果也表示为独热编码的形式:[0, 0, 1]

在模型评估时,我们会将这个预测的独热编码 [0, 0, 1] 与真实的标签(Ground Truth)进行比较。如果这个地点的真实标签就是‘广州’(其独热编码也是 [0, 0, 1]),那么这次预测就是正确的。

3.3 分类模型训练中独热编码的应用

在训练过程中,像交叉熵损失函数(Cross-Entropy Loss)这样的工具,也正是通过比较Softmax输出的概率分布(如 [0.1, 0.2, 0.7])和真实的独热编码标签(如 [0, 0, 1])来计算损失,并指导模型进行优化的。

分类模型训练中独热编码的应用

关于对交叉熵损失函数(Cross-Entropy Loss) 的介绍,可以参见我的这一篇文章:【深度学习】深入理解交叉熵损失函数 (Cross-Entropy Loss Function) 。

所以,独热编码也为多分类模型的输出提供了一个清晰、明确的比较基准和目标格式。

4 独热编码的优缺点

4.1 优点

  1. 消除序数关系:如上所述,独热编码能够有效处理没有内在顺序的分类数据,避免模型做出错误的假设。
  2. 提升模型性能:对于线性模型等对特征数值大小敏感的算法,使用独热编码通常能带来更准确的预测结果。
  3. 易于理解和实现:其概念直观,并且在主流的Python数据科学库中都有非常便捷的实现。

4.2 缺点

  1. 维度灾难(Curse of Dimensionality):当一个分类特征的类别数量非常多(即高基数特征,High Cardinality),独热编码会产生大量的稀疏特征(大部分值为0),导致数据集的维度急剧膨胀。这不仅会增加计算复杂度和内存消耗,还可能降低模型的性能,尤其是在树模型中。
  2. 信息冗余:由于N个新特征中,只要知道了前N-1个的值,最后一个的值就可以推断出来(例如,如果“类别猫类别_猫”和“类别狗类别_狗”都为0,那么“类别兔类别_兔”必然为1)。这种现象被称为“虚拟变量陷阱”(Dummy Variable Trap),可能导致多重共线性问题。在实践中,通常会通过丢弃其中一列来解决。

5 Python实战:玩转独热编码

接下来,我将通过两个最常用的Python库——pandasscikit-learn来演示如何实现独热编码。

5.1 使用 pandas.get_dummies()

pandas库提供了get_dummies()函数,这是实现独热编码最简单快捷的方式之一。

import pandas as pd# 创建一个示例DataFrame
data = {'city': ['北京', '上海', '广州', '深圳', '北京'],'temperature': [25, 30, 28, 32, 26]}
df = pd.DataFrame(data)print("原始数据:")
print(df)# 对 'city' 列进行独热编码
df_dummies = pd.get_dummies(df, columns=['city'])print("\n使用 get_dummies 进行独热编码后的数据:")
print(df_dummies)# 为了避免多重共线性,可以设置 drop_first=True
df_dummies_dropped = pd.get_dummies(df, columns=['city'], drop_first=True)
print("\n使用 get_dummies (drop_first=True) 后的数据:")
print(df_dummies_dropped)

代码解析:

  • pd.get_dummies(df, columns=['city']) 会自动识别city列中的所有唯一类别,并为每个类别创建一个新的二元列。
  • 设置drop_first=True参数会自动丢弃第一个类别(按字母顺序,这里是“广州”)对应的列,从而解决了虚拟变量陷阱的问题。

5.2 使用 scikit-learn.preprocessing.OneHotEncoder

scikit-learn是专业的机器学习库,其OneHotEncoder提供了更强大和灵活的功能,尤其是在构建机器学习流水线(Pipeline)时。与pandas不同,scikit-learn的编码器通常需要先对分类数据进行整数编码。

import pandas as pd
from sklearn.preprocessing import OneHotEncoder, LabelEncoder# 创建一个示例DataFrame
data = {'city': ['北京', '上海', '广州', '深圳', '北京'],'temperature': [25, 30, 28, 32, 26]}
df = pd.DataFrame(data)# 步骤1: 使用 LabelEncoder 将分类文本转换为整数
label_encoder = LabelEncoder()
df['city_encoded'] = label_encoder.fit_transform(df['city'])print("LabelEncoder 转换后的数据:")
print(df)# 步骤2: 使用 OneHotEncoder 进行独热编码
# 需要将数据转换为二维数组
onehot_encoder = OneHotEncoder(sparse_output=False) # sparse_output=False 返回numpy数组
encoded_data = onehot_encoder.fit_transform(df[['city_encoded']])# 将编码后的数据转换回 DataFrame,并添加有意义的列名
encoded_df = pd.DataFrame(encoded_data, columns=onehot_encoder.get_feature_names_out(['city']))# 合并回原始DataFrame (并删除临时列)
df_final = df.join(encoded_df).drop(columns=['city_encoded'])print("\n使用 scikit-learn OneHotEncoder 后的数据:")
print(df_final)

代码解析与对比:

  • LabelEncoder:首先将’北京’、'上海’等字符串映射为0、1、2等整数。
  • OneHotEncoder:接着将这些整数转换为独热编码。fit_transform方法需要一个二维数组作为输入,因此我们使用df[['city_encoded']]
  • sparse_output=False:默认情况下,OneHotEncoder返回一个稀疏矩阵以节省内存。在这里我们设置为False以便于观察,它将返回一个标准的NumPy数组。
  • get_feature_names_out():这个方法可以帮助我们获取编码后新特征的名称。
  • 为何使用scikit-learn 虽然pandas的方法更直接,但在机器学习工作流中,scikit-learn的编码器更具优势。例如,你可以在训练集上fit一个编码器,然后用这个相同的编码器transform测试集,这可以保证训练集和测试集上特征的一致性,避免因类别不匹配而导致的错误。它还可以无缝集成到sklearn.pipeline.Pipeline中,实现数据预处理和模型训练的自动化。

6 何时选择独热编码?

  • 当分类特征的类别数量较少时(通常建议在15个以下),独热编码是一个非常好的选择。
  • 当特征是名义类别(Nominal Category),即类别之间没有顺序关系时(如颜色、城市、性别),应该使用独热编码。
  • 对于树模型(如决策树、随机森林、梯度提升树),虽然它们对特征的数值大小不敏感,但高维度的稀疏数据可能会影响其分裂点的选择效率。因此,当类别数非常多时,可以考虑其他编码方式(如目标编码、频率编码等)。

7 总结

独热编码是数据预处理武器库中一件强大而基础的工具。它通过将分类数据转换为模型友好的数值格式,解决了序数假设问题,为许多机器学习算法的成功应用铺平了道路。通过掌握pandasget_dummiesscikit-learnOneHotEncoder,你将能够根据不同的场景和需求,灵活高效地处理数据,为构建高性能的机器学习模型打下坚实的基础。在实际应用中,请务必注意其可能带来的维度灾难问题,并结合业务理解选择最合适的编码策略。


参考资料

  1. 深入浅出 one-hot

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/91187.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/91187.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Promise完全体总结

我们在上篇文章提到了异步会导致无法通过返回值来获取函数的执行结果,我们通过传入一个回调函数的方式,以参数的形式获取到了我们想要获取的数据,但是这样如果需要对数据进行多次操作导致形成回调地狱那种不便于阅读以及护理的代码。为了解决…

SpringJDBC源码初探-DataSource类

一、DataSource接口核心作用 DataSource是JDBC规范的核心接口,位于javax.sql包中,用于替代传统的DriverManager获取数据库连接。Spring框架通过org.springframework.jdbc.datasource包对该接口进行了增强,提供连接池管理、事务绑定等高级特性…

C语言(08)——关于指针(逐渐清晰版)

为了更好地理解本篇文章的知识内容,读者可以将以下文章作为补充知识进行阅读 : C语言————原码 补码 反码 (超绝详细解释)-CSDN博客 C语言————二、八、十、十六进制的相互转换-CSDN博客 C语言————斐波那契数列的理解…

LeetCode 1616.分割两个字符串得到回文串

给你两个字符串 a 和 b ,它们长度相同。请你选择一个下标,将两个字符串都在 相同的下标 分割开。由 a 可以得到两个字符串: aprefix 和 asuffix ,满足 a aprefix asuffix ,同理,由 b 可以得到两个字符串 …

算法【1】

网址:主站 工具补充 1. sort 函数的使用规则 作用:对容器元素进行排序,默认升序。语法:sort(起始迭代器, 结束迭代器, 比较规则) 前两个参数是排序范围:[begin, end)(包含begin,不包含end&am…

信创国产Linux操作系统汇总:从桌面到服务器,百花齐放

在数字化浪潮席卷全球的今天,操作系统作为信息产业的基石,其战略地位日益凸显。曾经由国外巨头垄断的格局正悄然改变——中国本土Linux操作系统历经多年沉淀,已形成了百花齐放的局面。无论是日常办公、专业开发,还是关键行业应用&…

claudia for claude code

一.安装所有必需的依赖项 1.安装 Git for Windows 步骤: 访问 Git 的官方网站 git-scm.com。 下载适用于 Windows 的最新版本安装程序。 运行安装程序。在安装向导的各个步骤中,建议保留所有默认设置,这些设置对于本指南的后续操作已经足够。 验证…

企业内外网文件安全传输解决方案

企业内外网文件安全传输解决方案 基于零信任架构的智能中转系统设计 一、业务背景与挑战分析 1.1 企业网络安全现状 在数字化转型浪潮下,企业面临着前所未有的安全挑战。传统的"城墙式"网络防护已无法满足现代企业灵活协作的需求。根据《2024年中国企业…

《HCIA-Datacom 认证》希赛三色笔记:详解 VLAN 间通信的 3 种实现方式

标记说明:■掌握内容 ■次重点 ■理解内容 在局域网部署中,VLAN 技术通过隔离广播域提升了网络安全性和稳定性,但不同 VLAN 间的通信需求又成了新的难题。比如财务部门的电脑(VLAN 10)需要访问服务…

Windows 10 系统下的编程字体安装与配置(VSCode)教程

Windows 10 系统下的编程字体安装与配置教程 常见的优秀编程字体 开发者社区中有许多备受推崇的编程字体,它们都致力于提升代码的可读性和舒适度。以下是一些常见的选择: Fira Code: 以其丰富的编程连字(ligatures)而闻名&…

ITIL 4 高速IT:解耦架构——构建快速迭代的技术基座

一、为什么要解耦:从“架构”谈到“速度”1.高速IT的真正瓶颈:不是能力,而是架构在我们深入学习ITIL 4 高速IT的时候,大家可能都会有个疑问:为什么有些组织在数字化转型过程中推得动,有些却始终难以突破&am…

网络协议——MPLS(多协议标签转发)

一,基本概述1. mpls基本概念MPLS位于二三层之间,可以向所有网络层提供服务。通过在数据链路层和网络层之间增加额外的MPLS头部,基于MPLS头部实现数据快速转发。2. 控制平面和转发平面控制平面:负责产生和维护路由信息以及标签信息…

影刀RPA_初级课程_玩转影刀自动化_EXCEL操作自动化

声明:相关内容来自影刀学院,本文章为自用笔记,切勿商用!(若有侵权,请联络删除) 1. 数据的表达 1.1 列表 1.1 获取一段字符(字符串列表的截取 —— 前开后闭) 1.2 获取长…

当贝纯净版_海信ip811n海思mv320处理器安卓4.42及9.0主板优盘免拆刷机固件及教程

海信IP811N安卓4.4.2及安卓9.0主板免拆升级教程 下载固件之前,请拆机确认下主板处理器是否为 海思hi3798mv320处理器,拆机将主板上 位于中心位置的CPU芯片上的黑色贴纸取下 然后查看芯片第二行是否有V32字样,如下图 然后进入机顶盒设置&a…

三、平衡桥电路

一、电路结构 由于平衡桥后要连接双T型桥逆变电路并联,这里采用平衡桥电路来稳定母线和中线的电压平衡,使正母线电压BUS和负母线电压BUS-相对于中线的电压大小相等,极性相反,如50VBUS,-50BUS-。 平衡桥电路由两个电容…

Java-85 深入浅出 MySQL InnoDB 存储结构:Buffer Pool、写缓冲与日志机制全解

点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) AI炼丹日志-30-新发布【1T 万亿】参数量大模型!Kim…

Linux救援模式之应用篇

挂载并访问文件系统1. 首先识别分区 fdisk -l # 查看所有磁盘和分区 lsblk # 以树状结构查看块设备 blkid # 查看分区的UUID和文件系统类型2. 创建挂载点并挂载分区 mkdir /mnt/rescue # 创建挂载点# 挂载根分区(根据你实际的根分区设备) mount /dev/…

【学习路线】游戏开发大师之路:从编程基础到独立游戏制作

前言 游戏开发是一个充满创意和技术挑战的领域,它融合了编程、美术、音效、设计等多个学科。随着游戏产业的蓬勃发展,游戏开发已成为最具吸引力的技术职业之一。本文将为您提供一条从零基础到游戏开发大师的完整学习路线,涵盖编程基础、游戏引…

宇树 G1 部署(九)——遥操作控制脚本 teleop_hand_and_arm.py 分析与测试部署

首先,我使用的是 v1.0 版本,宇树最近发力了更新的很快:xr_teleoperate-1.0 teleop_hand_and_arm.py 支持通过 XR 设备(比如手势或手柄)来控制实际机器人动作,也支持在虚拟仿真中运行。可以根据需要&#x…

第十一天:不定方程求解

每日一道C题:不定方程求解 问题:给定正整数a,b,c。求不定方程 axbyc 关于未知数x和y的所有非负整数解组数。 要求:输入一行,包含三个正整数a,b,c,两个整数之间用单个空格…