从BERT到ChatGPT:一文精通文本分类的N种姿势(附代码) 📅 发布时间:2026/7/4 11:37:18 👁️ 浏览次数: 文本分类是自然语言处理NLP中最常见、最基础的任务之一。从情感分析、垃圾邮件过滤到意图识别、新闻分类它几乎无处不在。随着预训练语言模型的爆发文本分类的技术栈也发生了翻天覆地的变化。今天我们就用实战的方式带你从头到尾梳理表示模型和生成模型在文本分类中的应用并对比它们的优缺点。文章最后还有各种方法的F1分数对比帮你快速选型。1. 什么是文本分类简单说文本分类就是给一段文本打上一个预定义的标签。比如“这部电影太棒了” →正面“物流太慢了差评” →负面在传统的机器学习时代我们通常用TF-IDF提取特征再训练一个分类器如逻辑回归、SVM。但现在的语言模型时代我们有了更强大的工具预训练语言模型。它们已经在海量数据上学会了语言的通用表示我们只需要稍作调整就能在具体任务上达到惊人的效果。根据模型结构的不同文本分类可以分为两大流派表示模型Representation Models如BERT、RoBERTa它们擅长将文本编码为固定长度的向量然后基于这个向量做分类。生成模型Generative Models如GPT、T5它们本质上是文本到文本的模型通过生成文本来完成分类比如直接输出“positive”或“negative”。本文将以著名的烂番茄电影评论数据集rotten_tomatoes为测试床手把手带你体验这两种流派的各种玩法。2. 数据准备烂番茄电影评论我们使用Hugging Face的datasets库加载数据pythonfrom datasets import load_dataset data load_dataset(rotten_tomatoes) print(data)输出textDatasetDict({ train: Dataset({ features: [text, label], num_rows: 8530 }) validation: Dataset({ features: [text, label], num_rows: 1066 }) test: Dataset({ features: [text, label], num_rows: 1066 }) })数据集包含正负面评论各约5300条标签0表示负面1表示正面。看看几个样本pythonprint(data[train][0]) # {text: the rock is destined to be the 21st century\s new conan and that he\s going to make a splash even greater than arnold schwarzenegger , jean-claud van damme or steven segal ., label: 1} print(data[train][1]) # {text: things really get weird , though not particularly scary : the movie is all portent and no content ., label: 0}接下来我们就用这个数据集测试各种模型。3. 使用表示模型进行文本分类表示模型的核心是将文本编码成一个稠密向量然后基于这个向量进行分类。这里有两种常见的用法3.1 特定任务模型Task-Specific Models这类模型已经在某个任务上如情感分析微调过你可以直接拿来用无需再训练。比如Hugging Face上的cardiffnlp/twitter-roberta-base-sentiment-latest它是在推文上微调的RoBERTa模型虽然领域是社交媒体但我们可以看看它在电影评论上的泛化能力。pythonfrom transformers import pipeline model_path cardiffnlp/twitter-roberta-base-sentiment-latest pipe pipeline( modelmodel_path, tokenizermodel_path, return_all_scoresTrue, devicecuda:0 # 如果有GPU )这里我们加载了模型和分词器Tokenizer。分词器的作用是把原始文本切成模型能理解的词元tokens比如把“vocalization”切成“vocal”和“##ization”。即使遇到生词也能通过子词组合来理解。接下来对整个测试集进行推理pythonimport numpy as np from tqdm import tqdm from transformers.pipelines.pt_utils import KeyDataset y_pred [] for output in tqdm(pipe(KeyDataset(data[test], text)), totallen(data[test])): negative_score output[0][score] positive_score output[2][score] assignment np.argmax([negative_score, positive_score]) y_pred.append(assignment)注意该模型输出三个分数负面、中性、正面我们只取负面和正面。3.2 评估指标精确率、召回率、F1我们需要一个函数来评估结果pythonfrom sklearn.metrics import classification_report def evaluate_performance(y_true, y_pred): performance classification_report( y_true, y_pred, target_names[Negative Review, Positive Review] ) print(performance)运行pythonevaluate_performance(data[test][label], y_pred)输出textprecision recall f1-score support Negative Review 0.76 0.88 0.81 533 Positive Review 0.86 0.72 0.78 533 accuracy 0.80 1066 macro avg 0.81 0.80 0.80 1066 weighted avg 0.81 0.80 0.80 1066这些指标的含义精确率预测为正例的样本中有多少是真正的正例。召回率真正的正例中有多少被找出来了。F1分数精确率和召回率的调和平均综合衡量模型性能。准确率全部预测中正确的比例。可以看到这个推文情感模型在电影评论上得到了0.80的F1分数相当不错了。如果想要更高可以找电影评论领域微调的模型比如基于DistilBERT在SST-2斯坦福情感树库上微调的版本。3.3 嵌入模型 传统分类器如果找不到现成的特定任务模型怎么办难道要自己微调大模型不一定。我们可以使用通用嵌入模型如sentence-transformers将文本转为向量然后用一个简单的分类器如逻辑回归在CPU上训练。这样既省资源又灵活。pythonfrom sentence_transformers import SentenceTransformer model SentenceTransformer(sentence-transformers/all-mpnet-base-v2) train_embeddings model.encode(data[train][text], show_progress_barTrue) test_embeddings model.encode(data[test][text], show_progress_barTrue)每个文本被编码成768维的向量。接下来训练逻辑回归pythonfrom sklearn.linear_model import LogisticRegression clf LogisticRegression(random_state42) clf.fit(train_embeddings, data[train][label]) y_pred clf.predict(test_embeddings) evaluate_performance(data[test][label], y_pred)结果textprecision recall f1-score support Negative Review 0.85 0.86 0.85 533 Positive Review 0.86 0.85 0.85 533 accuracy 0.85 1066 macro avg 0.85 0.85 0.85 1066 weighted avg 0.85 0.85 0.85 1066F1提升到了0.85这说明即使嵌入模型本身没有在电影评论上微调但它的通用语义表示能力足够强加上一个简单的分类器就能超过特定任务模型。这种方法特别适合有少量标注数据的场景。3.4 零样本分类没有标注数据怎么办现实工作中我们常常连一条标注数据都没有只有几个标签的名字。这时候还能用嵌入模型吗当然可以我们可以用标签描述来代替标注数据。比如我们给标签起个描述“A negative review” 和 “A positive review”。然后分别计算每个评论的嵌入向量与这两个标签描述的嵌入向量之间的余弦相似度相似度高的就是预测标签。pythonlabel_embeddings model.encode([A negative review, A positive review]) from sklearn.metrics.pairwise import cosine_similarity sim_matrix cosine_similarity(test_embeddings, label_embeddings) y_pred np.argmax(sim_matrix, axis1) evaluate_performance(data[test][label], y_pred)结果textprecision recall f1-score support Negative Review 0.78 0.77 0.78 533 Positive Review 0.77 0.79 0.78 533 accuracy 0.78 1066 macro avg 0.78 0.78 0.78 1066 weighted avg 0.78 0.78 0.78 10660.78的F1在没有用任何标注数据的情况下这个成绩已经非常惊艳了而且你还可以优化标签描述比如改成“A very negative movie review”和“A very positive movie review”可能会得到更好的结果。这种方法的本质是把分类任务转化成了文本相似度匹配任务非常巧妙。4. 使用生成模型进行文本分类生成模型如GPT、T5接收文本输出文本。所以我们需要通过提示词prompt来引导模型输出我们想要的标签。这种方式不需要微调模型只需要设计好的提示。4.1 用T5/FLAN-T5做分类T5Text-to-Text Transfer Transformer是一种编码器-解码器模型把所有NLP任务都统一成“文本到文本”的形式。FLAN-T5是在T5基础上用大量任务指令微调过的版本对指令的理解能力更强。我们加载最小的FLAN-T5-smallpythonpipe pipeline( text2text-generation, modelgoogle/flan-t5-small, devicecuda:0 )然后给每个样本加上提示“Is the following sentence positive or negative? ”pythondef add_prompt(example): example[t5] Is the following sentence positive or negative? example[text] return example data data.map(add_prompt)现在推理pythony_pred [] for output in tqdm(pipe(KeyDataset(data[test], t5)), totallen(data[test])): text output[0][generated_text] y_pred.append(0 if text negative else 1)评估textprecision recall f1-score support Negative Review 0.83 0.85 0.84 533 Positive Review 0.85 0.83 0.84 533 accuracy 0.84 1066 macro avg 0.84 0.84 0.84 1066 weighted avg 0.84 0.84 0.84 10660.84的F1超过了之前的特定任务模型和嵌入逻辑回归相当。注意这里只用了一个很小的FLAN-T5-small如果换更大的版本base/large/XL效果还会更好。4.2 用ChatGPTGPT-3.5做分类专有模型如ChatGPT可以通过API调用无需本地GPU。首先创建客户端pythonimport openai client openai.OpenAI(api_key你的key)定义一个函数来调用模型pythondef chatgpt_generation(prompt, document, modelgpt-3.5-turbo): messages [ {role: system, content: You are a helpful assistant.}, {role: user, content: prompt.replace([DOCUMENT], document)} ] chat_completion client.chat.completions.create( messagesmessages, modelmodel, temperature0 ) return chat_completion.choices[0].message.content设计提示词pythonprompt Predict whether the following document is a positive or negative movie review: [DOCUMENT] If it is positive return 1 and if it is negative return 0. Do not give any other answers.然后对测试集运行注意控制成本测试集有1066条但OpenAI有免费额度pythonpredictions [chatgpt_generation(prompt, doc) for doc in tqdm(data[test][text])] y_pred [int(pred) for pred in predictions] evaluate_performance(data[test][label], y_pred)结果textprecision recall f1-score support Negative Review 0.87 0.97 0.92 533 Positive Review 0.96 0.86 0.91 533 accuracy 0.91 1066 macro avg 0.92 0.91 0.91 1066 weighted avg 0.92 0.91 0.91 1066F1高达0.91这充分展示了GPT-3.5的强大能力。不过需要注意的是我们不知道GPT的训练数据中是否包含了烂番茄数据集所以这个分数可能有数据泄露的嫌疑。但在实际应用中这种“开箱即用”的性能确实很吸引人。5. 方法对比与总结方法F1分数是否需要标注数据是否需要训练优点缺点特定任务模型Twitter-roBERTa0.80否否即插即用领域可能不匹配嵌入模型 逻辑回归0.85是是分类器资源消耗小效果好需要少量标注数据嵌入模型 零样本相似度0.78否否完全零样本灵活需要设计好的标签描述FLAN-T5-small生成式0.84否否指令理解好开源生成速度较慢ChatGPTGPT-3.50.91否否效果极佳无需资源收费可能存在数据泄露小结文本分类早已不是“TF-IDF SVM”的天下。预训练语言模型为我们提供了多种灵活的选择如果你有标注数据且资源有限嵌入模型轻量分类器是性价比之王。如果零样本且任务明确可以尝试特定任务模型或FLAN-T5等指令模型。如果不差钱且追求极致效果GPT-4等专有模型能给你惊喜。如果连标签定义都不明确还可以用嵌入相似度做探索性分析。无论哪种方法理解其背后的原理分词、嵌入、注意力都能帮助你更好地应用和调试。希望这篇文章能帮你理清思路在实际项目中选出最适合的文本分类方案。本文参考图解大模型生成式AI原理与实战书籍pdf免费下载地址https://pan.baidu.com/s/1mTaUQ5czcfGpBM8KvJuS2g?pwdun44
AI营销新纪元:如何选择靠谱的人工智能服务商,实现业绩指数级增长? 在数字化转型浪潮席卷各行各业的今天,人工智能已不再是遥不可及的未来科技,而是企业降本增效、抢占市场的核心引擎。尤其在企业营销领域,从内容创作、客户触达、互动响应到销售转化,AI正重塑着每一个环节。然而,面对市… 2026/5/17 11:51:55
安装OpenClaw对电脑配置有什么要求?旧电脑能跑得动吗?深度解析 # 一人公司的技术实现:OpenClaw究竟带来了什么? 最近在技术圈里,“一人公司”这个概念被讨论得越来越多。不是指真的只有一个人的公司,而是指一个人借助现代技术工具,能够完成过去需要一个团队才能完成的工作量。这听起… 2026/5/17 11:51:55
Quartz 2D还可以将图像绘制到图形上下文。 (void)drawImage:(CGContextRef)context{UIImage *image[UIImage imageNamed:"image2.jpg"];//从某一点开始绘制[image drawAtPoint:CGPointMake(10, 50)];//绘制到指定的矩形中,注意如果大小不合适会会进行拉伸 // [image drawInRect:CGRectMake(10, … 2026/7/4 11:36:40
基于LangChain与函数调用构建AI智能体:从原理到工程实践 🚀 30款热门AI模型一站整合,DeepSeek/GLM/Claude 随心用,限时 5 折。 👉 点击领海量免费额度 在实际 AI 应用开发中,我们常常面临一个核心矛盾:如何让一个强大的大语言模型(LLM)去… 2026/7/4 11:34:39
机器学习实战成长路线图:从环境配置到模型部署的七步实操指南 1. 这不是“速成指南”,而是一份我亲手踩过坑、重写过三次的ML成长路线图你点开这篇文章,大概率正坐在凌晨一点的台灯下,浏览器开着三四个标签页:一个在查“sigmoid函数为什么能做二分类”,一个在翻Kaggle入门赛的base… 2026/7/4 11:34:39
嵌入式系统独立定时器设计与应用实践 1. 为什么需要独立定时系统?在嵌入式开发中,时间管理一直是个让人头疼的问题。我曾经接手过一个工业控制项目,系统运行几天后就会莫名其妙地死机。经过一周的排查,最终发现问题出在STM32内部RTC的时钟漂移上——由于晶振温度特性不… 2026/7/4 11:32:38
Kimi Agent四维赛马评估法:穿透力、耐受度、适应性、成本确定性 1. 项目概述:当优质Agent不止一个,如何科学“赛马”选出真王者?最近在深度测试Kimi K2.5的Agent能力时,我遇到一个非常现实、也特别容易被忽略的问题:不是“有没有好Agent”,而是“一下子冒出好几个看起来都… 2026/7/4 11:30:37
RSA弱密钥漏洞深度剖析:从素数生成到实战检测与防御 1. 项目概述:从一次内部安全审计说起去年年底,我们团队在对一个自研的金融数据传输中间件进行例行安全审计时,发现了一个令人后背发凉的问题。这个中间件使用了RSA算法对关键的交易指令进行签名和验签,以确保指令的完整性和不可否… 2026/7/4 11:30:37
STM32F745VG与MC6470 IMU的高性能姿态控制系统设计 1. MC6470与STM32F745VG的黄金组合解析在工业自动化和机器人控制领域,传感器与微控制器的协同工作能力直接决定了系统的响应速度和定位精度。MC6470作为一款6自由度惯性测量单元(6DOF IMU),与STM32F745VG这款基于ARM Cortex-M7内核的高性能微控制器组合&… 2026/7/4 0:00:28
Playwright自动化测试实战:从零搭建现代Web测试框架 1. 项目概述:为什么是 Playwright?如果你正在为现代 Web 应用的自动化测试头疼,尤其是面对那些充斥着动态加载、复杂交互的单页应用(SPA),那么 Playwright 的出现,很可能就是你的解药。我接触过… 2026/7/4 0:00:28
终极指南:如何将JSXBIN二进制文件转换为可读JSX源代码 终极指南:如何将JSXBIN二进制文件转换为可读JSX源代码 【免费下载链接】jsxbin-to-jsx-converter JSXBin to JSX Converter written in C# 项目地址: https://gitcode.com/gh_mirrors/js/jsxbin-to-jsx-converter 你是否曾经面对过Adobe产品的JSXBIN文件感到… 2026/7/4 0:02:28