卷积神经网络--网络性能提升

发布于:2025-07-19 ⋅ 阅读:(20) ⋅ 点赞:(0)

网络性能提升的作用

1.提升模型准确率;

2.提高计算速度,加快收敛;

3.提高模型对为止数据的泛化能力。

一、使用复杂的模型

        直接使用现成的模型,别人已经写好了。我们只需要站在巨人的肩膀上看世界就好~

这里使用的是ResNet模型。

1.1步骤

导入模块:from torchvision.models import resnet50

使用模型:net = resnet50(weights = ResNet50_Weights.IMAGENET1K_V1)

注意:根据pytorch安装的版本,参数会有所不同。旧版本参数用pretrained,新版本参数用weights。

1.2实现

import torch
from torchvision.models import resnet50
from torchvision.models import ResNet50_Weights

net = tesnet50(weights=ResNet50_Weights.IMAGENET1K_V1)
print(net)

结果:

 ResNet(
  (conv1): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False)
  (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (relu): ReLU(inplace=True)
  (maxpool): MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1, ceil_mode=False)
  (layer1): Sequential(
    (0): Bottleneck(
      (conv1): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
.......
  (fc): Linear(in_features=2048, out_features=1000, bias=True)
)
)

二、继续训练

        在前面已经提及了一点。就是在训练了很多次的模型基础上,以训练的模型为基础再训练模型,不会让计算机每次都从头开始训练,这样可以节省时间,也可以节省算力。

API:

model.load_state_dict(torch.load(model_path))

#简易版
import torch
import torcn.nn as nn
from torchvision import datasets,transforms
import torch.optim as optim
import os

#继续训练的训练集处理
transform_train = transforms.Compose([transforms.Totensor()])
#数据集加载
train_dataset = datasets.ImageFolder(
    root = os.path.relpath(os.path.join(os.path.dirname(__file__),'dataset/Flower/train')),
    transform = transform_train    
)
#对训练数据集设置数据加载器
train_dataloder = DataLoder(train_dataset,batch_size = 32,shuffle = True,drop_last = True)

#定义你自己的网络结构
class MyNet(nn.Module):
    def __init__(self):
        ......

    def forward(self,x):
         ......

#定义自己的设备、批次、模型、学习率...
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = MyNet()
model.to(device)
epochs = 30
lr = 0.001
optimizer = optim.Adam(model.parameters(),lr = lr)
criterion = nn.CrossEntropyLoss()
#加载之前的模型
model.load_state_dict(torch.load(os.path.relpath(os.path.join(os.path.dirname(__file__),'models/last.pth'))))

#训练流程
for epoch in range(epochs):
    model.train()
    acc_total = 0
    loss_total = 0
    for i,(x,y) in enumerate(train_dataloder):
        x = x.to(device)
        y = y.to(device)
        out = model(x)
        loss = criterion(y,out)
        optim.zero_grad()
        loss.backward()
        optim.step()
        out1 = torch.argmax(out,dim=1)
        acc_total += (out1==y).sum().item()
        loss_total += loss.item()
        torch.save(model.state_dict(),model_path)
        
        print(f'进度{epoch/epochs},总损失{loss_total/len(train_dataloder.dataset)},准确率{acc_total/len(train_dataloder.dataset)}') 








三、预训练

        预训练的意义是利用迁移学习的优势,快速提升模型性能并减少训练成本。

import torch
from torchvision.models import resnet50
from torchvision.models import ResNet50_Weights

net = tesnet50(weights=ResNet50_Weights.IMAGENET1K_V1)
print(net)
#保存预训练权重参数
torch.save(net.state_dict(),'resnet50.pth')

 

四、迁移学习

4.1意义

        在别人已经测试的很完美的数据上进行修改,减少运算、节约成本,提高模型准确性,泛化能力。虽然别人的数据很完美,但是还要与我们自己的数据贴合起来,这样才能达到更好的效果,尤其是输入的数目和最后的输出分类数目一定要对应的上才行。

4.2步骤

        (1)导入相关模块;

        (2)进行预训练,保存预训练的权重结果;

        (3)创建没有预训练的模型;

        (4)修改预训练里面与我们数据不符合的数据信息;

        (5)将预训练的权重参数加载出来,并删除输出不正确的全连接层fc;

        (6)将预训练的权重参数更新到没有预训练的权重参数字典中;

        (7)冻结不需要修改的权重参数即除了fc的所有参数;

        (8)对fc进行筛选,进行梯度计算。

4.3实现

这是resnet50的输出fc结果: (fc): Linear(in_features=2048, out_features=1000, bias=True)

可以发现明显不对,因此需要修改,就有了上序步骤。

import torch
import torch.nn as nn
from torchvision.models import resnet50
from torchvision.models import ResNet50_Weights
import os

#创建没有预训练权重的resnet50模型
net_model = resnet50(weights = None)

#修改网络结构中不正确的信息
in_features = net_model.fc.in_features
print(in_features) #2048
net_model = nn.Linear(in_features, 3)

#加载预训练权重
resnet_path = os.path.relpath(os.path.join(os.path.dirname(__file__), 'model/resnet50.pth'))
pretrained_dict = torch.load(resnet_path)
pretrained_dict.pop('fc.weight')
pretrained_dict.pop('fc.bias')

#将预训练权重更新到没有预训练权重的模型中
#获取模型中所有可训练参数(如权重、偏置)的字典。
net_model_dict = net_model.state_dict()
net_model_dict.update(pretrained_dict)
#将保存的参数字典加载到模型中。
net_model.load_state_dict(net_model_dict)

#冻结参数
for name,param in net_model.named_parameters():
    if name!='fc.weight' and name!='fc.bias':
        param.requires_grad = False

#梯度计算fc--从模型中筛选出需要计算梯度的参数(即 requires_grad=True 的参数)
params_grad_true = filter(lambda x: x.requires_grad, net_model.parameters())
optimizer = torch.optim.Adam(params_grad_true, lr=0.001)

五、调整优化器和学习率

        调整优化器就是冻结正确的参数,计算需要重新梯度计算的fc的权重和偏置。

优化器:

for name,value in pretrained_model.named_parameters():
    if name!='fc.weight' and name!='fc.bias':
        value.requires_grad = False
param_grade_true = filter(lambda x:x.requires_grad,pretrained_model.parameters())

optimizer = torch.optim.Adam(param_grade_true,lr = learning_rate)

学习率:

scheduler = optim.lr_scheduler.StepLR(optimizer,step_size=30,gamma=0.1)
scheduler.step()

 用于学习率衰减的调度器,作用是在训练过程中按固定间隔降低学习率,以帮助模型更好地收敛(避免因学习率过高导致震荡,或过低导致收敛缓慢)。


网站公告

今日签到

点亮在社区的每一天
去签到