NLP 入门实战:文本向量化、词嵌入与情感分析

从零构建 NLP 实战:文本预处理流水线、Bag-of-Words/TF-IDF 向量化、Word2Vec/GloVe 词嵌入、RNN 与 Transformer 结构、情感分析端到端(scikit-learn + PyTorch)、HuggingFace 生态。

引言

NLP 的核心问题是:把「人类语言」翻译成「模型能算的向量」。本文按处理管线走一遍——分词清洗 → 向量化(TF-IDF 起步,Word2Vec 进阶)→ 模型(经典分类器到 Transformer)→ 端到端情感分析实战,最后给 HuggingFace 生态与常见陷阱,让你能独立处理一个文本分类任务。

前置:/ml-python-environment-setup/(sklearn/pandas)、/ml-neural-networks-basics/(张量基础)。


目录


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 算法深度专题

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「ml」更多文章

  1. 集成学习实战:Bagging、随机森林、梯度提升与 Stacking
  2. 迁移学习实战:预训练模型、特征提取与微调全流程
  3. 计算机视觉入门实战:图像处理与 CNN 图像分类