跳到主要内容

预训练语言模型

预训练语言模型(Pre-trained Language Model)是现代 NLP 的核心技术。通过在大规模语料上进行预训练,模型学习到通用的语言知识,然后通过微调适应下游任务。

预训练语言模型的发展

发展历程

年份模型特点
2018ELMo基于双向 LSTM 的动态词向量
2018GPT-1基于 Transformer 解码器的生成模型
2018BERT基于 Transformer 编码器的双向模型
2019GPT-2更大规模的生成模型
2019RoBERTa优化的 BERT 训练方法
2019XLNet排列语言模型
2019ALBERT轻量化 BERT
2020GPT-31750 亿参数的大模型
2020T5文本到文本统一框架
2021DeBERTa解耦注意力机制
2022ChatGPT对话优化的 GPT
2023GPT-4多模态大模型
2023LLaMA开源大语言模型系列

预训练范式

预训练语言模型主要有两种范式:

特征提取(Feature-based):如 ELMo,预训练模型作为特征提取器,输出用于下游任务。

微调(Fine-tuning):如 BERT、GPT,在预训练模型基础上添加任务特定层,端到端微调。

BERT

BERT(Bidirectional Encoder Representations from Transformers)是预训练语言模型的里程碑,由 Google 于 2018 年提出。

BERT 架构

BERT 基于 Transformer 编码器,使用双向上下文来学习词的表示。

from transformers import BertModel, BertTokenizer
import torch

# 加载 BERT 模型
model_name = "bert-base-chinese"
tokenizer = BertTokenizer.from_pretrained(model_name)
model = BertModel.from_pretrained(model_name)

# 查看模型结构
print(f"BERT 层数: {model.config.num_hidden_layers}")
print(f"隐藏层维度: {model.config.hidden_size}")
print(f"注意力头数: {model.config.num_attention_heads}")
print(f"词汇表大小: {model.config.vocab_size}")

# 获取词向量
text = "自然语言处理很有趣"
inputs = tokenizer(text, return_tensors="pt")

with torch.no_grad():
outputs = model(**inputs)

# last_hidden_state: (batch_size, seq_len, hidden_size)
# pooler_output: (batch_size, hidden_size) - [CLS] token 的表示
print(f"序列输出形状: {outputs.last_hidden_state.shape}")
print(f"池化输出形状: {outputs.pooler_output.shape}")

BERT 预训练任务

BERT 使用两个预训练任务:

掩码语言模型(MLM):随机遮盖 15% 的词,预测被遮盖的词。

下一句预测(NSP):判断两个句子是否连续。

from transformers import BertForMaskedLM

# 加载 MLM 模型
model = BertForMaskedLM.from_pretrained("bert-base-chinese")

# 填空任务
text = "自然语言处理是人工[MASK]能的重要分支。"
inputs = tokenizer(text, return_tensors="pt")

with torch.no_grad():
outputs = model(**inputs)

# 获取预测结果
mask_token_index = torch.where(inputs["input_ids"] == tokenizer.mask_token_id)[1]
predicted_token_id = outputs.logits[0, mask_token_index].argmax(axis=-1)
predicted_token = tokenizer.decode(predicted_token_id)

print(f"原文: {text}")
print(f"预测: {text.replace('[MASK]', predicted_token)}")

BERT 微调

from transformers import BertForSequenceClassification, Trainer, TrainingArguments

# 加载分类模型
model = BertForSequenceClassification.from_pretrained(
"bert-base-chinese",
num_labels=2 # 二分类
)

# 微调代码示例(需要准备数据集)
training_args = TrainingArguments(
output_dir="./results",
num_train_epochs=3,
per_device_train_batch_size=16,
learning_rate=2e-5
)

# trainer = Trainer(
# model=model,
# args=training_args,
# train_dataset=train_dataset,
# eval_dataset=val_dataset
# )
# trainer.train()

GPT

GPT(Generative Pre-trained Transformer)系列是 OpenAI 开发的生成式预训练模型。

GPT 架构

GPT 基于 Transformer 解码器,使用自回归方式生成文本。

from transformers import GPT2LMHeadModel, GPT2Tokenizer

# 加载 GPT-2 模型
model_name = "gpt2"
tokenizer = GPT2Tokenizer.from_pretrained(model_name)
model = GPT2LMHeadModel.from_pretrained(model_name)

# 文本生成
def generate_text(prompt, max_length=100):
inputs = tokenizer.encode(prompt, return_tensors="pt")

outputs = model.generate(
inputs,
max_length=max_length,
num_return_sequences=1,
temperature=0.7,
top_k=50,
top_p=0.95,
do_sample=True
)

return tokenizer.decode(outputs[0], skip_special_tokens=True)

# 生成文本
prompt = "Natural language processing is"
generated = generate_text(prompt)
print(generated)

中文 GPT 模型

from transformers import BertTokenizer, GPT2LMHeadModel

# 使用中文 GPT 模型
model_name = "uer/gpt2-chinese-cluecorpussmall"
tokenizer = BertTokenizer.from_pretrained(model_name)
model = GPT2LMHeadModel.from_pretrained(model_name)

def generate_chinese_text(prompt, max_length=100):
inputs = tokenizer.encode(prompt, return_tensors="pt")

outputs = model.generate(
inputs,
max_length=max_length,
num_return_sequences=1,
temperature=0.8,
top_p=0.9,
do_sample=True,
pad_token_id=tokenizer.eos_token_id
)

return tokenizer.decode(outputs[0], skip_special_tokens=True)

# 生成中文文本
prompt = "自然语言处理是"
generated = generate_chinese_text(prompt)
print(generated)

其他预训练模型

RoBERTa

RoBERTa 是 BERT 的优化版本,通过更大的数据和更长的训练获得更好的效果。

from transformers import RobertaModel, RobertaTokenizer

model_name = "roberta-base"
tokenizer = RobertaTokenizer.from_pretrained(model_name)
model = RobertaModel.from_pretrained(model_name)

ALBERT

ALBERT 通过参数共享和分解嵌入减少参数量。

from transformers import AlbertModel, AlbertTokenizer

model_name = "albert-base-v2"
tokenizer = AlbertTokenizer.from_pretrained(model_name)
model = AlbertModel.from_pretrained(model_name)

DeBERTa

DeBERTa 使用解耦注意力机制,效果优于 BERT。

from transformers import DebertaModel, DebertaTokenizer

model_name = "microsoft/deberta-base"
tokenizer = DebertaTokenizer.from_pretrained(model_name)
model = DebertaModel.from_pretrained(model_name)

大语言模型(LLM)

LLaMA

LLaMA 是 Meta 开源的大语言模型系列,支持多种规模。

from transformers import LlamaTokenizer, LlamaForCausalLM

# 需要先申请访问权限
model_name = "meta-llama/Llama-2-7b-hf"

# tokenizer = LlamaTokenizer.from_pretrained(model_name)
# model = LlamaForCausalLM.from_pretrained(model_name)

# 生成文本
def generate_with_llama(prompt, max_new_tokens=100):
inputs = tokenizer(prompt, return_tensors="pt")

outputs = model.generate(
**inputs,
max_new_tokens=max_new_tokens,
temperature=0.7,
top_p=0.9,
do_sample=True
)

return tokenizer.decode(outputs[0], skip_special_tokens=True)

使用 Hugging Face Pipeline

from transformers import pipeline

# 文本生成
generator = pipeline("text-generation", model="gpt2")

result = generator(
"Once upon a time",
max_length=100,
num_return_sequences=1
)
print(result[0]['generated_text'])

# 对话模型
chatbot = pipeline("text-generation", model="microsoft/DialoGPT-medium")

# 问答
qa = pipeline("question-answering", model="deepset/roberta-base-squad2")

result = qa(
question="什么是自然语言处理?",
context="自然语言处理是人工智能的一个分支,致力于让计算机理解和生成人类语言。"
)
print(f"答案: {result['answer']}, 置信度: {result['score']:.4f}")

模型微调技术

全参数微调

from transformers import AutoModelForSequenceClassification, AutoTokenizer
from transformers import Trainer, TrainingArguments

model_name = "bert-base-chinese"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForSequenceClassification.from_pretrained(model_name, num_labels=2)

# 训练参数
training_args = TrainingArguments(
output_dir="./fine_tuned_model",
num_train_epochs=3,
per_device_train_batch_size=16,
learning_rate=2e-5,
evaluation_strategy="epoch",
save_strategy="epoch"
)

# trainer = Trainer(
# model=model,
# args=training_args,
# train_dataset=train_dataset,
# eval_dataset=val_dataset
# )
# trainer.train()

LoRA 微调

LoRA(Low-Rank Adaptation)是一种参数高效的微调方法,只训练少量参数。

from peft import LoraConfig, get_peft_model, TaskType

# 配置 LoRA
lora_config = LoraConfig(
task_type=TaskType.SEQ_CLS,
r=8, # 低秩矩阵的秩
lora_alpha=32,
lora_dropout=0.1,
target_modules=["query", "value"]
)

# 应用 LoRA
model = AutoModelForSequenceClassification.from_pretrained("bert-base-chinese", num_labels=2)
model = get_peft_model(model, lora_config)

# 查看可训练参数
model.print_trainable_parameters()
# 输出类似: trainable params: 294,912 || all params: 109,774,084 || trainable%: 0.2686

Prompt Tuning

from peft import PromptTuningConfig, get_peft_model, TaskType

# 配置 Prompt Tuning
prompt_config = PromptTuningConfig(
task_type=TaskType.SEQ_CLS,
num_virtual_tokens=20,
token_dim=768,
num_transformer_submodules=1,
num_attention_heads=12,
num_layers=12
)

model = AutoModelForSequenceClassification.from_pretrained("bert-base-chinese", num_labels=2)
model = get_peft_model(model, prompt_config)

model.print_trainable_parameters()

模型量化

量化可以减少模型大小和推理时间。

from transformers import AutoModelForCausalLM, BitsAndBytesConfig

# 4-bit 量化配置
quantization_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_compute_dtype=torch.float16,
bnb_4bit_quant_type="nf4",
bnb_4bit_use_double_quant=True
)

# 加载量化模型
model = AutoModelForCausalLM.from_pretrained(
"meta-llama/Llama-2-7b-hf",
quantization_config=quantization_config,
device_map="auto"
)

模型部署

使用 ONNX 导出

from transformers import AutoModel, AutoTokenizer
from transformers.onnx import FeaturesManager

model_name = "bert-base-chinese"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModel.from_pretrained(model_name)

# 导出为 ONNX 格式
# from transformers.onnx import export
# export(tokenizer, model, FeaturesManager.get_supported_features_for_model_type("bert")[0], "bert.onnx")

使用 FastAPI 部署

from fastapi import FastAPI
from pydantic import BaseModel
from transformers import pipeline

app = FastAPI()

# 加载模型
classifier = pipeline("sentiment-analysis", model="bert-base-chinese")

class TextRequest(BaseModel):
text: str

@app.post("/classify")
async def classify_text(request: TextRequest):
result = classifier(request.text)
return {
"text": request.text,
"label": result[0]["label"],
"score": result[0]["score"]
}

# 运行: uvicorn app:app --reload

总结

预训练语言模型是现代 NLP 的核心技术,本章介绍了:

  • BERT:双向编码器模型,适合理解任务
  • GPT:自回归生成模型,适合生成任务
  • 其他模型:RoBERTa、ALBERT、DeBERTa 等
  • 大语言模型:LLaMA 等开源模型
  • 微调技术:全参数微调、LoRA、Prompt Tuning
  • 模型优化:量化、部署

预训练语言模型的发展推动了 NLP 领域的巨大进步,掌握这些技术对于现代 NLP 开发至关重要。