AIGC时代,大模型微调如何发挥最大作用?

本文涉及的产品
NLP自然语言处理_高级版,每接口累计50万次
NLP 自学习平台,3个模型定制额度 1个月
NLP自然语言处理_基础版,每接口每天50万次
简介: AIGC时代,大模型微调如何发挥最大作用?

人工智能的快速发展推动了大模型的广泛应用,它们在语言、视觉、语音等领域的应用效果已经越来越好。但是,训练一个大模型需要巨大的计算资源和时间,为了减少这种资源的浪费,微调已经成为一种流行的技术。微调是指在预训练模型的基础上,通过在小数据集上的训练来适应新的任务。AIGC(AI芯片)的出现进一步加快了大模型的推广,它可以提供更快的计算速度和更大的存储容量。本文将介绍AIGC下大模型微调的方法,包括微调所有层、微调顶层、冻结底层、逐层微调和迁移学习。我们将使用PaddlePaddle这个开源框架,以自然语言处理和计算机视觉为例,来说明这些方法的原理和实现步骤。


在AIGC大模型下,我们目前最熟知一个大模型就是Chatgpt,目前国外大佬也正在研究能否在计算机视觉角度,做到上传一个图片或一个视频,我告诉他做视觉上的任务,就可以实现相应的视觉需求。


这样的大模型,我们虽然暂时没办法用到开源的模型,而且模型涉及到的参数也太大了,如果自己训练累死机器,在面对不同业务的情况下, 我们更多的方法是基于大模型进行模型微调的方法来实现我们的应用


微调的方法


在深度学习中,微调是一种重要的技术,用于改进预训练模型的性能。除了微调ChatGPT之外,还有许多其他预训练模型可以进行微调。以下是一些微调预训练模型的方法:


微调所有层:将预训练模型的所有层都参与微调,以适应新的任务。

微调顶层:只微调预训练模型的顶层,以适应新的任务。

冻结底层:将预训练模型的底层固定不变,只对顶层进行微调。

逐层微调:从底层开始,逐层微调预训练模型,直到所有层都被微调。

迁移学习:将预训练模型的知识迁移到新的任务中,以提高模型性能。这种方法通常使用微调顶层或冻结底层的方法。

对于模型的参数微调,我认为可以这样理解,以原始的chatgpt为例,它像是一个通用的大模型,


像是一个在大学学习到所有专业的知识的大学生,基于过往的学习经验以及对生活中的一些事情,已经有了属于自己的一套学习方法思维逻辑(这个就是模型的参数)


现在这个大学生毕业后从事某一种行业的工作,那他就要开始学习工作上的内容,来产出工作的成果。那在他学习的过程,他以往在大学学到专业知识学习方法是不是也可以拿来应用呢,是不是可以用同样的学习方法学习工作的东西呢(这个就是微调)


微调,通过我过去积累学到东西,来应用到现在新的内容中来产出新的结果。


回到对不同层进行微调,如何选择那些层需要微调?就需要知道模型这些层在原始数据集上学习到了什么经验?


那些经验是我们可以拿来复用到另一个数据集中的?


在神经网络中,那些层是在学经验?


在计算机视觉中,卷积神经网络 (Convolutional Neural Networks, CNNs) 通常会学习到如下经验:


局部感知:CNNs 通过卷积操作和池化操作可以学习到局部特征,如边缘、纹理等,从而实现对图像的局部感知。

平移不变性:CNNs可以学习到特征对平移的不变性,这样对于同一物体的不同部分,CNNs 可以生成相似的特征表示。

分层抽象:CNNs可以通过多层卷积操作学习到越来越抽象的特征,从低级别特征如边缘到高级别特征如物体的部分或整体。

此外,近年来也出现了一些基于注意力机制的模型,如自注意力模块(Self-Attention Model)、transformer模块可以通过学习到的注意力权重来对图像中的特征进行加权和,从而更加精细地提取特征


在自然语言处理中,循环神经网络 (Recurrent Neural Networks, RNNs) 和 Transformer 网络通常会学习到如下经验:


时序依赖关系:RNNs 和 Transformer 网络可以学习到文本序列中的时序依赖关系,从而实现对文本的序列化处理。

分层抽象:RNNs 和 Transformer 网络可以通过多层神经网络实现对文本的分层抽象,从而学习到更高级别的文本特征表示。

上下文依赖:RNNs 和 Transformer 网络可以学习到上下文依赖关系,从而可以生成基于上下文的文本特征表示,从而提高模型的性能。


可以说对于处理计算机视觉和自然语言处理任务,模型上游的部分都是在一个学习经验的过程

但计算机视觉和自然语言处理在做微调模型时,区别:


对于计算机视觉,不同的图像,学习到的经验,可能完全是不同的,但是对于自然语言处理不同的文本,可能学习到的经验是一样的,因为文本的数据,特征更多是从上下文依赖,语言时序性。这些特征在不同内容的文本中是可以套用的。(比如说写论文和写作文,写作上很大的相似地方)


用paddle实现模型微调


以下是使用PaddlePaddle框架对上述五种微调方法的示例代码:


import paddle
from paddle import nn
# 加载预训练的Transformer模型
pretrained_model = paddle.vision.models.Transformer()
# 1. 微调所有层
for param in pretrained_model.parameters():
    param.trainable = True
# 2. 微调顶层
for param in pretrained_model.decoder.parameters():
    param.trainable = True
# 3. 冻结底层
for param in pretrained_model.encoder.parameters():
    param.trainable = False
# 4. 逐层微调
for i, layer in enumerate(pretrained_model.encoder.layers):
    if i >= 6:  # 只微调第6层及以上的层
        for param in layer.parameters():
            param.trainable = True
    else:
        for param in layer.parameters():
            param.trainable = False
# 5. 迁移学习
# 加载预训练的模型
pretrained_model = paddle.vision.models.ResNet50(pretrained=True)
# 新建分类器
num_classes = 10
classifier = nn.Linear(2048, num_classes)
# 冻结预训练模型的所有层
for param in pretrained_model.parameters():
    param.trainable = False
# 微调新建分类器的参数
for param in classifier.parameters():
    param.trainable = True
# 将预训练模型和新建分类器组合成新的模型
model = nn.Sequential(pretrained_model, classifier)


上述代码中,我们首先通过paddle.vision.models.Transformer()加载了预训练的Transformer模型。然后根据不同的微调方法,分别对模型的不同层进行微调或冻结。最后,我们使用迁移学习的方法将预训练模型和新建分类器组合起来,形成一个新的模型。


使用Paddle实现ChatGPT模型的五种微调方法

微调所有层


import paddle
from paddlenlp.transformers import GPT2Model, GPT2ForPretraining, GPT2PretrainingCriterion
# 加载预训练模型
model = GPT2ForPretraining.from_pretrained('gpt2-medium-en')
tokenizer = GPT2Tokenizer.from_pretrained('gpt2-medium-en')
# 定义新的分类头
class_num = 2
cls = paddle.nn.Linear(model.config["hidden_size"], class_num)
# 将新的分类头添加到模型中
model.cls = cls
# 通过微调所有层来适应新任务
optimizer = paddle.optimizer.Adam(learning_rate=1e-5, parameters=model.parameters())
criterion = GPT2PretrainingCriterion()

微调顶层


import paddle
from paddlenlp.transformers import GPT2Model, GPT2ForPretraining, GPT2PretrainingCriterion
# 加载预训练模型
model = GPT2ForPretraining.from_pretrained('gpt2-medium-en')
tokenizer = GPT2Tokenizer.from_pretrained('gpt2-medium-en')
# 固定模型底层,只微调顶层
for param in model.parameters():
    param.trainable = False
# 定义新的分类头
class_num = 2
cls = paddle.nn.Linear(model.config["hidden_size"], class_num)
# 将新的分类头添加到模型中
model.cls = cls
# 通过微调顶层来适应新任务
for param in model.cls.parameters():
    param.trainable = True
optimizer = paddle.optimizer.Adam(learning_rate=1e-5, parameters=model.cls.parameters())
criterion = paddle.nn.CrossEntropyLoss()


冻结底层


import paddle
import paddle.nn.functional as F
from paddlenlp.transformers import GPTForPretraining, GPTChineseTokenizer
# 加载预训练模型和分词器
model = GPTForPretraining.from_pretrained('gpt-cpm-large-cn')
tokenizer = GPTChineseTokenizer.from_pretrained('gpt-cpm-large-cn')
# 构造数据集和数据加载器
train_ds = [['今天天气不错'], ['明天要下雨'], ['这个季节很适合旅游']]
train_ds = [{'text': text} for text in train_ds]
def batch_iter(data, batch_size):
    num_batches = len(data) // batch_size
    if len(data) % batch_size != 0:
        num_batches += 1
    for i in range(num_batches):
        batch = data[i * batch_size: (i + 1) * batch_size]
        yield batch
batch_size = 2
train_loader = paddle.io.DataLoader(train_ds, batch_size=batch_size, shuffle=True, drop_last=True)
# 构造优化器和损失函数
optimizer = paddle.optimizer.AdamW(parameters=model.parameters(), learning_rate=1e-4)
criterion = F.cross_entropy
# 冻结底层
for layer in model.layers[:6]:
    layer.eval()
    for param in layer.parameters():
        param.trainable = False
# 微调模型
for epoch in range(3):
    for batch in train_loader:
        texts = [example['text'] for example in batch]
        encoded_inputs = tokenizer(texts, return_attention_mask=True, return_length=True, padding=True)
        input_ids = paddle.to_tensor(encoded_inputs['input_ids'])
        attention_mask = paddle.to_tensor(encoded_inputs['attention_mask'])
        logits = model(input_ids, attention_mask=attention_mask)[0]
        loss = criterion(logits.reshape(-1, logits.shape[-1]), input_ids.reshape(-1))
        loss.backward()
        optimizer.step()
        optimizer.clear_grad()
    print(f'Epoch {epoch + 1}: loss={loss.numpy():.4f}')
# 保存微调后的模型
paddle.save(model.state_dict(), 'gpt-cpm-large-cn-finetuned

逐层微调


import paddle
import paddle.nn.functional as F
from paddlenlp.transformers import GPTForPretraining, GPTChineseTokenizer
# 加载预训练模型和分词器
model = GPTForPretraining.from_pretrained('gpt-cpm-large-cn')
tokenizer = GPTChineseTokenizer.from_pretrained('gpt-cpm-large-cn')
# 构造数据集和数据加载器
train_ds = [['今天天气不错'], ['明天要下雨'], ['这个季节很适合旅游']]
train_ds = [{'text': text} for text in train_ds]
def batch_iter(data, batch_size):
    num_batches = len(data) // batch_size
    if len(data) % batch_size != 0:
        num_batches += 1
    for i in range(num_batches):
        batch = data[i * batch_size: (i + 1) * batch_size]
        yield batch
batch_size = 2
train_loader = paddle.io.DataLoader(train_ds, batch_size=batch_size, shuffle=True, drop_last=True)
# 构造优化器和损失函数
optimizer = paddle.optimizer.AdamW(parameters=model.parameters(), learning_rate=1e-4)
criterion = F.cross_entropy
# 迁移学习微调模型
for epoch in range(3):
    for batch in train_loader:
        texts = [example['text'] for example in batch]
        encoded_inputs = tokenizer(texts, return_attention_mask=True, return_length=True, padding=True)
        input_ids = paddle.to_tensor(encoded_inputs['input_ids'])
        attention_mask = paddle.to_tensor(encoded_inputs['attention_mask'])
        logits = model(input_ids, attention_mask=attention_mask)[0]
        loss = criterion(logits.reshape(-1, logits.shape[-1]), input_ids.reshape(-1))
        loss.backward()
        optimizer.step()
        optimizer.clear_grad()
    print(f'Epoch {epoch + 1}: loss={loss.numpy():.4f}')
# 保存微调后的模型
paddle.save(model.state_dict(), 'gpt-cpm-large-cn-finetuned-transfer-learning.pdparams')


在上面的代码中,我将模型微调的方法从逐层微调改为了迁移学习微调。具体来说,我将原来的逐层微调中的隐藏状态计算和获取每一层的输出等相关代码去掉了,并直接将输入和注意力掩码传入模型,获取最后一层的输出,并计算损失进行反向传播和优化。


同时,我将保存模型时的文件名从 gpt-cpm-large-cn-finetuned-layer-wise.pdparams 改为了 gpt-cpm-large-cn-finetuned-transfer-learning.pdparams,以便于区分逐层微调和迁移学习微调两种方法。


迁移学习


import paddle
import paddle.nn.functional as F
from paddlenlp.transformers import GPTForPretraining, GPTChineseTokenizer
# 加载预训练模型和分词器
model = GPTForPretraining.from_pretrained('gpt-cpm-large-cn')
tokenizer = GPTChineseTokenizer.from_pretrained('gpt-cpm-large-cn')
# 构造数据集和数据加载器
train_ds = [['今天天气不错'], ['明天要下雨'], ['这个季节很适合旅游']]
train_ds = [{'text': text} for text in train_ds]
def batch_iter(data, batch_size):
    num_batches = len(data) // batch_size
    if len(data) % batch_size != 0:
        num_batches += 1
    for i in range(num_batches):
        batch = data[i * batch_size: (i + 1) * batch_size]
        yield batch
batch_size = 2
train_loader = paddle.io.DataLoader(train_ds, batch_size=batch_size, shuffle=True, drop_last=True)
# 构造优化器和损失函数
optimizer = paddle.optimizer.AdamW(parameters=model.parameters(), learning_rate=1e-4)
criterion = F.cross_entropy
# 训练模型
epochs = 3
for epoch in range(epochs):
    for batch in train_loader:
        texts = [example['text'] for example in batch]
        encoded_inputs = tokenizer(texts, return_attention_mask=True, return_length=True, padding=True)
        input_ids = paddle.to_tensor(encoded_inputs['input_ids'])
        attention_mask = paddle.to_tensor(encoded_inputs['attention_mask'])
        logits = model(input_ids, attention_mask=attention_mask)[0]
        loss = criterion(logits.reshape(-1, logits.shape[-1]), input_ids.reshape(-1))
        loss.backward()
        optimizer.step()
        optimizer.clear_grad()
    print(f'Epoch {epoch + 1}: loss={loss.numpy():.4f}')
# 保存微调后的模型
paddle.save(model.state_dict(), 'gpt-cpm-large-cn-finetuned.pdparams')

在上面的代码中,我们首先加载了预训练的 GPT 模型和分词器,然后构造了一个简单的数据集和数据加载器。接着,我们使用 AdamW 优化器和交叉熵损失函数来训练模型,训练完后保存微调后的模型。


相关文章
|
1月前
|
存储 机器学习/深度学习 人工智能
大模型微调技术:LoRA原理与实践
本文深入解析大语言模型微调中的关键技术——低秩自适应(LoRA)。通过分析全参数微调的计算瓶颈,详细阐述LoRA的数学原理、实现机制和优势特点。文章包含完整的PyTorch实现代码、性能对比实验以及实际应用场景,为开发者提供高效微调大模型的实践指南。
1689 2
|
3月前
|
XML JSON 数据库
大模型不听话?试试提示词微调
想象一下,你向大型语言模型抛出问题,满心期待精准回答,得到的却是答非所问,是不是让人抓狂?在复杂分类场景下,这种“大模型不听话”的情况更是常见。
266 9
|
2月前
|
人工智能 自然语言处理 测试技术
有没有可能不微调也能让大模型准确完成指定任务?(少样本学习)
对于我这种正在从0到1构建AI产品的一人公司来说,Few Shots学习的最大价值在于:用最少的资源获得最大的效果。我不需要大量的标注数据,不需要复杂的模型训练,只需要精心设计几个示例,就能让大模型快速理解我的业务场景。
251 43
|
1月前
|
存储 数据采集 自然语言处理
56_大模型微调:全参数与参数高效方法对比
随着大型语言模型(LLM)规模的不断增长,从数百亿到数千亿参数,传统的全参数微调方法面临着计算资源消耗巨大、训练效率低下等挑战。2025年,大模型微调技术已经从早期的全参数微调发展到如今以LoRA、QLoRA为代表的参数高效微调方法,以及多种技术融合的复杂策略。本文将深入对比全参数微调和参数高效微调的技术原理、适用场景、性能表现和工程实践,为研究者和工程师提供全面的技术参考。
|
1月前
|
机器学习/深度学习 存储 人工智能
大模型微调:从理论到实践的全面指南
🌟蒋星熠Jaxonic:AI探索者,专注大模型微调技术。从LoRA到RLHF,实践医疗、法律等垂直领域模型优化,分享深度学习的科学与艺术,共赴二进制星河的极客征程。
大模型微调:从理论到实践的全面指南
|
2月前
|
机器学习/深度学习 数据采集 算法
大模型微调技术综述与详细案例解读
本文是一篇理论与实践结合的综述文章,综合性全面介绍大模型微调技术。本文先介绍大模型训练的两类场景:预训练和后训练,了解业界常见的模型训练方法。在后训练介绍内容中,引出模型微调(模型微调是属于后训练的一种)。然后,通过介绍业界常见的模型微调方法,以及通过模型微调实操案例的参数优化、微调过程介绍、微调日志解读,让读者对模型微调有更加直观的了解。最后,我们详细探讨数据并行训练DDP与模型并行训练MP两类模型并行训练技术,讨论在实际项目中如何选择两类并行训练技术。
|
4月前
|
机器学习/深度学习 数据采集 人工智能
微调之后还能做什么?大模型后训练全链路技术解析
本文探讨了后训练的重要性、方法以及最新进展。文章将包含理论分析与实际操作指南,适合希望深入了解并应用这些技术的开发者。
1026 18
微调之后还能做什么?大模型后训练全链路技术解析

热门文章

最新文章