3.2.微调

news2024/9/9 0:04:43

微调

​ 对于一些样本数量有限的数据集,如果使用较大的模型,可能很快过拟合,较小的模型可能效果不好。这个问题的一个解决方案是收集更多数据,但其实在很多情况下这是很难做到的。

​ 另一种方法就是迁移学习(transfer learning),将源数据集学到地知识迁移到目标数据集,例如,我们只想识别椅子,只有100把椅子,每把椅子的1000张不同角度的图像,尽管ImageNet数据集中大多数图像与椅子无关,但在次数据集上训练的模型可能会提取更通用的图像特征(可以理解为越底层的layer提取的特征越通用),这有助于识别边缘、纹理、形状和对象组合,也可能有效地识别椅子。

在这里插入图片描述

1. 步骤

​ 微调是迁移学习中的常见技巧,步骤如下:

  1. 在源数据集(例如ImageNet数据集)上预训练神经网络模型,即源模型
  2. 创建一个新的神经网络模型,即目标模型。这将复制源模型上的所有模型设计及其参数(输出层除外)。我们假定这些模型参数包含从源数据集中学到的知识,这些知识也将适用于目标数据集。我们还假设源模型的输出层与源数据集的标签密切相关;因此不在目标模型中使用该层。
  3. 向目标模型添加输出层,其输出数是目标数据集中的类别数。然后随机初始化该层的模型参数。
  4. 在目标数据集(如椅子数据集)上训练目标模型。输出层将从头开始进行训练,而所有其他层的参数将根据源模型的参数进行微调。

在这里插入图片描述

1.1 目标模型的训练:

​ 是一个正在目标数据集上的正常训练任务,但使用更强的正则化(参数变化不大):

  • 更小的学习率
  • 更少的数据迭代

​ 如果源数据集远复杂于目标数据,通常微调效果更好

1.2 重用分类器权重

​ 有些时候源数据集可能也有目标数据中的部分标号,比如ImageNet里可能有椅子这一标签,那么可以使用预训练好的模型分类器中对应标号中对应的向量来做初始化(就直接copy)

1.3 固定一些层

​ 通常而言,神经网络中低层次的特征更加通用,高层次的特征则更跟数据集相关。

​ 那么可以固定底部一些层的参数,不参与更新,这样也能有更强的正则。

2.热狗识别

import os
import torch
import torchvision
from torch import nn
from d2l import torch as d2l
import torch_directml

device = torch_directml.device()
# @save
d2l.DATA_HUB['hotdog'] = (d2l.DATA_URL + 'hotdog.zip',
                          'fba480ffa8aa7e0febbb511d181409f899b9baa5')

data_dir = d2l.download_extract('hotdog')

train_imgs = torchvision.datasets.ImageFolder(os.path.join(data_dir, 'train'))
test_imgs = torchvision.datasets.ImageFolder(os.path.join(data_dir, 'test'))

hotdogs = [train_imgs[i][0] for i in range(8)]
not_hotdogs = [train_imgs[-i - 1][0] for i in range(8)]
d2l.show_images(hotdogs + not_hotdogs, 2, 8, scale=1.4)
d2l.plt.show()

# 使用RGB通道的均值和标准差,以标准化每个通道 ,因为预训练的模型做了这个
normalize = torchvision.transforms.Normalize(
    [0.485, 0.456, 0.406], [0.229, 0.224, 0.225])

# 先随机裁剪,并变为224 * 224 的图形,因为预训练模型输入是这个
train_augs = torchvision.transforms.Compose([
    torchvision.transforms.RandomResizedCrop(224),
    torchvision.transforms.RandomHorizontalFlip(),
    torchvision.transforms.ToTensor(),
    normalize])
# 将图像的高度和宽度都缩放到256像素,然后裁剪中央 224 * 224的区域来作为输入
test_augs = torchvision.transforms.Compose([
    torchvision.transforms.Resize([256, 256]),
    torchvision.transforms.CenterCrop(224),
    torchvision.transforms.ToTensor(),
    normalize])

# 下载模型,pretrained参数已被弃用,使用weights来获取与训练模型
pretrained_net = torchvision.models.resnet18(weights=torchvision.models.ResNet18_Weights.IMAGENET1K_V1)
print(pretrained_net.fc)  # 预训练最后一层为输出层

finetune_net = torchvision.models.resnet18(weights=torchvision.models.ResNet18_Weights.IMAGENET1K_V1).to(device)
finetune_net.fc = nn.Linear(finetune_net.fc.in_features, 2).to(device)
nn.init.xavier_uniform_(finetune_net.fc.weight)


def train_batch_ch13(net, X, y, loss, trainer, devices):
    """用多GPU进行小批量训练"""
    if isinstance(X, list):
        # 微调BERT中所需
        X = [x.to(devices) for x in X]
    else:
        X = X.to(devices)
    y = y.to(devices)
    net.train()
    trainer.zero_grad()
    pred = net(X)
    l = loss(pred, y)
    l.sum().backward()
    trainer.step()
    train_loss_sum = l.sum()
    train_acc_sum = d2l.accuracy(pred, y)
    return train_loss_sum, train_acc_sum


# @save 多GPU的,把参数devices改成device了,本来是个列表
def train_ch13(net, train_iter, test_iter, loss, trainer, num_epochs,
               device):
    """用多GPU进行模型训练"""
    timer, num_batches = d2l.Timer(), len(train_iter)
    animator = d2l.Animator(xlabel='epoch', xlim=[1, num_epochs], ylim=[0, 1],
                            legend=['train loss', 'train acc', 'test acc'])
    # net = nn.DataParallel(net, device_ids=devices).to(devices[0])
    for epoch in range(num_epochs):
        # 4个维度:储存训练损失,训练准确度,实例数,特点数
        metric = d2l.Accumulator(4)
        for i, (features, labels) in enumerate(train_iter):
            timer.start()
            l, acc = train_batch_ch13(
                net, features, labels, loss, trainer, device)
            metric.add(l, acc, labels.shape[0], labels.numel())
            timer.stop()
            if (i + 1) % (num_batches // 5) == 0 or i == num_batches - 1:
                animator.add(epoch + (i + 1) / num_batches,
                             (metric[0] / metric[2], metric[1] / metric[3],
                              None))
        test_acc = d2l.evaluate_accuracy_gpu(net, test_iter)
        animator.add(epoch + 1, (None, None, test_acc))
    print(f'loss {metric[0] / metric[2]:.3f}, train acc '
          f'{metric[1] / metric[3]:.3f}, test acc {test_acc:.3f}')
    print(f'{metric[2] * num_epochs / timer.sum():.1f} examples/sec on '
          f'{str(device)}')


# 微调
# 如果param_group=True,输出层中的模型参数将使用十倍的学习率
def train_fine_tuning(net, learning_rate, batch_size=128, num_epochs=5,
                      param_group=True):
    train_iter = torch.utils.data.DataLoader(torchvision.datasets.ImageFolder(
        os.path.join(data_dir, 'train'), transform=train_augs),
        batch_size=batch_size, shuffle=True)
    test_iter = torch.utils.data.DataLoader(torchvision.datasets.ImageFolder(
        os.path.join(data_dir, 'test'), transform=test_augs),
        batch_size=batch_size)
    # devices = d2l.try_all_gpus()
    device = torch_directml.device()
    loss = nn.CrossEntropyLoss(reduction="none")
    if param_group:
        params_1x = [param for name, param in net.named_parameters()
                     if name not in ["fc.weight", "fc.bias"]]
        # 最后一层使用10倍学习率
        trainer = torch.optim.SGD([{'params': params_1x},
                                   {'params': net.fc.parameters(),
                                    'lr': learning_rate * 10}],
                                  lr=learning_rate, weight_decay=0.001)
    else:
        trainer = torch.optim.SGD(net.parameters(), lr=learning_rate,
                                  weight_decay=0.001)

    train_ch13(net, train_iter, test_iter, loss, trainer, num_epochs,
               device)


train_fine_tuning(finetune_net, 5e-5)
d2l.plt.show()

loss 0.270, train acc 0.899, test acc 0.948
232.6 examples/sec on privateuseone:0

一次训练效果就很好了,而且后续训练很平滑,没有过拟合。

在这里插入图片描述

​ 如果初始化为随机值:
在这里插入图片描述

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

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

相关文章

window长时间不关机,卡顿处理方法

window使用一短时间非常卡,快速处理办法如下: 1、windowR 输入%temp% 手动删除临时目录文件。 2、windowR输入cleanmgr 磁盘清理 3、恶意软件删除工具 删除流行恶意软件。

What Is RPC(Remote Procedure Call,远程过程调用)

RPC(Remote Procedure Call,远程过程调用)是一种计算机通信协议,它允许一个计算机程序通过网络调用另一个计算机程序中的子程序(也就是远程过程),并获取返回值。RPC服务是分布式计算的重要基础&…

面向对象程序设计(C++)模版初阶

1. 函数模版 1.1 函数模版概念 函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本,可以类比函数参数,函数模版就是将函数参数替换为特定类型版本 1.2 函数模版格…

mlp与attention的计算时间复杂度分别为多少?PAtchtst为啥patch后为啥attention计算量降低?

感谢分享 看这篇博客的时候,因为patch后做了一个fc的映射,也是有计算的消耗嘛,好奇为什么说patchtst能够减小“注意力图的内存使用和计算复杂度减少了S倍,从而在计算资源有限的情况下允许模型查看更长的历史序列。“ 所以思考了一…

【时时三省】(C语言基础)循环语句while(2)

山不在高,有仙则名。水不在深,有龙则灵。 ——csdn时时三省 getchar和scanf的作用 示例: int main ( ) { char password[20] ( 0 ) ; printf ( "请输入密码:> " ); scanf ( " %s…

Redis:未授权访问

Redis Redis(Remote Dictionary Server)是一个开源的高性能键值对(key-value)数据库,支持多种类型的数据结构。 核心特性 内存存储:Redis将所有数据存储在内存中,能够提供极高的读写性能。 …

jumpserver web资源--远程应用发布机

1、环境 jumpserver:3.10.10 远程发布机:windows 2019 2、windows 2019准备 保证windows 正常登录,并且可以访问jumpserver 3、添加远程发布机 能正常连接就继续 可看到这里正常了 4、添加web资源 找到我们需要自动登录界面 获取相关元素选…

独立3D网络游戏《战域重甲》开发与上架经验分享

“ 小编阿麟:心之所向便是光,我们都是追光者!这位独立游戏开发者的产品能力已经不输给许多小团队,希望他的故事和经验分享,可以给走在同样道路上的朋友一些信心和帮助。 背景介绍 2023年年底的时候,我突然有一个很强的…

OpenGL3.3_C++_Windows(32)

demo SSAO SSAO 环境光照(Ambient Lighting):光的散射,我们通过一个固定的常量作为环境光的模拟,但是这种固定的环境光并不能很好模拟散射,因为环境光不是一成不变的,环境光遮蔽:让(褶皱、孔洞…

Qt Designer,仿作一个ui界面的练习(一):界面的基本布局

初学不要太复杂,先做一个结构简单的,大致规划一下功能分区,绘制草图: 最终的效果: 界面主要由顶边栏、侧边栏、内容区构成。顶边栏左边是logo,右边是时钟显示。侧边栏最上边是切换按钮,用以动画…

Notcoin 即将空投:你需要知道什么

Notcoin 于 2024 年 1 月推出,是 Telegram 上的一款边玩边赚游戏,用户可以通过点击硬币图标获得 Notcoin 代币 (NOT) 形式的奖励。NOT 建立在开放网络区块链(称为“TON 区块链”)上,由 Open Builders 创始人 Sasha Plo…

鸿蒙配置Version版本号,并获取其值

app.json5中配置版本号: 获取版本号: bundleManager.getBundleInfoForSelf(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION).then((bundleInfo) > {let versionName bundleInfo.versionName; //应用版本号}).catch((error: BusinessE…

基于web的跨校区通勤车班次规划系统/校车管理系统

获取源码联系方式请查看文章结尾🍅 摘 要 随着信息技术和网络技术的飞速发展,人类已进入全新信息化时代,传统管理技术已无法高效,便捷地管理信息。为了迎合时代需求,优化管理效率,各种各样的管理系统应运而…

STM32项目分享:智能台灯(机智云)系统

目录 一、前言 二、项目简介 1.功能详解 2.主要器件 三、原理图设计 四、PCB硬件设计 PCB图 五、程序设计 六、实验效果 七、资料内容 项目分享 一、前言 项目成品图片: 哔哩哔哩视频链接: https://www.bilibili.com/video/BV1My411q7fE…

常见的CSS属性(一)——字体、文本、边框、内边距、外边距、背景、行高、圆角、透明度、颜色值

一、字体 二、文本 三、边框 四、外边距 五、内边距 六、背景 七、行高 八、圆角 九、透明度 九、颜色值 元素的继承性是指给父元素设置了某些属性,子元素或后代元素也会有作用。 一、字体 “font-*”是字体相关的属性,具有继承性。代码如下&a…

长上下文语言模型与RAPTOR 方法

在科技领域的前沿,长上下文语言模型(Long Context LLMs)和新兴检索方法如RAPTOR 正在引发广泛关注。本文将围绕这些技术展开讨论,并探讨它们在实际应用中的创新性和科技性。 长上下文语言模型的崛起 近几周来,随着新型…

基于 SSM 的汽车租赁系统

基于 SSM 的电器网上订购系统 开发语言:Java 数据库:MySQL 技术:Spring、JSP、MyBatis 工具:MyEclipse/IDEA、Tomcat 引言 汽车租赁是在约定时间内,租赁经营人将租赁汽车(包括载货汽车和载客汽车&#x…

前端在浏览器总报错,且获取请求头中token的值为null

前端请求总是失败说受跨域请求影响,但前后端配置已经没有问题了,如下: package com.example.shop_manage_sys.config;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Conf…

paddle ocr 文字识别模型训练 svtr

训练模型方法参考:https://github.com/PaddlePaddle/PaddleOCR/blob/main/doc/doc_ch/recognition.md 实践:https://aistudio.baidu.com/projectdetail/4482681 SVTR 算法原理 SVTR: Scene Text Recognition with a Single Visual Model Yongkun Du a…

Linux网络-ss命令

作者介绍:简历上没有一个精通的运维工程师。希望大家多多关注我,我尽量把自己会的都分享给大家,下面的思维导图也是预计更新的内容和当前进度(不定时更新)。 Linux服务器作为一个常用的网络服务器,主要的作用就是向客户端提供网络…