第一章:NLP概述与文本预处理
大家好,我是你们这门课的主讲。今天咱们聊聊NLP的起点——文本预处理。
说实话,我见过太多同学一上来就调模型、跑BERT,结果数据一塌糊涂,模型效果自然惨不忍睹。文本预处理,说白了就是NLP的地基。地基不稳,楼盖得再高也得塌。
1.1 NLP发展史:从规则到深度学习
NLP这几十年的发展,我把它分成三个阶段。你想想看,是不是很有意思?
- 规则时代(1950s-1990s):全靠人工写规则。比如“如果句子以‘吗’结尾,就是疑问句”。我刚开始接触NLP时,还见过老代码里几千条if-else,维护起来简直噩梦。
- 统计时代(1990s-2010s):用概率说话。朴素贝叶斯、HMM、CRF这些模型开始流行。我记得2012年做分词项目,CRF还是主流方案。
- 深度学习时代(2010s至今):Word2Vec、LSTM、Transformer、BERT……模型越来越强,但数据预处理的重要性一点没减。
核心观点:无论模型多先进,80%的问题出在数据上。文本预处理就是帮你解决那80%的问题。
1.2 应用场景:NLP到底能干啥?
NLP的应用场景,说白了就是“让机器理解人话”。我挑几个最常见的说说:
| 场景 | 典型任务 | 我踩过的坑 |
|---|---|---|
| 搜索推荐 | Query理解、关键词提取 | 用户搜“苹果”,到底是水果还是手机? |
| 智能客服 | 意图识别、情感分析 | 用户说“你行你上啊”,情感是正面还是负面? |
| 内容审核 | 敏感词检测、文本分类 | “我靠”在不同语境下含义完全不同 |
| 机器翻译 | Seq2Seq、注意力机制 | “吃食堂”翻译成“eat the canteen”就闹笑话了 |
个人经验:做NLP项目,先搞清楚业务场景。我见过有人给客服系统上BERT,结果用户问“几点下班”,模型回了篇小作文。杀鸡焉用牛刀?
1.3 文本清洗:脏数据是万恶之源
文本清洗,说白了就是“去杂质”。我做过一个项目,数据里全是HTML标签、特殊符号、乱码。模型训练完,准确率不到50%。后来一查,原来是数据没洗干净。
常见的清洗操作:
- 去HTML标签:用正则或者BeautifulSoup
- 去特殊符号:保留中文、英文、数字即可
- 去空白字符:多余的空格、换行、制表符
- 统一大小写:英文全部转小写
- 编码转换:统一为UTF-8
import re
def clean_text(text):
# 去HTML标签
text = re.sub(r'<[^>]+>', '', text)
# 去特殊符号,保留中文、英文、数字
text = re.sub(r'[^\u4e00-\u9fa5a-zA-Z0-9]', ' ', text)
# 去多余空格
text = re.sub(r'\s+', ' ', text).strip()
return text
避坑指南:我曾经在清洗时把“3.14”中的点去掉了,结果数值全变了。清洗前一定要确认业务含义,别一刀切。
1.4 分词:Jieba vs HanLP
分词是中文NLP的第一步。中文不像英文有空格,所以分词很关键。我常用的两个工具:Jieba和HanLP。
Jieba:轻量级选手
Jieba上手快,适合快速验证。它有三种模式:
- 精确模式:最常用,适合文本分析
- 全模式:把所有可能的词都切出来,速度慢
- 搜索引擎模式:在精确模式基础上再切长词
import jieba
text = "我爱自然语言处理"
# 精确模式
words = jieba.lcut(text)
print(words) # ['我', '爱', '自然语言', '处理']
# 添加自定义词典
jieba.add_word("自然语言处理")
words = jieba.lcut(text)
print(words) # ['我', '爱', '自然语言处理']
个人习惯:做项目时,我一般先用Jieba的精确模式跑一遍,看看效果。如果领域词多,就加自定义词典。简单粗暴,但有效。
HanLP:工业级选手
HanLP功能更全,支持词性标注、命名实体识别、依存句法分析等。适合生产环境。
from hanlp import HanLP
text = "我爱自然语言处理"
# 分词+词性标注
result = HanLP.segment(text)
for word, pos in result:
print(f"{word}/{pos}", end=" ")
# 输出:我/rr 爱/v 自然语言/n 处理/vn
HanLP的模型更大,效果更好,但部署成本也高。我一般在需要高精度时用HanLP,比如金融、医疗领域的文本分析。
| 对比项 | Jieba | HanLP |
|---|---|---|
| 安装难度 | 简单 | 中等 |
| 分词速度 | 快 | 中等 |
| 功能丰富度 | 基础 | 全面 |
| 适用场景 | 快速原型、小项目 | 生产环境、高精度需求 |
1.5 停用词过滤:去掉噪音
停用词就是那些高频但没啥意义的词,比如“的”、“了”、“是”、“在”。去掉它们,模型能更关注核心内容。
我常用的停用词表来源:
- 哈工大停用词表
- 百度停用词表
- 自己根据业务积累
def load_stopwords(filepath):
with open(filepath, 'r', encoding='utf-8') as f:
stopwords = set([line.strip() for line in f])
return stopwords
def filter_stopwords(words, stopwords):
return [w for w in words if w not in stopwords]
# 示例
stopwords = load_stopwords('stopwords.txt')
text = "我今天去了图书馆,然后学习了自然语言处理"
words = jieba.lcut(text)
filtered = filter_stopwords(words, stopwords)
print(filtered) # ['今天', '图书馆', '学习', '自然语言', '处理']
避坑指南:我曾经把“不”也加进了停用词表,结果“不喜欢”变成了“喜欢”,情感分析全反了。停用词表一定要根据任务调整,别偷懒直接用网上的。
小结
文本预处理,说白了就是“把脏数据洗干净,把长句子切碎,把没用的词扔掉”。这一步做好了,后面的模型训练才能事半功倍。
我个人习惯是:先清洗,再分词,最后去停用词。每一步都检查一下中间结果,别等到模型训练完才发现数据有问题。
嗯,今天就聊到这儿。下一章咱们聊聊词向量和特征工程,那才是真正让机器“理解”文本的开始。