楼层: 首页/ 软件技术/ Python 机器学习与深度学习/ HuggingFace Transformers 入门
13

HuggingFace Transformers 入门

HuggingFace: BERT / GPT / PEFT

HuggingFace 是"AI 界的 GitHub":几十万预训练模型 + 统一 API。你不用自己训 BERT,三行代码下载别人训好的,微调几轮就能用。

核心三件套

组件干什么
AutoTokenizer把文本切成模型认识的 token id。
AutoModelForXxx加载预训练模型,按任务选(ForSequenceClassification / ForCausalLM / ForTokenClassification ...)。
Trainer封装好的训练循环,一行 fit。

Transformer 一句话原理

论注意力机制

Transformer 的核心是自注意力(Self-Attention):序列里每个词都和其他所有词算一个"相关度"权重,然后加权求和得到新的表示。一句话里,"它"这个词会自动关注到前文最近的名词。BERT 用双向注意力(看左右上下文),GPT 用单向注意力(只看左边)。多头注意力(Multi-Head)相当于多个角度看关系。

BERT 架构速览

# BERT-base 结构: # - 12 层 Transformer Encoder # - 隐藏维度 768 # - 12 个注意力头 # - 总参数 110M # - 最大序列长度 512 token # 特殊 token: # [CLS] 句首,分类任务用它的输出 # [SEP] 句尾/句间分隔 # [PAD] padding # [MASK] MLM 预训练时遮住的词 # 预训练任务: # 1. MLM(Masked Language Model):遮住 15% 的词让模型猜 # 2. NSP(Next Sentence Prediction):判断两句话是否连续

一行代码用模型:pipeline

from transformers import pipeline # 情感分析 classifier = pipeline("sentiment-analysis") print(classifier("这个产品真的太好用了!")) # [{'label': 'POSITIVE', 'score': 0.9998}] # 文本生成 generator = pipeline("text-generation", model="gpt2") print(generator("今天天气真不错,我们", max_new_tokens=30))

Tokenizer:文本 → token id

from transformers import AutoTokenizer tok = AutoTokenizer.from_pretrained("bert-base-chinese") out = tok("今天天气真不错", padding=True, truncation=True, max_length=32, return_tensors="pt") print(out.keys()) # dict_keys(['input_ids', 'token_type_ids', 'attention_mask']) print(out["input_ids"]) # tensor([[ 101, 1962, 3698, 1962, 3362, 4696, 102]]) 101=[CLS], 102=[SEP]

完整案例:BERT 中文情感分析微调

from datasets import load_dataset from transformers import (AutoTokenizer, AutoModelForSequenceClassification, Trainer, TrainingArguments) # 1. 加载数据集(比如 ChnSentiCorp 中文影评) dataset = load_dataset("seamew/ChnSentiCorp") model_name = "bert-base-chinese" tokenizer = AutoTokenizer.from_pretrained(model_name) model = AutoModelForSequenceClassification.from_pretrained( model_name, num_labels=2 ) def tokenize(ex): return tokenizer(ex["text"], truncation=True, max_length=128) dataset = dataset.map(tokenize, batched=True) dataset = dataset.rename_column("label", "labels") dataset.set_format("torch", columns=["input_ids", "attention_mask", "labels"]) args = TrainingArguments( output_dir="./bert-chinese", learning_rate=2e-5, per_device_train_batch_size=16, num_train_epochs=3, evaluation_strategy="epoch", save_strategy="epoch", load_best_model_at_end=True, logging_steps=50, ) trainer = Trainer(model=model, args=args, train_dataset=dataset["train"], eval_dataset=dataset["validation"]) trainer.train() metrics = trainer.evaluate() print(metrics) # {'eval_accuracy': 0.94, 'eval_loss': 0.18}

Datasets 库:加载和处理数据集

from datasets import load_dataset # 1. 加载 HuggingFace Hub 上的数据集 ds = load_dataset("imdb", split="train") print(ds) # Dataset({features: ['text', 'label'], num_rows: 25000}) # 2. map:批量预处理 def tokenize_fn(example): return tokenizer(example["text"], truncation=True, max_length=128) ds = ds.map(tokenize_fn, batched=True) # 3. filter:按条件过滤 ds = ds.filter(lambda x: len(x["text"]) > 10) # 4. shuffle + train_test_split ds = ds.shuffle(seed=42) split = ds.train_test_split(test_size=0.1) # 5. 保存到磁盘,下次直接加载 ds.save_to_disk("./processed_dataset") # 加载:load_from_disk("./processed_dataset")

Tokenizer 算法对比

算法说明
WordPieceBERT 用,贪心合并高频子词。
BPEGPT 用,字节对编码,从字符开始合并。
UnigramT5 用,概率模型。
SentencePiece多语言,直接处理原始文本(不预分词)。

文本生成:generate 的采样参数

from transformers import AutoModelForCausalLM, AutoTokenizer model = AutoModelForCausalLM.from_pretrained("gpt2") tok = AutoTokenizer.from_pretrained("gpt2") inputs = tok("Once upon a time", return_tensors="pt") out = model.generate(**inputs, max_new_tokens=50, do_sample=True, temperature=0.7, # 越小越确定 top_p=0.9, # 核采样 top_k=50, num_beams=3, no_repeat_ngram_size=2 # 防止重复 ) print(tok.decode(out[0], skip_special_tokens=True))

PEFT / LoRA:微调大模型只训 0.1% 参数

论为什么需要 LoRA

7B 模型全微调要几十 GB 显存,普通人玩不起。LoRA(Low-Rank Adaptation):冻结原模型权重,只在旁边挂两个小矩阵(低秩分解),训练时只训这两个小矩阵。QLoRA 更进一步:把原模型量化到 4 位,再训 LoRA,一张 16GB 显卡就能微调 7B 模型。

from peft import LoraConfig, get_peft_model peft_config = LoraConfig( r=8, lora_alpha=32, target_modules=["query", "value"], lora_dropout=0.05, bias="none", task_type="SEQ_CLS" ) model = get_peft_model(model, peft_config) model.print_trainable_parameters() # trainable params: 294,912 || all params: 102,269,186 || trainable%: 0.288%

本章面试题

面试 · HuggingFace

Q1. BERT 和 GPT 的区别?

查看答案

BERT 是双向编码器(看上下文左右),适合理解类任务(分类/NER);GPT 是单向解码器(只看左边),适合生成类任务。

Q2. temperature 怎么调?

查看答案

温度低(0.1~0.3)确定、重复;温度高(0.8~1.0)随机、多样。创造性任务调高,事实性任务调低。

Q3. LoRA 为什么省显存?

查看答案

冻结原模型,只训低秩小矩阵,优化器状态和梯度只存小矩阵那部分。

Q4. padding 和 truncation 为什么要同时设?

查看答案

不定长文本批量喂入需要 padding 到同长;超过模型最大长度要 truncation。不设会报错或被截断丢信息。