one-hot 编码 - 获取
1 课程概览
本课演示 one-hot 编码的代码实现(复杂版),包括导包、分词、去重、构建词汇映射器(word_index 字典)、生成 one-hot 编码、保存模型等步骤。通过 jieba 分词和 joblib 保存模型,完整实现 one-hot 编码的获取流程。
2 核心概念与定义
- 词汇映射器(Vocabulary Mapper):将词汇映射到索引的字典(
word_index),记录每个词及其对应的位置索引。 - joblib:Python 第三方库,用于保存和加载模型(词汇映射器)。
- 去重(Deduplication):对切词后的结果去除重复词,得到词汇表。
3 模型与算法详解
one-hot 编码获取流程
- 导包:导入
jieba(分词)和joblib(模型保存) - 准备语料:定义待处理的文本
- 切词:使用
jieba.cut()进行分词 - 去重:对切词结果去重,得到词汇表
- 构建词汇映射器:创建
word_index字典,记录每个词的索引位置 - 生成 one-hot 编码:根据索引创建零列表,将对应位置改为 1
- 保存模型:使用
joblib.dump()保存词汇映射器
词汇映射器(word_index)示例
# 切词去重后的词汇表
vocab = ['我', '爱', '学习', 'AI']
# 构建的 word_index 字典
word_index = {
'我': 1,
'爱': 2,
'学习': 3,
'AI': 4
}
one-hot 编码生成逻辑
对于词汇 w:
1. 获取 w 在 word_index 中的索引 index
2. 创建长度为 len(word_index) 的零列表
3. 将列表第 (index - 1) 位改为 1
4. 返回该列表
4 数学原理与推导
one-hot 编码生成
给定词汇表 $V = {w_1, w_2, ..., w_n}$,词汇 $w_i$ 的索引为 $i$,其 one-hot 编码为:
$$\text{one-hot}(w_i) = [0, 0, \underbrace{1}_{第\ i\ 位}, 0, ..., 0]$$
注意:代码中索引从 1 开始,列表位置从 0 开始,因此列表中第 $(i-1)$ 位为 1。
5 代码示例
import jieba
import joblib
# 定义函数:演示 one-hot 编码(复杂版)
def dm01_one_hot_gen():
# 1. 准备语料
content = "我爱学习AI,学习使我快乐"
# 2. 使用 jieba 进行分词
result = jieba.cut(content, cut_all=False)
words = list(result)
print("分词结果:", words)
# 3. 去重,得到词汇表
vocab = list(set(words))
print("去重后词汇表:", vocab)
# 4. 构建词汇映射器(word_index 字典)
word_index = {}
for i, word in enumerate(vocab, start=1):
word_index[word] = i
print("词汇映射器:", word_index)
# 5. 生成 one-hot 编码
for word in vocab:
# 创建长度等于词汇表总数的零列表
one_hot = [0] * len(word_index)
# 获取该词的索引(从1开始,列表从0开始,需减1)
index = word_index[word] - 1
# 将对应位置改为1
one_hot[index] = 1
print(f"{word} 的 one-hot 编码:{one_hot}")
# 6. 保存词汇映射器(模型)
joblib.dump(word_index, "model/word_index.model")
print("词汇映射器已保存")
# 测试
if __name__ == "__main__":
dm01_one_hot_gen()
输出示例:
分词结果: ['我', '爱', '学习', 'AI', ',', '学习', '使', '我', '快乐']
去重后词汇表: ['快乐', 'AI', '学习', '我', '爱', '使', ',']
词汇映射器: {'快乐': 1, 'AI': 2, '学习': 3, '我': 4, '爱': 5, '使': 6, ',': 7}
快乐 的 one-hot 编码:[1, 0, 0, 0, 0, 0, 0]
AI 的 one-hot 编码:[0, 1, 0, 0, 0, 0, 0]
学习 的 one-hot 编码:[0, 0, 1, 0, 0, 0, 0]
...
词汇映射器已保存
6 重难点与易错提醒
- ❗重点:one-hot 编码的列表长度等于去重后的词汇总数,不是切词前的总数。
- ⚠️易错:
word_index的索引从 1 开始,但 Python 列表从 0 开始,生成 one-hot 时需要index - 1。 - ⚠️易错:
set()去重是无序的,每次运行结果可能不同,需保存模型才能保证一致性。 - 💡深入理解:词汇映射器本质上是将词汇顺序映射出来,保存后可保证后续使用时索引不变。
7 课堂问答精选
Q1:为什么要保存词汇映射器?
A:因为 set() 去重是无序的,每次运行词汇顺序可能不同,导致 one-hot 编码变化。保存词汇映射器后,后续使用时加载模型,索引固定不变(如"微微"始终是第 6 位)。
Q2:one-hot 编码的列表长度由什么决定?
A:由去重后的词汇表总数决定。如有 6 个去重后的词,则每个词的 one-hot 编码长度为 6。
Q3:为什么索引要减 1?
A:word_index 字典中索引从 1 开始计数,但 Python 列表从 0 开始索引,因此生成 one-hot 编码时需要 index - 1 才能对应正确的列表位置。
8 本课小结
- one-hot 编码获取流程:导包 → 分词 → 去重 → 构建词汇映射器 → 生成编码 → 保存模型。
- 词汇映射器(word_index)记录每个词的索引位置。
- 列表长度 = 去重后词汇总数,索引从 1 开始需减 1。
- 使用
joblib.dump()保存模型,保证后续使用时索引不变。
9 延伸思考
- 复杂版约 20 行代码,是否有更简单的实现方式?(简单版将在下节课介绍)
- 词汇表很大时,one-hot 编码会有什么问题?