使用表示模型进行文本分类

#2025/12/30 #ai

如何用"不会说人话"的表示模型来给电影评论分类?


目录

一、表示模型 vs 生成模型:两种不同的分类思路

类型特点输出代表模型
表示模型不会生成文字,只会输出数字类别编号(0或1)BERT、DistilBERT
生成模型会“说人话“,输出完整句子文字(“positive”/“negative”)GPT、T5

形象比喻:

  • 表示模型像打分裁判
    • 给你举牌“1分“或”0分
  • 生成模型像解说员
    • 说一句话 “这是正面评价”

{%}

图 4-3:基础模型针对特定任务进行微调,例如执行分类任务或生成通用嵌入向量

二、表示模型的两种用法

用表示模型分类有两条路:

{%}

使用特定任务模型直接进行分类,或使用通用嵌入向量间接进行分类

路径1:特定任务模型(直接分类)

输入评论 → 特定任务模型 → 直接输出类别(0或1)  

什么是特定任务模型?

就是已经专门针对“情感分析“训练好的模型,拿来就能用。

优点:

  • 开箱即用,不用自己训练
  • 效果通常不错(因为是专门训练的)

例子:

cardiffnlp/twitter-roberta-base-sentiment-latest

  • 这种模型,专门用来分析推特情感的。

路径2:嵌入模型 + 分类器(两步走)


步骤1:输入评论 → 嵌入模型 → 得到768维向量  

步骤2:768维向量 → 分类器(如逻辑回归) → 输出类别  

为什么要分两步?

因为嵌入模型是“通用型选手“,它不是专门做情感分析的,而是把文本变成数字向量,可以用于各种任务。

形象理解:

步骤类比
嵌入模型把评论“翻译“成768个数字(就像把中文翻译成英文)
分类器看这768个数字,判断是好评还是差评(就像看英文判断含义)

三、路径1详解:使用特定任务模型

完整流程图

"Best movie ever!"   # 迄今为止最好的电影
    ↓  
[分词器]把句子切成词元:[Best] [movie] [ever] [!]  
    ↓  
[特定任务模型]处理这些词元  
    ↓  
输出:正面(标签=1)  

代码示例(超简化)

from transformers import pipeline  

# 1. 加载模型(就像下载一个APP)  
model = pipeline(  
    model="cardiffnlp/twitter-roberta-base-sentiment-latest",  
    device="cuda:0"  # 用GPU加速  
)  

# 2. 输入评论,直接得到结果  
result = model("Best movie ever!")  
# 输出:[{'label': '正面', 'score': 0.98}]  

关键点:

  • 分词器会先把句子切成词元(就像把句子切成词)
  • 模型处理这些词元,直接输出分类结果

四、路径 2 详解:嵌入模型 + 分类器

为什么要这样做?

场景:

  • 找不到专门做“电影评论情感分析“的模型
  • 但你有标注数据(知道哪些是好评、哪些是差评)
  • 不想花大价钱微调整个大模型

解决方案:

通用嵌入模型把文本变成向量,再训练一个轻量级分类器(如逻辑回归)。


步骤1:用嵌入模型提取特征 → 768 维度

from sentence_transformers import SentenceTransformer  

# 加载嵌入模型  
model = SentenceTransformer("sentence-transformers/all-mpnet-base-v2")  

# 把评论变成768维向量  
embedding = model.encode("Best movie ever!")  
# 结果:[0.12, -0.35, 0.78, ..., 0.45]  ← 768个数字  

这768个数字代表什么?

它们是评论的“数字指纹“,包含了这句话的语义信息。

形象理解:

就像把一个人的特征(身高、体重、年龄…)记录成一串数字。


步骤2:训练分类器

from sklearn.linear_model import LogisticRegression  

# 假设你有8530条评论的嵌入向量和标签  
train_embeddings = [向量1, 向量2, ..., 向量8530]  
train_labels = [1, 0, 1, ..., 0]  # 1=好评,0=差评  

# 训练分类器(在CPU上就能跑!)  
classifier = LogisticRegression()  
classifier.fit(train_embeddings, train_labels)  

# 测试新评论  
new_embedding = model.encode("What a horrible movie...")  
prediction = classifier.predict([new_embedding])  
# 输出:0(差评)  

关键优势:

  • 嵌入模型保持“冻结“(不用训练,节省资源)
  • 只训练轻量级分类器(在CPU上几秒钟就能完成)

五、路径对比:特定任务模型 vs 嵌入模型+分类器

对比项特定任务模型嵌入模型+分类器
准备工作找现成模型就行需要标注数据+训练分类器
灵活性只能做固定任务可以适配各种分类任务
计算资源推理需要GPU可以在CPU上完成
适用场景有现成模型可用需要定制化分类
效果通常更好(专门训练)也不错(书中F1=0.85)

六、架构图对比(核心理解)

特定任务模型架构

输入:"Best movie ever!"  
    ↓  
[特定任务模型]← 已经训练好,不可改  
    ↓  
输出:1(正面)  

特点: 一步到位,模型参数冻结不动。


嵌入模型+分类器架构

输入:"Best movie ever!"  
    ↓  
[嵌入模型]← 冻结不动  
    ↓  
768维向量:[0.12, -0.35, ...]  
    ↓  
[分类器]← 这部分可以训练  
    ↓  
输出:1(正面)  

特点: 两步走,嵌入模型冻结,只训练分类器。


七、实战技巧:没有标注数据怎么办?

问题:
收集标注数据很贵(需要人工标注成千上万条评论)。

解决方案:零样本分类

不需要训练,直接用嵌入向量的相似度来分类:

# 1. 给标签写描述  
label_descriptions = [  
    "A negative movie review",  # 负面评论的描述  
    "A positive movie review"   # 正面评论的描述  
]  

# 2. 生成标签的嵌入向量  
label_embeddings = model.encode(label_descriptions)  

# 3. 生成评论的嵌入向量  
review_embedding = model.encode("Best movie ever!")  

# 4. 计算相似度,选最像的标签  
from sklearn.metrics.pairwise import cosine_similarity  
similarities = cosine_similarity([review_embedding], label_embeddings)  
# 结果:[0.32, 0.91]  ← 和"正面评论"更像!  

核心思想:

如果评论的向量和“正面评论描述“的向量更接近,就判断为正面。

效果:

书中测试F1分数=0.78,虽然比有监督学习差一点(0.85),但完全不需要标注数据!


八、选模型的小贴士

Hugging Face上有6万多个文本分类模型、8000多个嵌入模型,怎么选?

考虑因素

  1. 底层架构:大部分用BERT(仅编码器架构)
  2. 语言支持:是否支持中文/英文
  3. 模型大小:参数越多越慢,但不一定效果更好
  4. 性能表现:看MTEB排行榜(嵌入模型)

推荐模型

特定任务模型:

  • cardiffnlp/twitter-roberta-base-sentiment-latest(推特情感分析)
  • distilbert-base-uncased-finetuned-sst-2(电影评论专用)

嵌入模型:

  • sentence-transformers/all-mpnet-base-v2(性能和速度平衡)

九、核心要点总结

概念通俗解释关键词
表示模型不会说话的模型,只输出数字BERT、DistilBERT
特定任务模型专门做某个任务(如情感分析)的模型开箱即用
嵌入模型把文本变成向量的通用模型768维向量
冻结模型参数不变,不需要训练省资源
零样本分类不需要标注数据的分类方法相似度计算

十、一句话总结

表示模型做分类有两种方式:

  1. 直接用特定任务模型(像用专业工具)
  2. 嵌入模型+分类器(像先翻译再判断)
  3. 即使没有标注数据,也能零样本分类凑合用

第一种简单直接,第二种更灵活;没标注数据还能用零样本分类凑合用!


最后,如果你想动手实践,可以直接在Google Colab上运行这些代码,无需本地安装任何软件!