引言
NLP 的核心问题是:把「人类语言」翻译成「模型能算的向量」。本文按处理管线走一遍——分词清洗 → 向量化(TF-IDF 起步,Word2Vec 进阶)→ 模型(经典分类器到 Transformer)→ 端到端情感分析实战,最后给 HuggingFace 生态与常见陷阱,让你能独立处理一个文本分类任务。
前置:/ml-python-environment-setup/(sklearn/pandas)、/ml-neural-networks-basics/(张量基础)。
目录
- 1. NLP 任务全景
- 2. 文本预处理流水线
- 3. 向量化:Bag-of-Words 与 TF-IDF
- 4. 词嵌入:Word2Vec 与 GloVe
- 5. 序列模型:RNN 到 Transformer
- 6. 情感分析实战(一):经典管线
- 7. 情感分析实战(二):PyTorch 分类器
- 8. HuggingFace 生态与预训练模型
- 9. NLP 常见陷阱
- 10. 速查表
- 延伸阅读
1. NLP 任务全景
| 任务 | 输入→输出 | 示例 |
|---|---|---|
| 文本分类 | 文本→类别 | 情感分析、垃圾识别 |
| 序列标注 | 文本→标签序列 | 命名实体识别(NER) |
| 问答 | 问题→答案 | 抽取/生成 |
| 机器翻译 | 源文→译文 | 中译英 |
| 摘要 | 长文→短摘要 | 新闻摘要 |
| 语义相似 | 两段→相似度 | 去重、检索 |
统一抽象:绝大多数任务是「序列 → 序列/类别」——模型结构相通,任务只是解码头的差别。
心智:NLP = 文本变向量 + 序列建模 + 任务头。先把前两步做对,任务头是套路。
2. 文本预处理流水线
标准流水线:
import re
import jieba # 中文分词
def preprocess(text: str) -> list[str]:
text = text.lower() # 1. 小写(英文)
text = re.sub(r'[^\w一-鿿\s]', '', text) # 2. 去标点/特殊符号
words = jieba.lcut(text) if has_chinese(text) else text.split() # 3. 分词
return words
关键选择:
| 步骤 | 英文 | 中文 |
|---|---|---|
| 分词 | 按空格 | jieba / 预训练 Tokenizer |
| 词形还原 | lemmatization(went→go) | 不需要 |
| 词干化 | stemming(running→run) | 不需要 |
| 停用词 | the/a/is 等 | 的/了/是 等 |
| 清洗 | 去 HTML/URL/emoji(看场景) | 同左 |
注意:现代预训练模型(BPE Tokenizer)不需要手写分词——它自带子词切分;手写预处理主要用于传统机器学习。
3. 向量化:Bag-of-Words 与 TF-IDF
Bag-of-Words(词袋):文本 = 词频向量,丢失词序:
from sklearn.feature_extraction.text import CountVectorizer
corpus = ["我喜欢机器学习", "机器学习很有趣"]
vec = CountVectorizer(tokenizer=jieba.lcut, ngram_range=(1, 2))
X = vec.fit_transform(corpus) # (2, 词表大小) 稀疏矩阵
TF-IDF——词频 × 逆文档频率(突出「对本文重要」的词):
from sklearn.feature_extraction.text import TfidfVectorizer
tfidf = TfidfVectorizer(tokenizer=jieba.lcut, max_features=10000)
X = tfidf.fit_transform(corpus)
| 向量化 | 思想 | 问题 |
|---|---|---|
| BoW | 词出现次数 | 常见词主导 |
| TF-IDF | 词频 × 稀有度 | 无词序/语义 |
| Word2Vec | 分布式语义 | 词向量可加 |
| 预训练 Transformer | 上下文语义 | 最贵也最好 |
记忆:传统 ML 用 TF-IDF 起步(快、可解释),要语义就上词嵌入或预训练模型。
4. 词嵌入:Word2Vec 与 GloVe
词嵌入:每个词 → 稠密向量(几百维),语义相近的词向量相近:
king − man + woman ≈ queen
Word2Vec 两种训练目标:CBOW(上下文预测中心词)/ Skip-gram(中心词预测上下文)。
# 训练或加载词向量(gensim)
from gensim.models import Word2Vec
sentences = [["我喜欢", "机器学习"], ["机器学习", "很有趣"]]
model = Word2Vec(sentences, vector_size=100, window=5, min_count=1)
sim = model.wv.most_similar("机器学习") # 语义近邻
# 用预训练词向量做文本表示
import numpy as np
def embed_text(words, wv):
vecs = [wv[w] for w in words if w in wv]
return np.mean(vecs, axis=0) if vecs else np.zeros(100)
为什么嵌入好用:词在向量空间几何化——相似词相邻,类比可加减。
局限:Word2Vec 是「静态嵌入」(词义固定);要「一词多义」用上下文嵌入(BERT)。
5. 序列模型:RNN 到 Transformer
序列建模的两代结构:
RNN/LSTM(第 1 代) Transformer(第 2 代)
逐词串行、难并行 自注意力、全并行
长序列梯度难 可建模长距离依赖
Transformer 核心:自注意力(Self-Attention)——每个词关注句中所有词:
Attention(Q, K, V) = softmax(QK^T / sqrt(d)) V
Q(查询)K(键)V(值)都来自输入;权重 = 词与词的相关度
| 组件 | 作用 |
|---|---|
| 自注意力 | 词与全句互相关注 |
| 多头注意力 | 多视角的注意力 |
| 位置编码 | 注入词序信息 |
| 前馈层 | 非线性变换 |
| 残差连接 + LayerNorm | 深网络稳定训练 |
了解即可:现代 NLP 默认 Transformer(BERT/GPT)——你很少自己训,而是用预训练模型微调(见第 8 节)。
6. 情感分析实战(一):经典管线
任务:评论 → 正/负情感。先用 TF-IDF + 逻辑回归(快、可上线、可解释):
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
# 数据:review 文本 + label 0/1
df = pd.read_csv('reviews.csv')
X_train, X_test, y_train, y_test = train_test_split(
df['review'], df['label'], test_size=0.2, random_state=42)
# TF-IDF 只 fit 训练集(防数据泄露!)
tfidf = TfidfVectorizer(tokenizer=jieba.lcut, max_features=10000)
X_tr = tfidf.fit_transform(X_train)
X_te = tfidf.transform(X_test)
model = LogisticRegression(C=1.0, max_iter=1000)
model.fit(X_tr, y_train)
print(classification_report(y_test, model.predict(X_te)))
# 可解释:看 Top 特征词
top = sorted(zip(tfidf.get_feature_names_out(), model.coef_[0]),
key=lambda x: x[1], reverse=True)[:10]
print('正面词:', [w for w, _ in top])
为什么效果往往不错:情感分类对「词级信号」敏感,词袋 + 线性模型够用——先从简单管线拿到基线,再升级复杂模型。
7. 情感分析实战(二):PyTorch 分类器
升级:词嵌入 + 序列模型(处理词序):
import torch, torch.nn as nn
from torch.utils.data import Dataset, DataLoader
# 把文本映射到 id 序列
from torchtext.data.utils import get_tokenizer
from torchtext.vocab import build_vocab_from_iterator
def ids_of(reviews, vocab):
tok = get_tokenizer(lambda s: jieba.lcut(s))
return [vocab(tok(r)) for r in reviews]
# 简单 RNN 分类器
class SentimentRNN(nn.Module):
def __init__(self, vocab_size, embed_dim=64, hidden=64, num_class=2):
super().__init__()
self.embed = nn.Embedding(vocab_size, embed_dim, padding_idx=0)
self.rnn = nn.LSTM(embed_dim, hidden, batch_first=True)
self.fc = nn.Linear(hidden, num_class)
def forward(self, x):
emb = self.embed(x) # (B, L, E)
_, (h, _) = self.rnn(emb) # 取最后隐藏态
return self.fc(h[-1]) # (B, 2)
# 训练循环同 /ml-deep-learning-advanced/ 的标准流程
# 要点:padding 到同长、mask 掉 padding 的损失
要点:Embedding 层查表取词向量、LSTM 编码序列、取末态做分类——这就是「文本→向量→分类」的完整闭环。
8. HuggingFace 生态与预训练模型
现实:NLP 已进入「预训练微调」时代——你不训模型,你用现成的:
from transformers import pipeline
# 一条 pipeline 搞定情感分析(默认微调好的 BERT)
classifier = pipeline("sentiment-analysis",
model="uer/roberta-base-finetuned-jd-binary-chinese") # 中文
result = classifier("这家店的东西很好用,推荐!")
# [{'label': 'positive', 'score': 0.99}]
# 其他开箱任务
summarizer = pipeline("summarization")
translator = pipeline("translation", model="Helsinki-NLP/opus-mt-zh-en")
生态四件套:transformers(模型)、datasets(数据集)、tokenizers(分词)、accelerate(训练)。
微调套路(比从零训省太多):
from transformers import AutoTokenizer, AutoModelForSequenceClassification, Trainer
tokenizer = AutoTokenizer.from_pretrained("bert-base-chinese")
model = AutoModelForSequenceClassification.from_pretrained(
"bert-base-chinese", num_labels=2)
# Trainer 封装训练/评估/保存,见 HuggingFace 文档
记忆:别从零训练——
pipeline先验证可行性,Trainer再微调。LLM 应用见 [[llm]]。
9. NLP 常见陷阱
| 陷阱 | 后果 | 规避 |
|---|---|---|
| TF-IDF 在全集 fit | 数据泄露,指标虚高 | 只 fit 训练集 |
| 未处理类别不平衡 | 多数类主导 | 加权/采样 |
| 忽略词序 | 丢语义(“不好吃” 与 “好吃”) | 用 n-gram/序列模型 |
| 中文未正确分词 | 特征破碎 | jieba/预训练 tokenizer |
| 停用词过度删除 | 丢否定词(“不”) | 别删否定词 |
| 测试集含训练分布 | 泛化假象 | 按时间/来源切分 |
| 直接对比不同模型 | 不公平 | 统一管线与评估 |
「不」字陷阱(经典):情感分析里「不」是强信号,删除停用词时绝不能删否定词。
10. 速查表
| 需求 | 做法 |
|---|---|
| 中文分词 | jieba / 预训练 tokenizer |
| 文本向量 | TF-IDF(经典)→ Word2Vec(嵌入)→ BERT |
| 分类模型 | 逻辑回归(基线)→ RNN → 预训练微调 |
| 情感分析 | pipeline 开箱即用 |
| 数据泄露 | 向量化只 fit 训练集 |
| 类别不平衡 | 加权损失/过采样 |
| 长文本 | 截断 + 分段 |
| 可解释 | TF-IDF Top 特征词 / SHAP |
一句话记忆:文本变向量(TF-IDF 起步、嵌入进阶),序列走 LSTM 或直接微调 Transformer;先用经典管线拿基线,再上预训练模型;防数据泄露、别删否定词。
延伸阅读
- /ml-deep-learning-advanced/ — RNN/LSTM 结构细节
- /ml-model-evaluation/ — 分类指标与评估
- /ml-feature-engineering/ — 文本特征工程延伸
- [[llm]] — 大语言模型应用开发
- [[ai-ml]] — NLP 算法深度专题
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。