文章目录
大语言模型微调相关的finetuning、CE Loss、RLHF如何配合工作
概念定义
虽然有点啰嗦,但是值得反复强化概念
Fine-tuning (Finetuning):
Fine-tuning 是机器学习特别是深度学习中的一个重要概念和技术手段,主要应用于预训练模型的迁移学习过程。其基本原理是对已经在大规模通用数据集上预训练好的模型(如BERT、GPT系列、Transformer等),针对特定任务或领域数据进行微调。具体步骤如下:
- 加载预训练模型:首先,获取已经在大规模无标注或有标注数据上训练得到的模型参数。
- 保留部分或全部预训练权重:通常情况下,保留大部分层尤其是底层网络的权重不变,因为它们已经学习到了丰富的通用特征表示。
- 修改输出层:如果预训练模型的输出层与新任务的目标类别数不符,则会修改或替换输出层。
- 微调训练:使用目标领域的有标注数据重新训练模型,但这次的学习率通常设置得较低,以避免破坏预训练模型已学到的良好特征表示,并仅更新部分或所有层的参数以适应新的任务需求。
Cross-Entropy Loss (CE Loss):
交叉熵损失函数是一种常用的监督学习损失函数,尤其是在多分类和序列标注等任务中。它是衡量预测概率分布与真实标签分布之间差异的一种度量。在深度学习模型训练过程中,CE Loss 用于指导模型参数更新,使其预测输出更接近实际目标。
Reinforcement Learning from Human Feedback (RLHF):
RLHF 是强化学习的一个分支,特别强调通过人类反馈来指导智能体(如语言模型)的学习过程。基本原理和步骤如下:
- 收集人类反馈数据:让预训练的语言模型生成一系列响应或行动,然后由人工评估或打分,这个过程可以是直接评分,也可以是二元偏好(选择哪个响应更好)。
- 构建奖励函数:将人类反馈转化为数值形式的奖励信号,构建强化学习环境中的奖励函数。
- 强化学习训练:利用强化学习算法(如PPO、A3C等)进行迭代训练,模型试图最大化从人类反馈获得的奖励,从而改进其行为策略。
- 微调与迭代:不断循环上述步骤,直至模型能够根据人类反馈持续优化其生成内容的质量和合规性。
总结起来,finetuning 适用于迁移学习和特定任务的适应,CE Loss 是模型训练时常见的损失函数,而 RLHF 则是一种利用人类反馈进行模型优化的方法,常用于提升 AI 系统的行为质量和人性化程度。这三者在不同的应用场景下相互配合,共同推进深度学习模型在具体任务上的性能提升。
RAG、Agent、Finetuning之间的关系
RAG(Retrieval-Augmented Generation)、Agent 和 Finetuning 在自然语言处理和机器学习中有不同的角色和关联,但它们并非直接互斥的概念,而是在不同层次上配合使用的工具和技术。
RAG (检索增强生成):
- RAG 是一种自然语言处理架构,它结合了检索与生成两种策略,用于提升模型在问答、对话等任务中的表现。RAG模型首先从预定义的数据源检索相关信息,然后利用这些检索到的信息辅助其生成更准确的答案或文本。
Agent:
- 在人工智能领域,特别是在强化学习和对话系统中,Agent 表示的是一个能够感知环境、做出决策并执行动作的智能体。Agent 不特指某个技术或模型类型,而是指代具有自主行动能力的软件实体。尽管RAG模型可以作为对话系统的一部分,充当一个信息检索和生成的Agent角色,但“Agent”本身的概念更为宽泛,不仅限于RAG这种特定的技术。
Finetuning:
- Finetuning 是机器学习尤其是深度学习中的一种微调技术,常用于预训练模型在特定任务上的适应和优化。当一个模型(例如,大型语言模型)在大规模无监督数据上进行了预训练之后,可以通过finetuning调整模型参数使其更好地适应特定的小规模有监督数据集,解决具体任务(如情感分析、问答系统等)。在涉及RAG模型时,如果要针对特定领域的知识库进行优化,那么也可能需要对其进行finetuning,以便模型更加精准地检索和利用领域内的信息。
总结来说,三者之间的关系与异同在于:
- RAG 是一种具体的模型架构设计,侧重于通过检索+生成的方式改善生成效果。
- Agent 是一个更高层面的概念,它可能是基于RAG模型构建的,负责执行某项任务(如对话交互),并可能包含多种技术集成。
- Finetuning 是一个通用的训练方法,无论是RAG这样的模型还是其他任何预训练模型,都可运用finetuning来针对特定任务进行优化。在RAG场景下,finetuning有助于模型更好地检索和生成与目标领域相关的高质量内容。
RAG、Agent、Finetuning各自的技术方法
RAG (Retrieval-Augmented Generation):
RAG是一种结合了检索与生成技术的混合模型,它通常采用以下具体技术方法:
- 检索模块:通过高效的向量检索引擎,根据输入问题或上下文从大规模知识库中检索最相关的文档片段或段落。
- 融合模块:检索到的相关信息被编码并与输入问题的表示结合起来,共同输入到一个生成模型中。
- 生成模型:基于Transformer结构的大规模预训练语言模型,如GPT系列或其他类似模型,接收检索信息后进行条件生成,输出更准确和可靠的回答。
Agent(在人工智能和机器学习中):
- 状态感知:Agent能够感知环境的状态变化,这可能包括传感器数据、用户输入等信息。
- 决策制定:使用规划算法、强化学习策略(如Q-Learning、DQN、PPO等)或者其他形式的推理机制来决定采取何种行动。
- 行为执行:执行选定的动作,这可以是物理操作(在机器人学中),也可以是在虚拟环境中的操作(如游戏AI),或者是在对话系统中选择合适的回复。
- 学习和适应:通过不断与环境互动,Agent可能会持续学习改进其策略,比如通过在线学习或经验回放等技术。
Finetuning(微调):
- 加载预训练权重:首先,模型通常是基于大规模数据集预先训练好的,例如BERT、GPT、T5等模型。
- 目标任务定义:针对特定任务,如文本分类、序列标注、问答系统等,定义相应的损失函数和优化目标。
- 带标签数据集:使用特定任务的有标注数据集进行进一步训练,调整模型参数。
- 正则化和调整超参数:可能应用L2正则化、早停法等防止过拟合,并调整学习率、批次大小等超参数以达到最佳性能。
- 多任务学习与迁移学习:有时也会通过多任务学习框架或少量样本微调(如Adapter、LoRA等轻量级适配器技术)来进行微调,以保留预训练模型的通用性同时提高在特定任务上的性能。
步骤流程
Fine-tuning、Cross-Entropy Loss(CE Loss)与Reinforcement Learning from Human Feedback(RLHF)在某些场景下可以结合使用来进一步优化模型的表现,尤其在基于深度学习的语言模型和其他决策任务中。下面是一种可能的整合流程:
-
预训练模型与Fine-tuning
- 使用大规模未标注或带标注的数据预先训练一个基础模型,比如预训练一个语言模型,使其学习到语言的基本规律和模式。
-
Fine-tuning with CE Loss
- 对预训练模型进行Fine-tuning,这时的任务可能是一个监督学习任务,例如文本分类、命名实体识别等。
- 将目标任务的标记数据输入模型,并使用CE Loss作为损失函数来调整模型的输出层以及其他可能的层。
- 在每一步训练中,计算模型预测的概率分布与真实标签之间的交叉熵损失,并反向传播误差以更新模型参数,使得模型对于目标任务的预测能力逐步提高。
-
引入RLHF
- 当常规的Fine-tuning不能满足对模型输出质量或特定属性(如安全性、伦理准则遵循等)的要求时,可以采用RLHF。
- 首先,收集一组人类反馈数据,即让经过Fine-tuning的模型产生一些输出,然后由人类评估员给出评分或偏好指示。
- 根据这些反馈构造一个奖励函数,它可以量化模型生成结果的好坏,奖励函数的设计目的是引导模型朝着符合人类期望的方向发展。
- 在此基础上,将模型放入强化学习环境中,利用强化学习算法(如PPO)来优化模型的策略,使模型生成的结果能在后续迭代中获得更高的奖励值。
-
联合训练
- 可以选择交替进行Fine-tuning和RLHF,先用CE Loss进行一轮或多轮迭代,然后再加入RLHF进行一轮优化,之后再回到CE Loss,如此反复。
- 或者在每次RLHF训练后,继续使用CE Loss对模型在目标任务上的表现进行微调,以保持模型在原始任务上的性能同时吸收强化学习带来的更贴近人类偏好的特质。
通过这样的协同流程,模型不仅能够继承预训练模型的泛化能力和语义理解,还能够在特定任务上有针对性地优化,并通过RLHF得到更加符合人类价值观和期望的行为策略。
示例代码
在实际工作中,Fine-tuning(微调)、Cross-Entropy Loss(CE Loss)和Reinforcement Learning from Human Feedback (RLHF) 可以通过以下方式进行配合,这里提供一个简化的示例流程,由于实际代码较长且复杂,下面仅给出伪代码说明:
假设我们有一个基于Hugging Face Transformers库的大规模预训练模型,我们需要在一个特定任务上进行微调,并在微调之后应用RLHF进一步优化模型。
-
Fine-tuning(微调)阶段:
from transformers import AutoModelForSequenceClassification, Trainer, TrainingArguments import torch from datasets import load_dataset # 加载预训练模型 model = AutoModelForSequenceClassification.from_pretrained("bert-base-uncased") # 准备数据集 dataset = load_dataset("my_task_dataset") # 替换成你自己的数据集名 dataset = dataset.map(...) # 数据预处理,包括Tokenization等 train_dataset = dataset["train"] eval_dataset = dataset["validation"] # 定义训练参数 training_args = TrainingArguments( output_dir='./results', num_train_epochs=3, per_device_train_batch_size=16, per_device_eval_batch_size=16, logging_dir='./logs', evaluation_strategy="epoch", save_strategy="epoch", metric_for_best_model="accuracy", # 根据实际情况调整 ) # 定义损失函数,这里使用CE Loss def compute_metrics(eval_pred): predictions, labels = eval_pred predictions = torch.argmax(predictions, dim=-1) acc = (predictions == labels).mean() return {"accuracy": acc} trainer = Trainer( model=model, args=training_args, train_dataset=train_dataset, eval_dataset=eval_dataset, compute_metrics=compute_metrics, ) # 开始微调 trainer.train() # 微调后保存模型 fine_tuned_model.save_pretrained("./fine_tuned_model")
-
RLHF(Reinforcement Learning from Human Feedback)阶段:
这一阶段通常涉及收集人类反馈数据、构建奖励函数并使用强化学习算法进一步优化模型。以下是一个简化的流程:# 假设我们已经有了收集的人类反馈数据集,其中包括模型生成的文本和对应的奖励分数 human_feedback_data = load_human_feedback_data() # 定义强化学习训练部分 # 这里省略了如何将模型转换为能够接收奖励信号、如何构造环境和策略的具体代码 from reinforcement_learning_module import ReinforcementLearningTrainer rl_trainer = ReinforcementLearningTrainer( model=fine_tuned_model, feedback_data=human_feedback_data, policy_optimizer=torch.optim.Adam, # 使用Adam优化器更新策略 reward_function=my_reward_function, # 自定义奖励函数,根据人类反馈计算奖励 # ... 其他RL训练参数 ) # 开始RLHF训练 rl_trainer.train_rl() # 训练完成后保存RLHF优化后的模型 rlhf_optimized_model.save_pretrained("./rlhf_optimized_model")
请注意,上面的RLHF部分仅是一个高层次的示意,实际实现会涉及更多的细节,例如构建强化学习环境、策略网络、以及将模型调整为可以进行强化学习的形式。RLHF通常需要设计一套复杂的管道来收集人类反馈、构建奖励函数,并将这些反馈融入到模型的优化过程中。具体实施可能需要借助第三方库(如Coach、RLlib等)或者自己编写定制化的强化学习算法实现。
pytorch + 抱抱脸Hugging Face基于预训练模型做微调
基于预训练的模型做FineTune
FineTune或者Transfer Learning是一种比较流行的做法,特别是在NLP领域:利用大量的语料训练出一个基本的模型,然后在结合自己的业务数据,再基本模型之上进一步FineTune。HF中有三种方法来运行Fine-Tune的训练过程:
Fine-tune a pretrained model with 🤗 Transformers Trainer.
Fine-tune a pretrained model in TensorFlow with Keras.
Fine-tune a pretrained model in native PyTorch.
FineTune是在预训练的模型的权重基础之上,进一步训练,有两种情况:
预训练好的模型已经可以解决目前的问题,但是需要把模型权重进一步训练以适应新的训练样本。
一个典型例子是通用的预训练英文翻译模型,在大量的通用语料上训练而来;但是针对某个专业领域效果不是很理想。如果我们拥有这个领域的语料,可以进一步训练,使得在这个领域的效果得到改进。
预训练模型的网络结构不能直接解决当前问题,进利用预训练模型的最主要网络部分,然后增加针对新任务的神经网络layer;这个时候的FineTune是把原模型的主要部分权重已经新增加的layer的权重一起训练。
比如我们用一个普通的bert语言模型来做QuestionAnswering,HF就会提示原有的部分模型权重没有被使用,同时有一部分权重没有被初始化。这是因为预训练好的模型的的网络结构是Embedding->Transoformer Encoder->classification,而QuestionAnswering需要Embedding->Transofrmer Encoder->QA。其中的Classification Layer只需要输出2个logit用来做二分类,而QA需要输出2个整数代表Answer的start和end下标。
查看模型结构并理解FineTune
我们尝试用一个bert模型来做QuestionAnsering,可以看到HF的Warning信息:原预训练模型的网络结构中的分类layer会被抛弃,同时新增一个没有初始化的QA layer。这就意味着这个模型必须被FineTune训练之后才能被使用。
我们也可以看到这个模型的详细神经网络结构:
最底层是Embedding层,支持30522个单词(token),每个单词对应的Embedding是一个768维的向量。
之后是一个Transfomer,由6个TransformerBlock构成,每一个TransformerBlock有MultiHeadSelfAttention, LayerNorm,FFN三部分。最后输出一个768维的向量
增加了一个新的Layer叫QA Output;把一个768维的向量转换为2个数字,分别代表Answer的start和end下标
预训练第一步:加载一个预训练模型
我们选择排名第一的中文翻译到英文的模型来做FineTune:Helsinki-NLP/opus-mt-zh-en(链接)。我们将在这个模型基础之上加入自己的语料进一步FineTune,也就是保留预训练的模型结构,只是对其中权重(weights)做训练。
我们加载模型,并看一下这个预训练模型的效果:
import logging
logging.disable(logging.WARN)
from transformers import AutoModelForSeq2SeqLM, AutoTokenizer
model_checkpoint = "Helsinki-NLP/opus-mt-zh-en"
model = AutoModelForSeq2SeqLM.from_pretrained(model_checkpoint)
tokenizer = AutoTokenizer.from_pretrained(model_checkpoint)
translator = pipeline("translation", model=model, tokenizer=tokenizer)
sequences = [
"你好,今天天气很好",
"深度学习是一种新的方法",
"数学的重要性不言而喻",
"不明觉厉",
#'“虽不明,但觉厉”,网络流行词,简称“不明觉厉”,表示“虽然不明白你在说什么,但好像很厉害的样子。'
]
results = translator(sequences)
print(results)
for source, target in zip(sequences, results):
print(source, "===>", target["translation_text"])
[{'translation_text': "Hello. It's a nice day."}, {'translation_text': 'Deep learning is a new approach.'}, {'translation_text': 'The importance of mathematics speaks for itself.'}, {'translation_text': "I don't know what I'm talking about."}]
你好,今天天气很好 ===> Hello. It's a nice day.
深度学习是一种新的方法 ===> Deep learning is a new approach.
数学的重要性不言而喻 ===> The importance of mathematics speaks for itself.
不明觉厉 ===> I don't know what I'm talking about.
可以看到当前的翻译效果很不错,并且还帮我们把句号都加上了😄!其中的“不言而喻”的翻译更是非常地道。但是对“不明觉厉”这个网络词汇的理解不够准确,我们下面要完成的FineTune任务就是让模型记住“不明觉厉”的英文句子。
预训练第二步:准备训练数据
如果HF Hub中已经有我们需要的数据集,可以用datasets这个库来直接load;也可以提前push到HF Hub之后再load。如果不希望push到HF,也可以把训练数据放到本地来Load。 为了方便演示,我们用内存中数据来构造一个dataset(参考链接);其中就是“不明觉厉”的英文翻译这一个样本。
from datasets import Dataset
source_sentences = ["不明觉厉"]
target_sentences=["It's not clear what you're talking about, but it looks like it's pretty good"]
inputs = tokenizer(source_sentences, max_length=50, padding=True, truncation=True, return_tensors="pt")
with tokenizer.as_target_tokenizer():
labels = tokenizer(target_sentences, return_tensors='pt', padding=True)
inputs['decoder_input_ids']=labels['input_ids']
inputs['decoder_attention_mask']=labels['attention_mask']
inputs['labels']=labels['input_ids']
dataset = Dataset.from_dict(inputs)
预训练第三步:准备训练的参数
from transformers import Seq2SeqTrainingArguments, Seq2SeqTrainer, DataCollatorForSeq2Seq
training_args = Seq2SeqTrainingArguments(
output_dir="./mymodels",
evaluation_strategy="no",
overwrite_output_dir=True,
num_train_epochs=6,
save_steps=1000,
save_total_limit=2,
predict_with_generate=False,
prediction_loss_only=True)
data_collator = DataCollatorForSeq2Seq(tokenizer, model=model)
预训练第四步:开始训练
HF提供了Trainer类来辅助训练,HF也支持用Tensorflow或者PyTorch来完成训练。
trainer = Seq2SeqTrainer(
model = model,
args = training_args,
data_collator=data_collator,
tokenizer=tokenizer,
#compute_metrics=compute_metrics,
train_dataset=dataset)
trainer.train()
使用FineTune之后的模型查看翻译效果
new_pipeline=pipeline('translation', model=model, tokenizer=tokenizer)
new_pipeline(["听到这个消息之后,所有人都震惊了", "不明觉厉"])
[{'translation_text': 'Everyone was shocked when I heard the news.'},
{'translation_text': "It's not clear what you're talking about, but it looks like it's pretty good"}]
保存模型
model.save_pretrained("./models")
总结
HuggingFace提供了大量的预训练模型供算法工程师使用,基于预训练模型,我们可以直接做推理或预测,也可以进一步FineTune来适应自己的业务数据。而HF python SDK提供了非常友好的interface,最常用的是pipeline、model、tokeninzer、trainer等。