2. NLP基础与工具链:核心任务与库选型
好,咱们进入第二章。说实话,很多刚入行的朋友一上来就追着模型跑,结果连分词都搞不明白。我个人习惯是,先把地基打牢。NLP的核心任务,说白了就三样:分词、词性标注、命名实体识别。这三板斧玩转了,后面做客服意图识别、实体抽取才能得心应手。
2.1 三大核心任务,一个都不能少
分词(Word Segmentation)
中文和英文不一样。英文单词天然有空格隔开,中文没有。所以第一步,就是把连续的汉字切分成有意义的词。比如「我喜欢吃苹果」,切出来是「我 / 喜欢 / 吃 / 苹果」。
为什么重要? 分词错了,后面全错。比如「南京市长江大桥」,如果切成「南京 / 市长 / 江大桥」,意思就完全跑偏了。我在项目中遇到过,用户问「武汉长江大桥有多长」,结果系统把「武汉长江」当成了一个地名,直接查不到数据。
分词难点在哪?
- 歧义消解:「他说的确实在理」——「的确」还是「的 / 确实」?
- 未登录词:新词、人名、产品名,比如「拼多多」「抖音」这种,词典里没有。
- 粒度问题:粗粒度(「北京大学」作为一个词)还是细粒度(「北京 / 大学」)?看场景。
词性标注(POS Tagging)
给每个词打上标签,比如名词、动词、形容词。这有什么用?你想想看,客服系统里用户说「我要退款」,系统需要知道「退款」是动词还是名词?如果是动词,可能是操作指令;如果是名词,可能是查询状态。
我刚开始做的时候,觉得词性标注可有可无。后来发现,意图识别里,动词往往是核心动作,名词是实体。没有词性标注,你很难精准定位用户到底想干嘛。
命名实体识别(NER)
这个就更有意思了。从文本里抽取出人名、地名、机构名、时间、金额等。比如「帮我查一下昨天从北京到上海的机票」——需要抽取出时间(昨天)、出发地(北京)、目的地(上海)、商品(机票)。
我的经验: 在智能客服里,NER 是召回率的关键。我曾经做过一个电商客服,用户说「我上周买的那个红色毛衣还没到」,如果 NER 没抽取出「上周」「红色」「毛衣」,系统根本不知道他在问哪个订单。
2.2 Python 主流 NLP 库,怎么选?
市面上库很多,但常用的就这几个:Jieba、HanLP、NLTK、spaCy。我一个个说,最后给你一个选型建议。
| 库名 | 语言 | 核心优势 | 适合场景 |
|---|---|---|---|
| Jieba | 中文 | 轻量、速度快、易上手 | 快速分词、简单文本处理 |
| HanLP | 中文 | 功能全面、模型丰富、精度高 | 生产级中文 NLP 任务 |
| NLTK | 英文为主 | 教学经典、资源丰富 | 学习研究、英文文本分析 |
| spaCy | 多语言 | 工业级、速度快、管道化设计 | 生产环境、多语言任务 |
Jieba:中文分词的老大哥
说实话,Jieba 是我用得最多的库。为什么?简单。三行代码就能跑起来。
import jieba
text = "我今天想吃北京烤鸭"
words = jieba.lcut(text)
print(words) # ['我', '今天', '想', '吃', '北京烤鸭']
它支持三种模式:精确模式(默认)、全模式(把所有可能的词都切出来)、搜索引擎模式(精确模式基础上再切长词)。
注意: Jieba 的词典是静态的。如果你遇到新词,比如「瑞幸咖啡」,需要手动添加自定义词典。我曾经因为没加词典,结果「瑞幸咖啡」被切成了「瑞 / 幸 / 咖啡」,用户搜「瑞幸」根本匹配不到。
HanLP:中文 NLP 的瑞士军刀
HanLP 比 Jieba 重,但功能强太多。分词、词性标注、NER、依存句法分析、文本分类……几乎你能想到的它都有。
import hanlp
# 加载预训练模型
tokenizer = hanlp.load(hanlp.pretrained.tok.COARSE_ELECTRA_SMALL_ZH)
pos_tagger = hanlp.load(hanlp.pretrained.pos.CTB9_POS_ELECTRA_SMALL)
ner_tagger = hanlp.load(hanlp.pretrained.ner.MSRA_NER_ELECTRA_SMALL_ZH)
text = "华为在深圳发布了新款手机"
print(tokenizer(text)) # ['华为', '在', '深圳', '发布', '了', '新款', '手机']
print(pos_tagger(text)) # ['NR', 'P', 'NR', 'VV', 'AS', 'JJ', 'NN']
print(ner_tagger(text)) # [('华为', 'ORGANIZATION'), ('深圳', 'LOCATION')]
你看,一条龙服务。我个人建议,如果项目对精度要求高,而且你愿意花点时间加载模型,HanLP 是首选。
NLTK:学习入门的好帮手
NLTK 是 NLP 界的教科书。它内置了大量语料库和词典,非常适合学习。但说实话,生产环境我很少用它。为什么?速度慢,而且中文支持一般。
import nltk
nltk.download('punkt')
nltk.download('averaged_perceptron_tagger')
text = "Natural language processing is fun."
tokens = nltk.word_tokenize(text)
tags = nltk.pos_tag(tokens)
print(tags) # [('Natural', 'JJ'), ('language', 'NN'), ...]
嗯,这里要注意,NLTK 默认是英文的。你要做中文,还得自己搭分词器,有点折腾。
spaCy:工业级的多语言选手
spaCy 的设计理念就是「拿来就用」。它把分词、词性标注、NER、依存分析都整合到一个 pipeline 里,一次调用全搞定。而且速度极快,我做过测试,spaCy 处理英文的速度比 NLTK 快 10 倍以上。
import spacy
nlp = spacy.load("zh_core_web_sm")
doc = nlp("阿里巴巴在杭州成立了达摩院")
for ent in doc.ents:
print(ent.text, ent.label_)
# 阿里巴巴 ORG
# 杭州 GPE
# 达摩院 ORG
spaCy 的中文模型基于预训练词向量,精度不错。但它的中文模型体积较大,第一次加载需要下载。
2.3 选型建议:别盲目跟风
你可能会问:「到底该用哪个?」我的建议是看场景:
- 快速原型、简单分词:Jieba。轻量、无依赖、秒上手。
- 中文生产级应用:HanLP。精度高、功能全,适合做客服意图识别、实体抽取。
- 英文文本分析:spaCy。速度快、管道化设计,适合做信息抽取。
- 学习研究:NLTK。语料库丰富,适合练手。
我的小技巧: 实际项目中,我经常混用。比如用 Jieba 做快速分词,然后用 HanLP 做 NER。或者用 spaCy 做英文部分,用 Jieba 做中文部分。工具是死的,人是活的。
2.4 避坑指南
最后,分享几个我踩过的坑:
- 词典更新:Jieba 的词典不会自动更新。如果你做电商客服,记得定期添加新商品名、品牌名。
- 模型版本:HanLP 和 spaCy 的模型版本要和库版本匹配。我曾经因为版本不一致,加载模型时报错,查了半天。
- 性能测试:别光看精度,也要看速度。在客服系统里,用户等不了 3 秒。我一般会先用小数据集跑一下,看看延迟。
- 编码问题:中文文本经常有乱码。记得统一用 UTF-8,别用 GBK。
好了,这一章就到这里。下一章我们聊聊文本预处理,那是真正动手前的最后一步准备。