文本特征处理 - n-gram 代码演示
1 课程概览
本课演示 n-gram 特征的代码实现,使用滑动窗口和 zip(*) 函数生成 n-gram 特征。n-gram 将连续的 N 个词作为整体特征,帮助模型更好地理解文本规律。实际开发中 N 通常取 2 或 3。
2 核心概念与定义
- n-gram:连续的 N 个词或字相邻出现,作为一个特征(小词组特征)。
- uni-gram(1-gram):每个词独立,即切词结果。
- bi-gram(2-gram):连续 2 个词组合,如"敲动"、"我心"。
- tri-gram(3-gram):连续 3 个词组合,如"敲动我心"。
- 滑动窗口(Sliding Window):通过切片生成 n-gram 特征的方法。
3 模型与算法详解
n-gram 分类
| 名称 | 别名 | N值 | 说明 |
|---|---|---|---|
| uni-gram | 1-gram | 1 | 每个词独立 |
| bi-gram | 2-gram | 2 | 连续2词组合 |
| tri-gram | 3-gram | 3 | 连续3词组合 |
n-gram 生成流程
- 设定 N 值:通常为 2 或 3
- 滑动窗口切片:
[input_list[i:] for i in range(n_gram)] - zip(*) 组合:将切片列表的对应元素打包
- 去重:使用
set()去除重复的 n-gram
示例
输入:[1, 3, 2, 1, 5, 3],N=2
切片:
[1, 3, 2, 1, 5, 3] (i=0)
[3, 2, 1, 5, 3] (i=1)
zip(*) 组合:
[(1,3), (3,2), (2,1), (1,5), (5,3)]
N 值选择建议
- 实际开发中 N 通常取 2 或 3
- N 过大(如 10、20)会失去切词意义
- 大多数场景使用 2-gram 即可
4 数学原理与推导
n-gram 特征定义
给定词序列 $W = [w_1, w_2, ..., w_m]$,n-gram 特征为:
$$\text{n-gram}(W) = {(w_i, w_{i+1}, ..., w_{i+n-1}) | 1 \leq i \leq m-n+1}$$
滑动窗口切片
$$\text{Slices} = [W[i:] \text{ for } i \text{ in range}(n)]$$
zip(*) 组合
$$\text{n-gram tuples} = \text{zip}(*\text{Slices})$$
5 代码示例
# n-gram 特征代码实现
# 1. 定义变量,记录 N 的值
n_gram_range = 2 # 通常取 2 或 3
# 2. 定义函数,生成 n-gram 特征
def create_n_gram(input_list, n_gram_range):
"""
生成 n-gram 特征
:param input_list: 输入列表(如切词后的词列表)
:param n_gram_range: n-gram 的 N 值
:return: n-gram 特征列表
"""
# 2.1 通过滑动窗口获取切片
sliced_list = [
input_list[i:] for i in range(n_gram_range)
]
# 例如:input_list = [1, 3, 2, 1, 5, 3], n=2
# sliced_list = [[1, 3, 2, 1, 5, 3], [3, 2, 1, 5, 3]]
# 2.2 使用 zip(*) 对切片列表进行组合
n_gram_tuples = list(zip(*sliced_list))
# 例如:[(1, 3), (3, 2), (2, 1), (1, 5), (5, 3)]
return n_gram_tuples
# 3. 测试
def main():
# 定义输入列表
input_list = [1, 3, 2, 1, 5, 3]
# 调用函数生成 n-gram 特征
result = create_n_gram(input_list, n_gram_range)
# 输出结果
print("输入:", input_list)
print(f"{n_gram_range}-gram 特征:", result)
# [(1, 3), (3, 2), (2, 1), (1, 5), (5, 3)]
if __name__ == "__main__":
main()
文本 n-gram 示例
import jieba
# 文本 n-gram
text = "敲动我心"
words = jieba.lcut(text) # ['敲动', '我心']
# 2-gram
n_gram = 2
sliced = [words[i:] for i in range(n_gram)]
bi_gram = list(zip(*sliced))
print("2-gram:", bi_gram) # [('敲动', '我心')]
6 重难点与易错提醒
- ❗重点:n-gram 将连续 N 个词作为整体特征,N 通常取 2 或 3。
- ❗重点:滑动窗口切片 +
zip(*)组合是核心实现方法。 - ⚠️易错:
zip(*)中的*不可省略,否则无法正确组合。 - 💡深入理解:n-gram 帮助模型理解词与词之间的组合关系,提升语义理解。
- 💡深入理解:N 过大会失去切词意义,实际开发中最多到 3-gram。
7 课堂问答精选
Q1:什么是 n-gram?
A:n-gram 是将连续的 N 个词或字作为整体特征。例如 2-gram 将相邻 2 词组合,如"敲动"+"我心" → ("敲动", "我心")。
Q2:如何生成 n-gram 特征?
A:①滑动窗口切片 [input_list[i:] for i in range(n_gram)];②zip(*) 组合 list(zip(*sliced_list))。
Q3:N 值通常取多少?
A:通常取 2 或 3。N 过大(如 10、20)会失去切词意义,因为有的句子切完可能都没有 10 个词。
Q4:n-gram 有什么作用?
A:让计算机更好地理解文本规律,将相邻词的组合作为特征,提升模型对语义的理解能力。
8 本课小结
- n-gram:连续 N 个词作为整体特征。
- 分类:uni-gram(1)、bi-gram(2)、tri-gram(3)。
- 实现:滑动窗口切片 +
zip(*)组合。 - N 值通常取 2 或 3。
- 作用:帮助模型理解词组合关系,提升语义理解。
9 延伸思考
- n-gram 特征如何应用于文本分类?
- 如何处理 n-gram 特征的维度爆炸问题?