写在前面:本博客全部基于知乎的大模型课程所做的笔记和整以及和在实操过程中遇到的问题和处理方法,(老师们讲的都很好,解答的也很细致)博主也正在学习中,如果有错误的地方期待和我沟通。大多代码都来自于上课的资料,加入了一些注释和梳理,或者对我没有跑通的代码做了一些修改让他符合我的需求。之前的链接:langchain 、AI框架
关于HuggingFace
什么是huggingface:(一个工具箱、库)
可以把HuggingFace看成:
**·**AI 界的 GitHub:
程序员找代码去 GitHub,AI 工程师找模型和数据去 HuggingFace(开源模型)。
它托管了全球最主流的开源模型(Llama, BERT, Stable Diffusion 等)。
**·**AI 界的 App Store:
它提供了很多现成的 Pipeline(集成工具),你不需要懂原理,就能在你的代码里跑起来(比如一键实现情感分析)。
国内替代版(modelscope),常用modelscope做下载,huggingface做使用。
langchain和huggingface有什么区别?
huggingface:是一个社区里面有很多可以下载的模型;也是一个库可以帮助跑下载后的模型、更底层、封装了一些pytorch的功能**(纯粹使用大模型本身)**
langchain:封装了llm,还有一些agent所需要的工具=>帮我们更好的开发agent应用,叫做agent智能体(大模型还要加....tool、mcp、memory等等)
huggingface的核心是什么
三个核心库
1.Transformers (库):
工具箱。提供了统一的 Python 接口,可以用几乎相同的代码加载 BERT、GPT 或 Llama。
主要分为三个流派,功能截然不同:
1)Encoder-Only (编码器架构)
代表模型:BERT
能力:擅长理解和分析。(做特征提取、分类任务)
像一个阅读理解满分的学生。你给它一篇文章,它能告诉你文章的情感是正面的还是负面的,或者提取出文章里的人名。
应用:文本分类、实体识别、搜索匹配。
2)Decoder-Only (解码器架构)
代表模型:GPT系列, Llama, Qwen
能力:擅长生成。(回答问题、展示输出)
像一个话唠小说家。你给它一个开头,它会根据概率不断猜下一个字是什么。
应用:聊天机器人、代码生成、创意写作。
3)Encoder-Decoder (编解码架构)(实战角度用的不多)
代表模型:T5, BART
能力:擅长转换。
像一个翻译官。听懂一句(Encode),然后重组成另一种语言说出来(Decode)。
应用:机器翻译、文本摘要。
2.Model Hub (网站):
仓库。存放模型权重文件(.bin 或 .safetensors)和配置文件(config.json)。
HuggingFace中都有哪些常用的模型
NLP(自然语言处理)领域
基础理解类(Encoder-Only):
BERT / RoBERTa:文本分类、命名实体识别(NER)(具体的识别专业名词的实体)的首选经典。
DistilBERT:BERT 的轻量化版本,推理速度更快,适合端侧应用。
生成类(Decoder-Only / 大语言模型):(常用)
Llama 系列 (Meta):目前最主流的开源大模型,适合对话、逻辑推理。
Qwen 系列 (阿里):中文能力极强,开源社区的热门选择。
DeepSeek 系列:近期极具性价比的国产模型,常用于生成和思考任务。
GPT-2:虽然较老,但因其轻量,常作为教学文本生成的入门案例。
翻译与摘要(Encoder-Decoder):
T5 / FLAN-T5:能够将所有 NLP 任务转换为"文本到文本"的格式。
BART:擅长文本纠错和长文档摘要。
CV(计算机视觉)与多模态领域
ViT (Vision Transformer):图像分类的标杆。
Stable Diffusion:目前最火的开源图像生成模型。
CLIP (OpenAI):连接文本与图像,常用于以图搜图或零样本分类。
(yolo是CNN基于神经网络的模型,参数小、速度快)
3.Datasets (数据库):
开源的数据库。一键下载维基百科、医疗问答、电商评论等海量数据集,并自动处理成模型能读的格式。
| 任务类型 | 常用数据集名称 | 简介 |
|---|---|---|
| 情感分析 | IMDb/Amazon Polarity | 5 万条电影评论 /3500 万条商品评论,带正负标签。 |
| 问答系统 | SQuAD/CoQA | 斯坦福问答数据集,用于训练模型提取文章中的答案。 |
| 大模型预训练 | FineWeb/C4 | 数千亿词规模的清洗后网页文本,是大模型进化的基石。 |
| 语音识别 | Common Voice | Mozilla 提供的多语言开源语音数据集。 |
| 代码生成 | MBPP/CodeContests | 包含数千个编程问题及其正确答案。 |
| 中文特定 | CLUECorpusSmall | 常用中文通用语料库,适合初学者训练中文小模型。 |
| [常用的数据库] |
什么是Tokenization?(分词)
模型不认识汉字或英文单词,它只认识数字。Tokenizer 是人类语言和机器数字之间的桥梁。
Input: "我爱HuggingFace"
Tokenize (切分): ['我', '爱', 'Hugging', '##Face'] (BERT常用WordPiece切分)
Convert to IDs (转数字): [2769, 4263, 12890, 8921](数值类型)
Output: 模型接收的就是这串数字向量。 最后输出反编译。
Tips: 不同的模型有专属的 Tokenizer,不能混用!用 BERT 的 Tokenizer 去处理数据喂给
GPT 模型,会报错或输出乱码。
不同语言模型的Token是如何定义的?
Token是大型语言模型处理文本的最小单位。由于模型本身无法直接理解文字,因此需要将文本切分成一个个Token,再将Token转换为数字(向量)进行运算。不同的模型使用不同的"分词器"(Tokenizer)来定义Token。
例如,对于英文 Hello World:
GPT-4o 会切分为 ["Hello", "World"] => 对应的 token id = [13225, 5922]
对于中文"人工智能你好啊":
DeepSeek-R1会切分为 ["人工智能", "你好", "啊"] => 对应的token id = [33574, 30594, 3266]
分词方式的不同会直接影响模型的效率和对语言细节的理解能力。
可以通过 https://tiktokenizer.vercel.app/ 这个工具看到不同模型是如何切分你输入的文本的。(类似一个翻译软件,可以在文本和模型所训练的固定数字之间相转化)
不同模型是不同的,处理什么语言的任务时最好使用同语言的模型,可以更清晰的转变且消耗token少一点
常见的特殊token
为了让模型更好地理解文本的结构和指令,开发者会预设一些具有特殊功能的Token。
这些Token不代表具体词义,而是作为一种"标点"或"命令"存在。
• 分隔符 (Separator Token):
用于区分不同的文本段落或角色。比如,在对话中区分用户和AI的发言,可能会用 <|user|> 和 <|assistant|> 这样的Token。
• 结束符 (End-of-Sentence/End-of-Text Token):
告知模型文本已经结束,可以停止生成了。常见的如 [EOS] 或 <|endoftext|>。这对于确保模型生成完整且不冗长的回答至关重要。
• 起始符 (Start Token):
标记序列的开始,例如 [CLS] (Classification) 或 [BOS] (Beginning of Sentence),帮助模型准备开始处理文本。
按照官方文档写 model.from_pretrained('bert-base-uncased'),在国内大概率会报ConnectionError。这是为什么?
不是你代码写错了,是网络问题。有两种最稳妥的解决方案。
方案 1:使用 HF-Mirror (镜像站)
不需要修改代码逻辑,只需要在运行 Python 之前设置一个环境变量,把流量指引到国内镜像站。
import os
设置环境变量,使用国内镜像站
os.environ['HF_ENDPOINT'] = 'https://hf-mirror.com'
from transformers import AutoModel, AutoTokenizer
此时会自动从镜像站下载,速度飞快
model = AutoModel.from_pretrained("bert-base-chinese")
在 Python 代码最开头(import transformers 之前)加入
方案 2:使用 ModelScope (魔搭社区)
使用阿里的 ModelScope 下载文件,然后用 HuggingFace 加载。
=> ModelScope 是下载工具,HuggingFace 是加载工具。
1. 安装 modelscope: pip install modelscope
from modelscope import snapshot_download
from transformers import AutoModel, AutoTokenizer
2. 从 ModelScope 下载模型文件到本地
这里的 qwen/Qwen2.5-0.5B 是魔搭上的模型ID,通常和HF同名
model_dir = snapshot_download('qwen/Qwen2.5-0.5B')
print(f"模型已下载到:{model_dir}")
3. 使用 HuggingFace 原生库加载(注意:这里传入的是
本地路径)
tokenizer = AutoTokenizer.from_pretrained(model_dir)
model = AutoModel.from_pretrained(model_dir)
4. 验证是否成功
print("模型加载成功!")
Pipeline与模型应用
Pipeline 是什么?
它是一个全自动的黑盒。当你把文本扔进去,它自动帮你完成三个繁琐的步骤:
• 预处理 (Tokenizer):把文本变成数字。
• 模型推理 (Model):模型进行计算,输出一堆看不懂的分数(Logits)。
• 后处理 (Post-processing):把分数变成人类能看懂的标签(比如 "Positive", 99%)。
关于租用服务器--autodl
下面我们来看一些实验,实验会涉及很多的模型调用,需要我们拥有较好的显卡或者服务器,这里给出租用服务器的一些小建议
租用服务器可以用autodl,国外的话可以考虑Google colab
怎么看选择多大显存的服务器:模型的数字乘3以上的都可以考虑。
eg. Qwen2.5-7B:7*3=21,可以用RTX 4090 / 24GB的服务器(因为24大于21)
我最近做项目一直在用autodl,觉得大多数个人项目应该很难做到按周按月租,这样太耗钱了(至少我自己是这样的,不用的时候我是关机的)那这样就很容易出现GPU不充足、无GPU可用的状态,这个时候一方面可以等到半夜或者周末会稍微好一点,不过相比之下在你的数据盘没有那么大整体迁移不是很难的情况下,可以尝试克隆实例,我之前就是每天等到大半夜去跑模型,后面换实例终于结束了我的阴间作息。
来看一些case,我们深入浅出的了解一下pipeline到底能干吗
case 1:情感分析
python
import os
# 必须在导入 pipeline 之前设置
os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"#用的huggingface的镜像文件
os.environ["HF_HOME"] = "/root/autodl-tmp/models" #定义好根目录在数据盘里(autodl-tmp),如果不定义很容易放到其他盘里
# 同时控制 model 和 tokenizer 缓存
from transformers import pipeline
# 1. 加载 pipeline
# 指定 task="sentiment-analysis"给定任务规范输出的方向
# 💡 技巧:如果不指定 model,默认下载英文模型。(下载后直接到hf------home里去)
# 这里我们指定一个中文微调过的模型,效果更好。
cache_dir = '/root/autodl-tmp/models'
classifier = pipeline(
task="sentiment-analysis",
model="uer/roberta-base-finetuned-dianping-chinese"
#model="bert-base-chinese"
)
# 2. 预测
result = classifier("这个手机屏幕太烂了,反应很慢!")
print(result)
# 输出示例:[{'label': 'negative (negative)', 'score': 0.98}]
result2 = classifier("物流很快,包装很精美,五星好评。")
print(result2)
# 输出示例:[{'label': 'positive (positive)', 'score': 0.99}]
我们定义了一个分类器,依靠pipeline和他的任务,之后就可以把相关的问题传给分类器即可得到回复。来看一下输出,这里pipeline直接给出了正负的情感反馈,以及评分(默认123为低分,45为高分),score相当于confidence,是模型对于自己给出答案准确程度的自信度:
{'label': 'negative (stars 1, 2 and 3)', 'score': 0.9923227429389954}
{'label': 'positive (stars 4 and 5)', 'score': 0.9825959205627441}
魔搭可以用bert base模型试试。
case2:文本生成
python
import os
os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"
os.environ["HF_HOME"] = "/root/autodl-tmp/models" # 同时控制 model 和 tokenizer 缓存
from transformers import pipeline
generator = pipeline(
task="text-generation",
model="uer/gpt2-chinese-cluecorpussmall",
device="cuda"#强制使用GPU
)
text = "在一个风雨交加的夜晚,程序员小李打开了电脑,突然"
result = generator(text, max_length=100, truncation=True, do_sample=True)
print(result[0]['generated_text'])
case3:零样本分类
python
import os
# 必须在导入 pipeline 之前设置
os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"
os.environ["HF_HOME"] = "/root/autodl-tmp/models" # 同时控制 model 和 tokenizer 缓存
from transformers import pipeline
# 加载零样本分类器 (推荐使用支持多语言的模型)
classifier = pipeline(
task="zero-shot-classification",
model="facebook/bart-large-mnli" # 这个模型虽然是英文的,但对简单中文也能理解,或者换用 multilingual 模型
)
text = "特斯拉发布了最新的自动驾驶技术,股价大涨。"
candidate_labels = ["体育", "财经", "娱乐", "科技"]
# 让模型自己去匹配
result = classifier(text, candidate_labels)
print(f"文本内容:{text}")
print(f"预测标签:{result['labels'][0]} (置信度: {result['scores'][0]:.4f})")
# 输出示例:科技 (0.85) 或 财经
来看输出:
文本内容:特斯拉发布了最新的自动驾驶技术,股价大涨。
预测标签:科技 ( 置信度 : 0.4399)
Huggingface的Pipeline很好用,还要不要了解pipeline里面都封装了什么?还是直接用就可以了?
Huggingface是傻瓜相机,可以直接用。如果想要深度定制,或者微调模型,就要把 Pipeline 拆开
核心组件 1:Tokenizer (分词器)
作用:把文本变成 Tensor (张量)(GPU中的数值)。
• 加载词表:必须和模型配套(不能用 BERT 的字典查 GPT 的词)。
• Padding (填充):把短句子补长(通常补 0),因为 GPU 喜欢整齐的矩阵。
• Truncation (截断):把太长的句子切掉,因为模型有最大长度限制(如 512)。
padding 和 truncation 是批处理数据的关键。
case4:tokenizer使用
Tensor:张量,在GPU上的一个数据结构,帮你完成任务的多维数组。利用GPU内的矩阵做运算
python
import os
# 必须在导入 pipeline 之前设置
os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"
os.environ["HF_HOME"] = "/root/autodl-tmp/models" # 同时控制 model 和 tokenizer 缓存
from transformers import AutoTokenizer
# 加载分词器
tokenizer = AutoTokenizer.from_pretrained("bert-base-chinese")
#制定一个模型做分词,做中文任务时最好用中文模型
# 模拟一个 Batch(两个长度不一样的句子)
sentences = ["我爱AI", "HuggingFace真好用"]
# 调用分词器
inputs = tokenizer(
sentences,
padding=True, # 自动填充到最长句子的长度
truncation=True, # 超过最大长度就截断
max_length=10, # 设置最大长度
return_tensors="pt" # 返回 PyTorch 张量
)
print(inputs)
# 重点观察:
# 'input_ids': 你的字对应的数字
# 'attention_mask': 1代表是真实的字,0代表是填充的(Padding)
{'input_ids': tensor([[ 101, 2769, 4263, 100, 102, 0],
101, 100, 4696, 1962, 4500, 102\]\]), 'token_type_ids': tensor(\[\[0, 0, 0, 0, 0, 0\], \[0, 0, 0, 0, 0, 0\]\]), 'attention_mask': tensor(\[\[1, 1, 1, 1, 1, 0\],
让AI做运算
第一步,分词->ids
第二步:推理->input ids放到model中进行计算
第三步:后处理-> 做转换,换成中文/图片/想要的格式
在Huggingface中经常会看到 AutoModel vs AutoModelFor... 这两个分别是什么?
核心组件2:model
AutoModel(Base Model):只有大脑。它输出的是隐藏状态 (Hidden States),一堆高维向量
=> 人类看不懂,适合做从头搭建网络。(做特征理解)
AutoModelForSequenceClassification(带头模型):大脑 + 嘴巴。(加了一个转换头)
=> 它在 Base Model 后面加了一个全连接层(Classification Head),直接输出分类的分数。
case5:model使用
python
import os
# 必须在导入 pipeline 之前设置
os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"
os.environ["HF_HOME"] = "/root/autodl-tmp/models" # 同时控制 model 和 tokenizer 缓存
from transformers import AutoModel, AutoModelForSequenceClassification
# 1. 纯净版模型
base_model = AutoModel.from_pretrained("bert-base-chinese")
base_model
# 输出形状:(Batch_Size, Sequence_Length, Hidden_Size) -> (2, 10, 768)
# 2. 带分类头的模型
cls_model = AutoModelForSequenceClassification.from_pretrained("bert-base-chinese", num_labels=2)
# 输出形状:(Batch_Size, Num_Labels) -> (2, 2)
cls_model
代码完全符合两种model,如果运行纯净版,只会看到一系列关于神经网络之类的流程,运行加转换头的,会多这样一段话,显示将原有的768个维度的特征变成2分类特征输出。
(dropout): Dropout(p=0.1, inplace=False)
(classifier): Linear(in_features=768, out_features=2, bias=True)
case6:手写从输入文本获得概率的全过程
在此之前,我们都是调用pipeline里的功能直接用或者展示里面的功能,那么他到底里面是怎么运转的呢,我们拆开来看一下。
pipeline像一个全自动黑盒,好用但掩盖了底层逻辑。
我们来手写一个舆情分类项目,了解一下tokenizer、model、和后处理(post-processing)三大核心组件的协作方式。这里和前面的case不同的是,它相当于把pipeline拆开了拆成三部分来做。(如果有需要自我diy或者微调模型的就需要掌握这方面)
python
import os
# 必须在导入 pipeline 之前设置
os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"
os.environ["HF_HOME"] = "/root/autodl-tmp/models" # 同时控制 model 和 tokenizer 缓存
import torch
import torch.nn.functional as F
from transformers import AutoTokenizer, AutoModelForSequenceClassification
# 1. 准备工作
checkpoint = "uer/roberta-base-finetuned-dianping-chinese"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)#分词
model = AutoModelForSequenceClassification.from_pretrained(checkpoint)#做任务
# 2. 原始文本
text = "这家餐厅太难吃了,服务员态度还差!"
# 3. Step 1: Tokenize (预处理)
inputs = tokenizer(text, return_tensors="pt")
# inputs 包含 input_ids 和 attention_mask
# 4. Step 2: Model Inference (模型推理)
# 不需要计算梯度,节省内存
with torch.no_grad():
outputs = model(**inputs)
# 获取 Logits (未归一化的分数)
logits = outputs.logits
print(f"模型原始输出 (Logits): {logits}")
# 5. Step 3: Post-processing (后处理)
# 使用 Softmax 将 logits 转换为概率
probabilities = F.softmax(logits, dim=-1)
print(f"概率分布: {probabilities}")
# 获取概率最大的标签索引
predicted_id = torch.argmax(probabilities).item()
# 使用 model.config.id2label 查表得到人类可读标签
predicted_label = model.config.id2label[predicted_id]
print(f"最终结果: {predicted_label}")
输出:
模型原始输出 (Logits): tensor([[ 2.8590, -2.7449]])
概率分布 : tensor([[0.9963, 0.0037]])( 两数相加等于1分别是正向的和负向的概率值取大值判断情感)
最终结果 : negative (stars 1, 2 and 3)
我们来总结一下pipeline干了什么:
1、预处理(tokenizer):inputs = tokenizer(text,return_tensor="pt")
将文本切分成token并映射为模型认识的数字ID(inputs_ids)和编码(attention_mask),返回pytorch张量格式。
2、模型推理(model inference):outputs = model(**inputs)
将张量喂给模型进行前向传播,使用torch.no_gard()禁用梯度计算能有效减少推理时的显存占用并加速运算。
3、获取logits:logits = outputs.logits模型直接输出的是logits(未归一化的分数),是分类前的原始预测结果,无法直接阅读。
4、后处理(post-processing):probabilities = F.softmax(logits,dim=-1)
通过softmax函数将logits转换为总和为1的概率分布,最后利用id2label映射表,将概率最大的索引表转换为最终的标签名称(如negative)
pipeline 是 HuggingFace 提供的最简易接口,只需指定 task 名称即可直接调用。
task可选的任务是模型提供的,模型之前就封装好的
• NLP (自然语言处理、文本)常用任务
sentiment-analysis:情感分析,判断文本褒贬。
text-generation:文本生成,如写故事、续写代码。
zero-shot-classification:零样本分类,无需训练即可根据自定义标签分类。
question-answering:问答系统,根据给定的上下文回答问题。
summarization:自动摘要,将长文浓缩为短句。
translation_xx_to_yy:翻译任务,如 translation_en_to_zh。
ner:命名实体识别,提取人名、地名、组织名。
• CV(计算机视觉) & 音频 常用任务
image-classification:图像分类。
object-detection:目标检测,识别图中的物体并定位。
automatic-speech-recognition (ASR):语音转文字。
text-to-speech (TTS):文字转语音。
model是参数里面有很多层
input -> hidden layer1,....,->output
每一层里有很多参数,每个参数我们叫做神经元,每个神经元都有一个变量,让神经元拟合成一个合适的参数。
全量微调
什么时候需要微调:
1、原始的训练预料和目标的预料不一致的时候
eg.bert使用的是公开的互联网语料,认为恭喜你中奖了是好的;现在目标环境是针对邮件处理,认为恭喜你中奖了是不好的。
2、风格转换
eg.假设之前的bert是比较工整的话术,打算训练更日常更调皮的风格,要准备这个环境下的大量语料。
3、有事先独立数据库
eg.金融智能客服、银行专员,需要事先熟悉金融知识和银行的工作流程。大模型懂市场懂宏观,但他不了解具体岗位具体公司的内部信息,需要职前培训。
核心工具
1、数据加载与清洗 (Datasets)
在实际工作中,数据通常不在 Hub 上,而在你的 CSV 或 Excel 里。
• 加载:load_dataset("csv", data_files="my_data.csv")
• Map 函数 (神器):
作用:它不是简单的 for 循环,而是支持多进程的并行处理。
操作:我们需要把文本列(Text)批量转换成数字列(Input IDs)。
2、DataCollator:动态补齐
• 痛点:BERT 模型要求同一批(Batch)进来的数据长度必须一致。
• 传统做法:不管句子多长,全部补齐到 512。
缺点:如果一句话只有 10 个字,你补了 502 个 0,显卡在疯狂计算无效的 0,浪费显存和时间。
• 聪明做法 (动态补齐):在训练时,看这一批数据(比如 16 条)里最长的那句是多少(比如 50)。把其他 15 条都只补齐到 50。
结果:训练速度极大提升,显存占用大幅下降。
微调到底要多少数据:和任务难度和多样性相关
只是想训练好还是不好:1000条也可以
假如场景丰富、情感复杂:100万个也有可能
训练神器:trainer api(用来微调)
(还有一个PEFT高效微调:也是huggingface中的微调工具)
在 HuggingFace 出现之前,写一个训练循环需要手动写出所有步骤。
你要自己写 Forward(前向传播), Backward(反向传播), Optimizer.step(参数优化), Zero_grad(梯度清零)... 写错一步模型就不收敛。
现在,Trainer 把这些脏活累活全包了。
|------|---------------------------------|-----------------------------|
| 维度 | 传统 PyTorch 写法 | HuggingFace Trainer |
| 代码量 | 50+ 行循环代码 | 实例化 1 个类 |
| 功能支持 | 需手写日志、保存、断点续训 | 开箱即用 (Checkpoints, Logging) |
| 硬件优化 | 需手动配置混合精度 (fp16) | 参数 fp16=True 即可 |
| 多卡训练 | 配置 DistributedDataParallel (极难) | 自动适配多卡 |
case:垃圾邮件分类器
使用 HuggingFace 的 Transformers 库,基于预训练的 BERT 中文模型(bert-base-chinese)进行微调,构建一个能够自动识别垃圾邮件的分类器。
这里用ipynb的jupyter形式展现,如果运行完整代码的话需要全部复制,jupyter中可一段段来。
step1:准备环境与数据
首先配置 HuggingFace 镜像站,确保在国内环境下能够顺利下载模型
准备训练数据,每条数据包含文本内容和标签(0表示正常,1表示垃圾):
看最后一行,需要划分测试集和训练集,如果所有数据全部拿来训练确实会有更好的训练结果,但是没有测试数据来验证,无法对效果有更直观的体会。
python
import os
# 必须在导入 pipeline 之前设置
os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"
os.environ["HF_HOME"] = "/root/autodl-tmp/models" # 同时控制 model 和 tokenizer 缓存
import torch
from transformers import AutoTokenizer, AutoModelForSequenceClassification, Trainer, TrainingArguments
from datasets import Dataset
# 1. 模拟一个私有数据集 (真实场景用 load_dataset 加载 CSV)
data = [
{"text": "今晚有空一起吃饭吗?", "label": 0}, # 正常
{"text": "恭喜您获得500万大奖,点击领取", "label": 1}, # 垃圾
{"text": "您的验证码是1234,请勿泄露", "label": 0},
{"text": "澳门首家线上赌场上线啦", "label": 1},
{"text": "项目进度怎么样了?需不需要开会", "label": 0},
{"text": "独家内幕消息,股票必涨,加群", "label": 1},
]
# 转为 HF Dataset 对象
dataset = Dataset.from_list(data)
# 2. 划分训练集和测试集
dataset = dataset.train_test_split(test_size=0.2)
Step2,数据预处理(Tokenization)
使用 BERT 的 Tokenizer 将文本转换为模型可理解的数字序列。这里的关键是不进行 Padding,留给 DataCollator 动态处理。
选择模型微调,选择这个模型适配的tokenizer。
python
checkpoint = "bert-base-chinese"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
def preprocess_function(examples):
# Truncation=True: 截断过长的
# Padding=False: 这里先不补齐!留给 DataCollator 动态补齐,避免浪费显存
return tokenizer(examples["text"], truncation=True, max_length=128)
# 批量处理
tokenized_datasets = dataset.map(preprocess_function, batched=True)
Step3 , DataCollator 动态补齐
传统做法是将所有样本补齐到固定长度(如512),这会浪费大量显存。动态补齐,只补齐到当前批次中最长的长度,大幅提升训练效率。
python
from transformers import DataCollatorWithPadding
# 动态补齐工具
data_collator = DataCollatorWithPadding(tokenizer=tokenizer)
Step4,模型加载
加载带分类头的 BERT 模型,num_labels=2 表示二分类任务。
python
# 加载带分类头的模型 (num_labels=2: 二分类)
model = AutoModelForSequenceClassification.from_pretrained(checkpoint, num_labels=2)
AutoModelForSequenceClassification 在基础 BERT 模型后添加了分类头,可以直接输出分类结果。
Step5,评估指标定义
定义准确率作为评估指标,预测结果和参考答案进行对比。
python
import numpy as np
import evaluate # pip install evaluate
# 加载评估指标
metric = evaluate.load("accuracy")
def compute_metrics(eval_pred):
"""计算评估指标"""
logits, labels = eval_pred
predictions = np.argmax(logits, axis=-1)
return metric.compute(predictions=predictions, references=labels)
Step6,训练配置与执行
使用 Trainer API 简化训练流程,只需配置参数即可
学习率大效果好但是不稳定,小的话更稳定慢慢调整。
python
training_args = TrainingArguments(
output_dir="/root/autodl-tmp/models/spam-bert-finetuned", # 模型保存路径(微调后的模型)
eval_strategy="epoch", # 每个 epoch 结束后评估一次
save_strategy="epoch", # 每个 epoch 结束后保存一次
learning_rate=2e-5, # 学习率 (微调通常很小)
per_device_train_batch_size=4, # 批次大小 (显存小就调小)
num_train_epochs=3, # 训练轮数
weight_decay=0.01,
logging_steps=10,
)
trainer = Trainer(
model=model,
args=training_args,
train_dataset=tokenized_datasets["train"],#已经转换成分词了
eval_dataset=tokenized_datasets["test"],
tokenizer=tokenizer,
data_collator=data_collator,
compute_metrics=compute_metrics,
)
# 开始训练!
trainer.train()
tariner优势:自动处理训练循环(Forward、Backward、Optimizer)支持混合精度训练、多卡训练;自动保存检查点、记录日志。
Step7,模型推理
训练完成后,使用模型进行预测
python
# 模拟一条新数据
text = "澳门线上赌场,特价酬宾"
inputs = tokenizer(text, return_tensors="pt").to(model.device) # 确保数据也在 GPU 上
with torch.no_grad():
logits = model(**inputs).logits
predicted_class_id = logits.argmax().item()
print(f"输入文本: {text}")
print(f"预测类别: {'垃圾邮件' if predicted_class_id == 1 else '正常邮件'}")
输出:
输入文本: 澳门线上赌场,特价酬宾 预测类别: 垃圾邮件
总结一下:
微调 vs 预训练:预训练模型已经具备语言理解能力,微调只需要少量领域数据即可适应特定任务
动态补齐:使用 DataCollatorWithPadding 实现批次级别的动态补齐,提升训练效率
Trainer API:封装了训练的所有细节,让开发者专注于数据和模型本身
评估策略:每个 epoch 结束后进行评估和保存,便于监控训练过程
HuggingFace 生态简化 NLP 任务的开发流程,从数据准备到模型训练,再到最终推理,整个过程清晰高效。
如果用国内的大语言模型呢?
case:垃圾邮件分类器-Qwen
使用大语言模型(Qwen),通过精心设计的 Prompt 让模型理解任务并生成分类结果,无需训练。 针对国内的环境,模型下载可以使用 modelscope。和上面的区别不大,最主要的核心就是训练还是用prompt(提示词)的区别,下面是一些名词解释。
ModelScope 是下载工具:负责从魔搭社区下载模型文件
HuggingFace 是加载工具(还有dashscope等工具):使用统一的 Transformers API加载和使用
AutoModelForCausalLM:因果语言模型,用于文本生成
device_map="auto":自动分配设备,支持多 GPU
model.generate() :生成文本,而不是直接分类
Pipeline 封装了 tokenize、generate、decode 流程,代码更简洁,适合快速原型开发。
总结一下:
基座模型:大模型,qwen能力强参数量大,GPU要求高;bert-base-Chinese等
1、BERT 微调方式: 文本 → Tokenize → 模型前向传播 → Logits → argmax → 类别ID
2、大模型 Prompt 方式:
文本 → 构建 Prompt → Tokenize → 模型生成 → 解码文本 → 解析结果 → 类别
Thinking:什么时候用BERT微调,什么时候用大模型?
BERT:有大量标注数据,任务固定,需要高准确率,快速推理(生产环境),显存有限(1-2GB)
大模型:没有标注数据,任务多样,需要快速验证,需要零样本学习能力,有足够的显存(8GB+)
超参数(人工可以调配的参数,在模型之前的用于训练模型的设置)如何调优?
num_train_epochs = 3:一般选择训练3-6轮,如果再多容易过拟合,记住答案了。
learning_rate(学习率) =2e-5:1e-5(小数点后五位)到1e-2
学习率代表学习的速度,调参数的幅度,像步长
输入到大模型中后又输出,RAG在输出中增强,模型微调在大模型这增强。
纯粹课堂笔记,有任何侵权,联系我,马上删。