one-hot 编码 - 简单实现思路
1 课程概览
本课演示 one-hot 编码的简单实现版本,无需 jieba、joblib 等第三方库,仅用 Python 基础语法(enumerate 函数)即可完成。同时总结 one-hot 编码的优缺点,引出稠密词向量表示法(Word2Vec、Word Embedding)的必要性。
2 核心概念与定义
- 简单版 one-hot 编码:使用 Python 基础语法实现,无需第三方库,通过
enumerate构建词汇到索引的映射。 enumerate函数:Python 内置函数,同时获取索引和值,格式为for i, value in enumerate(iterable)。
3 模型与算法详解
简单版实现流程
- 准备语料库:定义切词后的词汇列表(vocab)
- 构建词汇到索引的映射:使用
enumerate构建word_to_index字典 - 对每个词进行 one-hot 编码:
- 初始化全零列表(长度 = 语料库长度)
- 获取当前词汇的索引
- 修改对应位置为 1
- 打印结果
复杂版 vs 简单版对比
| 对比项 | 复杂版 | 简单版 |
|---|---|---|
| 依赖库 | jieba + joblib + top_nether | 无(纯 Python) |
| 代码量 | 约 20 行 | 约 10 行 |
| 索引稳定性 | 保存模型后固定 | 依赖字典顺序,固定 |
| 适用场景 | 数据量大、需保存映射关系 | 快速实现、学习理解 |
one-hot 编码优缺点总结
| 优点 | 缺点 |
|---|---|
| 操作简单,容易理解 | 完全割裂词与词之间的联系 |
| 实现容易(零列表 + 改 1) | 大词汇量下向量长度过大 |
| — | 占用大量内存(零也占空间) |
| — | 数据稀疏(100 个词 → 1 个 1 + 99 个 0) |
正因为 one-hot 的缺点(稀疏、割裂词间联系、浪费内存),才出现了 Word2Vec 和 Word Embedding 等稠密向量表示法。
4 数学原理与推导
简单版索引映射
使用 enumerate(vocab, start=0),词汇 $w_i$ 的索引为 $i$(从 0 开始):
$$\text{word_to_index}[w_i] = i$$
one-hot 编码生成
$$\text{one-hot}(w_i) = [0, 0, ..., \underbrace{1}_{第\ i\ 位}, ..., 0]$$
注意:简单版索引从 0 开始,无需减 1。
5 代码示例
# 简单版 one-hot 编码实现
def dm_simple_one_hot():
# 1. 准备语料库(切词后的词汇列表)
vocabs = ['周杰伦', '微微', '成龙', '学习']
# 2. 构建词汇到索引的映射关系
word_to_index = {}
for i, vocab in enumerate(vocabs):
word_to_index[vocab] = i
print("词汇映射:", word_to_index)
# 输出:{'周杰伦': 0, '微微': 1, '成龙': 2, '学习': 3}
# 3. 对每个词进行 one-hot 编码
for vocab in vocabs:
# 3.1 初始化全零列表,长度等于语料库长度
zero_list = [0] * len(vocabs)
# 3.2 获取当前词汇的索引(从0开始,无需减1)
index = word_to_index[vocab]
# 3.3 修改对应元素为1
zero_list[index] = 1
# 4. 打印结果
print(f"{vocab} 的 one-hot 编码:{zero_list}")
# 测试
if __name__ == "__main__":
dm_simple_one_hot()
输出示例:
词汇映射: {'周杰伦': 0, '微微': 1, '成龙': 2, '学习': 3}
周杰伦 的 one-hot 编码:[1, 0, 0, 0]
微微 的 one-hot 编码:[0, 1, 0, 0]
成龙 的 one-hot 编码:[0, 0, 1, 0]
学习 的 one-hot 编码:[0, 0, 0, 1]
6 重难点与易错提醒
- ❗重点:简单版无需任何第三方库,纯 Python 基础语法即可实现。
- ⚠️易错:简单版索引从 0 开始(
enumerate默认),无需减 1;复杂版索引从 1 开始,需减 1。 - 💡深入理解:简单版结果固定不变(依赖字典顺序),与复杂版保存模型后效果类似。
- ❗重点:one-hot 的核心缺点是稀疏(大量 0)和割裂词间联系,这是引入 Word2Vec 的根本原因。
7 课堂问答精选
Q1:简单版和复杂版有什么区别?
A:复杂版使用 jieba 分词 + joblib 保存模型 + top_nether 库,约 20 行代码;简单版纯 Python 基础语法(enumerate),约 10 行代码,无需第三方库。两者结果一致,简单版更适合快速实现。
Q2:为什么 one-hot 编码需要改进?
A:one-hot 有三大缺点——①完全割裂词与词之间的联系;②大词汇量下向量长度过大;③数据稀疏(大量 0),占用大量内存。因此需要稠密向量表示法(Word2Vec、Word Embedding)来解决。
Q3:简单版的结果会变化吗?
A:不会。简单版依赖字典的遍历顺序,只要语料库不变,结果固定不变。复杂版通过保存模型(joblib)保证一致性。
8 本课小结
- 简单版 one-hot:使用
enumerate构建映射,纯 Python 实现,约 10 行代码。 - 简单版索引从 0 开始,无需减 1。
- one-hot 优点:操作简单、容易理解。
- one-hot 缺点:割裂词间联系、向量过长、占用内存、数据稀疏。
- 缺点引出:Word2Vec 和 Word Embedding 等稠密表示法。
9 延伸思考
- Word2Vec 如何解决 one-hot 的稀疏问题?
- Word2Vec 如何建立词与词之间的语义联系?