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

news2025/7/25 10:42:09

人工智能的快速发展推动了大模型的广泛应用,它们在语言、视觉、语音等领域的应用效果已经越来越好。但是,训练一个大模型需要巨大的计算资源和时间,为了减少这种资源的浪费,微调已经成为一种流行的技术。微调是指在预训练模型的基础上,通过在小数据集上的训练来适应新的任务。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 优化器和交叉熵损失函数来训练模型,训练完后保存微调后的模型。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/394810.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2023年3月全国DAMA-CDGA/CDGP数据管理认证火热报名中...

弘博创新是DAMA中国授权的数据治理人才培养基地,贴合市场需求定制教学体系,采用行业资深名师授课,理论与实践案例相结合,快速全面提升个人/企业数据治理专业知识与实践经验,通过考试还能获得数据专业领域证书。 DAMA认…

【iOS】—— 浅看block源码

block 文章目录block如何通过终端clang生成源码cpp文件block实质截获自动变量全局变量和静态变量的截获__block说明符iOS开发“强弱共舞”——weak和strong配套使用解决block循环引用问题如何通过终端clang生成源码cpp文件 之前在学习block中学习的比较浅,只看了oc…

sentinel源码入门

sentinel是一个流量治理组件,主要用来做降级、熔断和限流,以及监控等,sentinel的使用相对来说比较简单,这篇博客主要介绍sentinel的源码 入口 在使用sentinel的时候,我们需要引入sentinel的相关jar包,然后…

如何使用码匠连接 ClickHouse

目录 在码匠中集成 ClickHouse 在码匠中使用 ClickHouse 关于码匠 ClickHouse 数据源是一种列式数据库管理系统,由俄罗斯 Yandex 公司开发和维护。它专注于高性能、高并发、高可扩展性和低延迟的数据处理,特别是在海量数据的 OLAP(联机分析…

性能分析利器:火焰图

什么是火焰图 火焰图(FlameGraph)是是由 Linux 性能优化大师 Brendan Gregg 发明的。通过 perf 等工具分析得到结果,看起来就像是火焰,这也是它的名字的由来。火焰图以一个全局的视野来看待时间分布,它从底部往顶部&am…

Dockerfile部署SpringBoot项目

Dockerfile部署SpringBoot项目 文章目录 利用Dockerfile部署SpringBoot项目 1、创建一个SpringBooot项目并且打成jar包2、在Linux中创建一个文件夹,来做docker测试3、将jar包上传到Linux中4、编写Dockerfile文件5、制作镜像6、启动容器7、查看容器启动日志8、访问接…

高效能自动化港口数字化码头智慧港航,中国人工智能企业CIMCAI世界港航人工智能领军者,成熟港口码头人工智能产品中国人工智能企业

打造高效能自动化港口数字化码头智慧港航,中国人工智能企业CIMCAI中集飞瞳世界港航人工智能领军者,成熟港口码头人工智能产品全球顶尖AI科技CIMCAI成熟AI产品全球前三船公司及港口落地,包括全球港口/堆场智能闸口验箱,全球港口岸边…

Vulnhub系列:Raven 1

该篇为Vulnhub系列靶机渗透,本次靶机存在4个flag。下面开始我们今天的渗透之旅。Raven靶机有很多种思路,我将对其进行一一整理。首先进行信息收集,利用arp-scan和nmap,进行靶机的ip及端口扫描发现了22、80、111端口。下面访问80端…

【LeetCode】剑指 Offer 23. 链表中环的入口节点 p139 -- Java Version

题目链接:https://leetcode.cn/problems/c32eOV/ 1. 题目介绍(23. 链表中环的入口节点) 给定一个链表,返回链表开始入环的第一个节点。 从链表的头节点开始沿着 next 指针进入环的第一个节点为环的入口节点。如果链表无环&#x…

怎么清空回收站?3分钟解决!

真实案例:回收站清空不了怎么办?怎样清空回收站里的文件? “各位大神,怎么恢复回收站里清空的文件?我按照百度上的方法,还是不行。” 当你在电脑上删除文件时,它们通常会被移到回收站&#xf…

mpi4py 运行过程中出现Read -1, expected xxx, errno = 1 解决方案

目录 问题描述 代码1(串行) 代码2(并行) 代码2执行时所用指令 错误信息 解决方案 解决方案1 解决方案2 问题描述 今天正在学习使用mpi4py,在对比运行以下2个代码时疯狂报错: 代码1(串…

HTML 脚本

HTML 脚本 JavaScript 是可插入 HTML 页面的编程代码。 JavaScript 使 HTML 页面具有更强的动态和交互性。 JavaScript 插入 HTML 页面后&#xff0c;可由所有的现代浏览器执行。 在线实例 插入一段脚本 如何将脚本插入 HTML 文档。 使用 <noscript> 标签 如何应对不…

非接触式流量监测设备——雷达流速仪

一、设备概述 雷达流速仪是一款非接触且可连续测量流速、水位、流量的一体式流量监测设备。它采用雷达平面微波技术&#xff0c;通过非接触方式测量水体的流速和水位。根据内置的软件算法&#xff0c;计算并输出实时断面流量及累计流量&#xff1b;可用于泵站、河道、灌渠、地…

扬帆优配|三大油气巨头都嗨了,龙头总市值盘中破万亿

近期组织盯上哪些股&#xff1f; 3月7日早盘&#xff0c;周期板块大幅上涨。石油板块涨超4%遥遥领先&#xff0c;海越能源涨停。油气巨头我国石油盘中涨近6%&#xff0c;总市值一度突破万亿元。我国石化盘中涨幅到达6.86%&#xff0c;股价创四年来新高。我国海油盘中涨停&#…

Rocketmq技术详解

Rocketmq技术详解 运维部署 docker-compose.yml version: 3.5 services:rmqnamesrv:image: foxiswho/rocketmq:servercontainer_name: rmqnamesrvports:- 9876:9876volumes:- ./logs:/opt/logs- ./store:/opt/storenetworks:rmq:aliases:- rmqnamesrvrmqbroker:image: foxisw…

后疫情时代,EIoT助力实体零售ESG战略落地

多点智能物联总经理刘汉彻 2023一开年&#xff0c;烟火气回归&#xff0c;各行各业都在摩拳擦掌&#xff0c;准备在后疫情元年“大干一场”。对企业而言&#xff0c;“降本增效”已成为跨行业的共同认知&#xff0c;实体零售也给自身的发展标定了方向&#xff1a;“彻底回归商…

CSS清楚浮动

先看看关于浮动的一些性质 浮动使元素脱离文档流 浮动元素可以设置宽高&#xff0c;在CSS中&#xff0c;任何元素都可以浮动&#xff0c;浮动元素会生成一个块级框&#xff0c;而不论其本身是何种元素。 如果没有给浮动元素指定高度&#xff0c;&#xff0c;那么它会以内容的…

JAVA SE: IO流

一、Java流式输入输出原理Java对于输入输出是以流(Stream)的方式进行的&#xff0c;JDK提供各种各样的“流”类&#xff0c;以获取不同类型的数据。可以理解为将管道插入到文件中&#xff0c;然后从管道获取数据。这个管道外边还可以套管道&#xff0c;外边的管道对数据进行处理…

Transwarp KunDB 备份恢复工具安装和备份工作自动化

备份恢复工具安装安装包# KunDR压缩包 KUNTOOL-Image-Registry-3.0.0-X86_64-final.tar.gzservice_client └── kuntools-3.0.0-final├── kundr-3.0.tar.gz└── kuntools-3.0.tar.gzkundr-3.0.tar.gz ├── bin │ ├── kunkun.sh │ ├── kuntools │ └──…

软件测试(进阶篇)(1)

一)如何根据需求来设计测试用例&#xff1f; 1)验证功能的正确性&#xff0c;合理性&#xff0c;无二义性&#xff0c;逻辑要正确 2)分析需求&#xff0c;细化需求&#xff0c;从需求中提取出测试项&#xff0c;根据测试项找到测试点&#xff0c;根据测试点具体的来进行设计测试…