文本预处理
本节定位
文本预处理最容易让新人误会成:
- 一个固定流程
但真实情况更像:
- 一套按任务选择的整理工具
所以这节最重要的不是背步骤,而是先建立一个判断:
你为什么要做这一步,它会保留什么,又会丢掉什么。
学习目标
完成本节后,你将能够:
- 理解文本预处理到底在解决什么问题
- 掌握清洗、标准化、分词、停用词等常见步骤
- 写出一个可直接运行的预处理函数
- 明白为什么预处理不是越重越好,而是任务驱动
先建立一张地图
文本预处理更适合按“任务 -> 信息 -> 操作”的顺序理解:
所以这节真正想解决的是:
- 为什么预处理不是越重越好
- 为什么同样一条文本,在不同任务里会有不同处理方式
一、为什么文本要预处理?
原始文本通常很“脏”:
- 大小写不统一
- 标点很多
- 链接、数字、表情混在一起
- 同一个意思可能有很多写法
你可以把文本预处理想成“洗菜”:
- 不洗,模型很难直接下锅
- 洗过头,又可能把营养一起洗掉
所以预处理的核心不是“洗得越干净越好”,而是:
让文本更适合当前任务。
1.1 一个更适合新人的总类比
你可以把文本预处理想成:
- 出门前整理背包
如果你去爬山,带的东西会和去办公室不一样。
同样地:
- 做情感分析时,否定词很重要
- 做检索时,关键词覆盖更重要
- 做命名实体识别时,大小写和格式信息可能很重要
所以预处理不是:
- 永远固定一套动作
而是:
- 看你准备去做什么任务
二、预处理最常见的几步
| 步骤 | 常见作用 |
|---|---|
| 小写化 | 统一英文大小写 |
| 去链接 / 特殊符号 | 降低无意义噪声 |
| 去多余空格 | 统一格式 |
| 分词 | 拆成更小处理单位 |
| 停用词处理 | 去掉高频低信息词 |
| 数字 / 特殊模式标准化 | 统一某些规则模式 |
但记住:
- 这些步骤不是每次都全做
- 也不是做得越多越好
2.1 一个新人很值得先记住的判断表
| 任务 | 最值得优先保留的信息 |
|---|---|
| 情感分析 | 否定词、情绪词、程度词 |
| 检索 / RAG | 关键词、术语、数字、专有名词 |
| NER | 大小写、格式、专名边界 |
| 传统文本分类 | 稍重一点的清洗常常更常见 |
这个表不是绝对规则,但它能帮新人先建立一个很重要的直觉:
- 预处理是否合理,必须回到任务本身看
三、先跑一个最小预处理函数
下面我们先用英文示例,因为英文更容易用标准库直接演示。
思路对中文同样适用,只是中文通常要借助更专业的切分工具。
import re
stopwords = {"the", "is", "a", "an", "and", "to", "of", "in"}
def preprocess(text):
text = text.lower() # 1. 小写化
text = re.sub(r"http\\S+", " ", text) # 2. 去链接
text = re.sub(r"[^a-z0-9\\s]", " ", text) # 3. 去特殊符号
text = re.sub(r"\\s+", " ", text).strip() # 4. 合并多余空格
tokens = text.split() # 5. 简单分词
tokens = [t for t in tokens if t not in stopwords] # 6. 去停用词
return tokens
sample = "The movie is AMAZING, and the ending is full of surprises!"
print(preprocess(sample))
这个例子最想让你看到什么?
文本预处理通常不是一个神秘大黑箱,
而是一连串很朴素的小步骤。
真正关键的是:
- 每一步为什么存在
- 它是否真的适合当前任务
3.1 再看一个“保留否定词”的最小对比
import re
stopwords_keep_not = {"the", "is", "a", "an", "and", "to", "of", "in"}
stopwords_drop_not = {"the", "is", "a", "an", "and", "to", "of", "in", "not"}
def preprocess_with_stopwords(text, stopwords):
text = text.lower()
text = re.sub(r"[^a-z0-9\\s]", " ", text)
text = re.sub(r"\\s+", " ", text).strip()
tokens = text.split()
return [t for t in tokens if t not in stopwords]
sample = "This movie is not good"
print("keep_not :", preprocess_with_stopwords(sample, stopwords_keep_not))
print("drop_not :", preprocess_with_stopwords(sample, stopwords_drop_not))
这个例子很适合初学者,因为它会直接让你看到:
- 一个看起来“不重要”的词
- 其实可能正是决定语义方向的关键