【PyTorch学习笔记】01——Inception卷积神经网络模型训练(文件夹命名加载数据集)

本文介绍如何使用PyTorch构建卷积神经网络(CNN)解决二分类问题,包括数据集组织、预处理、InceptionA模块设计、模型训练与动态学习率调整。作者通过实例演示了如何使用文件夹名分组数据,并探讨了批量大小对训练稳定性的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考:

网络模型讲解和搭建:B站 刘二大人 ,传送门PyTorch深度学习实践——卷积神经网络(高级篇)

课代表笔记:https://blog.csdn.net/bit452/article/details/109693790?spm=1001.2014.3001.5501

动态化学习率:https://blog.csdn.net/a906958671/article/details/104967447

数据集加载参考:https://github.com/HubAIZ123/Pytorch-/blob/main/%E6%95%B0%E6%8D%AE%E5%8A%A0%E8%BD%BD%E7%9A%84%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.ipynb

 

采用的是使用文件夹名进行数据集分组:

dog:crab

训练集二分类各450张;验证集:50张

 

import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from torchvision import datasets
from torch.utils.data import DataLoader
import torch.optim as optim
import matplotlib.pyplot as plt
import cv2
import copy
import numpy as np 


batch_size = 32
LR = 0.002
Mom = 0.02
transform = transforms.Compose([
#  transforms.Resize(224), # 缩放图片(Image),保持长宽比不变,最短边为32像素
#  transforms.CenterCrop(224), # 从图片中间切出32*32的图片
 transforms.ToTensor(), # 将图片(Image)转成Tensor,归一化至[0, 1]
 transforms.Normalize(mean=[0.492, 0.461, 0.417], std=[0.256, 0.248, 0.251]) # 标准化至[-1, 1],规定均值和标准差
])

train_dataset = datasets.ImageFolder(root="D:\\VScode_workfile\\CNN_test\\train", transform=transform)
train_loader = DataLoader(train_dataset, shuffle=True, batch_size=batch_size)

val_dataset = datasets.ImageFolder(root="D:\\VScode_workfile\\CNN_test\\val", transform=transform)
val_loader = DataLoader(val_dataset, shuffle=False, batch_size=batch_size)

 
# img, label = train_dataset[0] #print show me what is this
# print(label)
# print(img.size)


# design model using class
#InceptionA 类,方便待会做网络的拼接
class InceptionA(nn.Module):
    def __init__(self, in_channels):
        super(InceptionA, self).__init__()
        self.branch1x1 = torch.nn.Conv2d(in_channels, 16, kernel_size=1)
 
        self.branch5x5_1 = nn.Conv2d(in_channels, 16, kernel_size=1)
        self.branch5x5_2 = nn.Conv2d(16, 24, kernel_size=5, padding=2)
 
        self.branch3x3_1 = nn.Conv2d(in_channels, 16, kernel_size=1)
        self.branch3x3_2 = nn.Conv2d(16, 24, kernel_size=3, padding=1)
        self.branch3x3_3 = nn.Conv2d(24, 24, kernel_size=3, padding=1)
 
        self.branch_pool = nn.Conv2d(in_channels, 24, kernel_size=1)

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

        branch5x5 = self.branch5x5_1(x)
        branch5x5 = self.branch5x5_2(branch5x5)

        branch3x3 = self.branch3x3_1(x)
        branch3x3 = self.branch3x3_2(branch3x3)
        branch3x3 = self.branch3x3_3(branch3x3)

        branch_pool = F.avg_pool2d(x,kernel_size = 3, stride=1,padding=1)
        branch_pool = self.branch_pool(branch_pool)

        outputs = [branch1x1, branch5x5, branch3x3, branch_pool]
        return torch.cat(outputs, dim=1) #b,c,w,h   c对应的是dim = 1
        
#卷积神经网络类的搭建        
class Net(nn.Module):
    def __init__(self):
        super(Net,self).__init__()
        self.conv1 = nn.Conv2d(3,10,kernel_size = 5)
        self.conv2 = nn.Conv2d(88,20,kernel_size = 5)

        self.incep1 = InceptionA(in_channels = 10)
        self.incep2 = InceptionA(20)
        
        self.mp = nn.MaxPool2d(2)
        self.fc = nn.Linear(247192,10)

    def forward(self, x):
        in_size = x.size(0)
        x = F.relu(self.mp(self.conv1(x)))
        x = self.incep1(x)
        x = F.relu(self.mp(self.conv2(x)))
        x = self.incep2(x)
        x = x.view(in_size, -1)
        #print(x.size()) 可以先进行打印出来看看最后输出多少
        x = self.fc(x)

        return x

model = Net()
#使用GPU训练数据,和进行梯度的求解
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") 
model.to(device)
# construct loss and optimizer
#交叉熵损失函数
criterion = torch.nn.CrossEntropyLoss()
criterion = criterion.to(device)
#动态化学习率
optimizer = optim.SGD(model.parameters(), lr = LR, momentum = Mom)
scheduler = optim.lr_scheduler.StepLR(optimizer,step_size=4,gamma = 0.65)
# training cycle forward, backward, update





def train(epoch):
    running_loss = 0.0
    epoch_loss = 10.0
    for batch_idx, data in enumerate(train_loader,0):
        input,target = data
        input,target = input.to(device),target.to(device)
        optimizer.zero_grad()

        output = model(input)
        loss = criterion(output, target)
        loss.backward()
        optimizer.step()

        running_loss += loss.item()
        print("loss = %.3f" % running_loss)
        if batch_idx % 15 == 14:
            av_epoch_loss = running_loss/15
            print('[%d, %5d] loss: %.3f' % (epoch+1, batch_idx+1, av_epoch_loss))
            if av_epoch_loss < epoch_loss:
                epoch_loss = av_epoch_loss
            running_loss = 0.0

    return epoch_loss


def val():
    correct = 0
    total = 0
    with torch.no_grad():
        for data in val_loader:
            images, labels = data
            images,labels = images.to(device),labels.to(device)
            outputs = model(images)
            _, predicted = torch.max(outputs.data, dim=1)
            total += labels.size(0)
            correct += (predicted == labels).sum().item()
    print('accuracy on test set: %d %% ' % (100*correct/total))
    return correct/total



if __name__ == '__main__':
    epoch_list = []
    loss_list = []
    val_list = []
    val_acc = 0
    best_model = None
    min_loss_val = 10  # 任取一个大数
    Cheng_loss = 1.0

    for epoch in range(20):
        Cheng_loss = train(epoch)
        val_acc = val()
        print("------------------------------------------------------")
        print('Epoch :  %5d    loss: %.3f   acc: %.3f' % (epoch+1, Cheng_loss, val_acc))
        if  Cheng_loss <= min_loss_val:
            min_loss_val = Cheng_loss
            best_model = copy.deepcopy(model)#might something wrong with it   、
            #将最好的模型保存下来
            torch.save(model,"D:\\VScode_workfile\\CNN_test\\best.pkl")
        epoch_list.append(epoch)
        if Cheng_loss>1:
            Cheng_loss = 1.0
        loss_list.append(Cheng_loss)
        val_list.append(val_acc)
        # lenth = loss_list.size()

    fig, ax = plt.subplots()
    ax.plot(epoch_list, val_list, label='val')
    ax.plot(epoch_list, loss_list, label='loss')
    # ax.scatter([1, 2, 3, 4], [20, 10, 30, 15], label='Point')
    ax.set(ylabel='val and loss ', xlabel='epoch', title='A total train and val')
    ax.legend()
    plt.show()

 

关于训练结果,分析下来还是太少,看不出来了,batch_size 越大越好,能够减少震荡,学习记录。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值