当前位置: 首页 > article >正文

12.06 深度学习-预训练

# 使用更深的神经网络 经典神经网络

import torch

import cv2

from torchvision.models import resnet18,ResNet18_Weights

from torch import optim,nn

from torch.utils.data import DataLoader

from torchvision.datasets import CIFAR10

from torchvision import transforms

def demo1():

    data_train=CIFAR10(root="assets",download=False,train=True,transform=transforms.Compose([transforms.ToTensor()]))

    # # 获取权重

    # weight=ResNet18_Weights.IMAGENET1K_V1 # 1000分类的权重文件

    # net1=resnet18(weights=weight) #设置这个模型的权重

    # # 把权重保存了 这里不能直接训练 因为这个net1的fc还不是 10输出

    # torch.save(net1.state_dict(),"assets/model_pre.pt")

    # return

    # 获取模型

    net1=resnet18(weights=None)

    # 获取fc 的输入特征数               迁移学习 是网络结构有变化的 如果没有变化就是继续训练 就不是迁移学习

    in_features=net1.fc.in_features

    # 可以去改模型的层次结构 根据自己的数据来  被改的层次都要重新进行训练 不仅是fc了 被改的层次不能冻结 而且权重参数也要删掉

    net1.fc=nn.Linear(in_features=in_features,out_features=10,bias=True)

    net1.conv1=nn.Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(3, 3), bias=False)

   

    # 加载预训练权重

    state_dict=torch.load("assets/model_pre.pt",weights_only=True)

    # 线性层 的预训练权重不需要

    state_dict.pop("fc.weight")

    state_dict.pop("fc.bias")

    state_dict.pop("conv1.weight")

    # state_dict.pop("conv1.bias")

    # 更新模型的权重参数

    # net1.load_state_dict(state_dict) # 会少keys 不能用

    my_weight=net1.state_dict()

    my_weight.update(state_dict)

    net1.load_state_dict(my_weight)

    # 冻结层的使用 现在这个模型net1 只有fc需要进行训练 其他层都训练好了 给其他层冻结了只训练fc层 model.parameters()返回model的每一层权重和偏置的tensor 的迭代器 可以遍历它  named_parameters多返回一个名字

    # 把要冻结的层的权重和偏置的tensor的requires_grad=True 全设为Flase 在把model.parameters()给优化器 要过滤掉 requires_grad=Flase的

    for name,param in net1.named_parameters():

        param.requires_grad=False

    for name,param in net1.named_parameters():

        if name =="fc.weight" or name =="fc.bias" :

            param.requires_grad=True

    for name,param in net1.named_parameters():

        if name =="conv1.weight"  :

            param.requires_grad=True

       

   

    # 过滤掉 requires_grad=Flase的 权重参数

    true_weight=filter(lambda p:p.requires_grad,net1.parameters())

    dataLoader1=DataLoader(data_train,batch_size=16,shuffle=True)

    # 循环轮次

    epochs=2

    # 优化器

    optim1=optim.Adam(true_weight,lr=0.01)

    # 损失函数

    loss_func=nn.CrossEntropyLoss()

    # 开始训练

    for i in range(epochs):

        for x_train,y_train in dataLoader1:

            # 前向传播

            y_pre=net1(x_train)

            # 损失

            loss=loss_func(y_pre,y_train)

            # 清空梯度

            optim1.zero_grad()

            # 反向

            loss.backward()

            # 梯度更新

            optim1.step()

    torch.save(net1.state_dict(),"assets/model3.pt")

    # 预训练 先用一组数据 对模型进行训练 然后在 把这个模型拿出来继续训练

    # resnet18 有一个1000分类的预训练数据 这个数据拿过来改 把resnet18模型的线性层改为10分类 然后再把1000分类的预训练数据初始化给这个模型 进行再训练

    # 需要注意的是 先初始化一个这个1000分类的模型 然后保存他的权重

    # # # 获取权重

    # weight=ResNet18_Weights.IMAGENET1K_V1

    # net1=resnet18(weights=weight)

    # # 把权重保存了 这里不能直接训练 因为这个net1的fc还不是 10输出

    # torch.save(net1.state_dict(),"assets/model_pre.pt")

    print("完成")

    # 在初始化另一个来改fc

    pass

def demo2(): # 用训练的模型 对图片进行分类

    # 获得模型

    net1=resnet18(weights=None)

    in_features=net1.fc.in_features

    net1.fc=nn.Linear(in_features=in_features,out_features=10,bias=True)

    # 加载模型数据

    net1.load_state_dict(torch.load("assets/model3.pt",weights_only=True))

    # 加载图片数据 训练数据 是一个二维的 数组 RGB

    img=cv2.imread("assets/qw.jpg")

    img=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)

    img=cv2.resize(img,(32,32))

    # 转为tensor

    img=torch.tensor(img,dtype=torch.float32)

    # 换维度

    img=img.permute(2,0,1)

    # 升一个维度

    img=img.unsqueeze(0)

    # print(img.shape)

    # 推理

   

    net1.eval()

    with torch.no_grad():

        res=net1(img)

    func=nn.Softmax()

    res=func(res)

    print(res)

   

    print(torch.argmax(res,dim=1))


 

    pass

def demo3():

    # 获得模型

    net1=resnet18(weights=None)

    in_features=net1.fc.in_features

    net1.fc=nn.Linear(in_features=in_features,out_features=10,bias=True)

    # 加载模型数据

    net1.load_state_dict(torch.load("assets/model3.pt",weights_only=True))

    data_test=CIFAR10(root="assets",download=False,train=False,transform=transforms.Compose([transforms.ToTensor()]))

    data_loader1=DataLoader(data_test,shuffle=True,batch_size=32)

    acc=0

    i=0

    for x_test,y_test in data_loader1:

        # 推理

        net1.eval()

        with torch.no_grad():

            res=net1(x_test)

        func=nn.Softmax()

        res=func(res)

        res=torch.argmax(res,dim=1)

        acc+=sum(res==y_test)/len(y_test)

        i+=1

    print(acc/i)

    pass

if __name__=="__main__":

    demo1()

    # demo2()

    # demo3()


 

    pass


http://www.kler.cn/a/429716.html

相关文章:

  • Open FPV VTX开源之嵌入式OSD配置
  • Kylin: `GLIBC_2.34‘ not found
  • MMDetection框架下的常见目标检测与分割模型综述与实践指南
  • 开发人员学习书籍推荐(C#、Python方向)
  • 无源器件-电容
  • 《CPython Internals》阅读笔记:p118-p150
  • Linux下网卡实现NAT转发
  • flink-connector-mysql-cdc:03 mysql-cdc常见问题汇总
  • 智能指针中的share_ptr(共享智能指针)
  • 使用ffmpeg将视频与字幕合并为一个文件并将视频拼接
  • 永磁同步电机负载估计--线性扩张状态观测器
  • 分离轴定理检测两个凸多边形是否相交
  • AI驱动的低代码平台:解密背后的算法与架构创新
  • STC单片机I2C驱动例程
  • psmisc移植到ARM Linux环境
  • 【EthIf编译脚本】communication/EthIf/EthIf.mod.mk
  • 夜莺运维指南之自定义告警模板
  • C/C++流星雨
  • 使用php生成、识别二维码
  • ElasticSearch如何做性能优化?
  • Online Monocular Lane Mapping
  • vba学习系列(9)--按需求计数单元格数量
  • vue之$emit 获取返回值
  • 数字孪生与大型模型强强联合,共塑工业制造崭新前景
  • .NET用C#导入Excel数据到数据库
  • 面试技术点之安卓篇