基于pytorch实现Resnet对本地数据集的训练

本文详细介绍了使用PyTorch框架训练ResNet模型对本地数据集进行分类的步骤,包括数据预处理、网络结构和训练过程。通过dataset.py、network.py和train.py三个文件实现数据加载、模型构建和模型训练,并展示了代码流程图。最终结果显示模型在小数据集上表现一般,可能因数据量不足导致泛化能力较弱。

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

  本文需要具备python编辑器和pytorch深度学习框架的语句基础知识

目录

文章目录

前言

一、dataset.py文件

二、network.py文件

三、train.py

结果与总结


前言

       本文是使用pycharm下的pytorch框架编写一个训练本地数据集的Resnet深度学习模型,其一共有两百行代码左右,分成mian.py、network.py、dataset.py以及train.py文件,功能是对本地的数据集进行分类。本文介绍逻辑是总分形式,即首先对总流程进行一个概括,然后分别介绍每个流程中的实现过程(代码+流程图+文字的介绍)。

       对于整个项目的流程首先是加载本地数据集,然后导入Resnet网络,最后进行网络训练。整体来说一个完整的小项目,难度并不高,需要有一定的pytorch语句以及深度学习的基础。

       mian.py文件是该项目的总文件,也是训练网络模型的运行文件,文本的介绍流程是随着该文件一 一对代码进行介绍。

  main.py代码如下所示:

from dataset import data_dataloader    #电脑本地写的读取数据的函数
from torch import nn                   #导入pytorch的nn模块
from torch import optim                #导入pytorch的optim模块
from network import Res_net            #电脑本地写的网络框架的函数
from train import train                #电脑本地写的训练函数

def main():
    # 以下是通过Data_dataloader函数输入为:数据的路径,数据模式,数据大小,batch的大小,有几线并用 (把dataset和Dataloader功能合在了一起)
    train_loader = data_dataloader(data_path='./data', mode='train', size=64, batch_size=24, num_workers=4)
    val_loader = data_dataloader(data_path='./data', mode='val', size=64, batch_size=24, num_workers=2)
    test_loader = data_dataloader(data_path='./data', mode='test', size=64, batch_size=24, num_workers=2)

    # 以下是超参数的定义
    lr = 1e-4           #学习率
    epochs = 10         #训练轮次

    model = Res_net(2)  # resnet网络
    optimizer = optim.Adam(model.parameters(), lr=lr)  # 优化器
    loss_function = nn.CrossEntropyLoss()  # 损失函数

    # 训练以及验证测试函数
    train(model=model, optimizer=optimizer, loss_function=loss_function, train_data=train_loader, val_data=val_loader,test_data= test_loader, epochs=epochs)

if __name__ == '__main__':
    main()

 main.py流程图如图1所示:

图 1 main.py 代码流程图

一、dataset.py文件

       main.py()前五行分别是导入相应的模块,其中dataset,network以及train是本地编写的文件。在mian()函数中的前几行代码中,我们使用dataset.py文件中的Data_dataloader函数导入训练集、验证集和测试集。Dataset文件是导入我们自己的本地数据库,其功能是得到所有的数据,将其变成pytorch能够识别的tensor数据,然后得到图片。

       dataset.py文件代码如下所示:

import torch
import os,glob
import random
import csv
from torch.utils.data import Dataset
from PIL import Image
from torchvision import transforms
from torch.utils.data import DataLoader

# 第一部分:通过三个步骤得到输出的tensor类型的数据
class Dataset_self(Dataset):                    #如果是nn.moduel 则是编写网络模型框架,这里需要继承的是dataset的数据,所以括号中的是Dataset
    #第一步:初始化
    def __init__(self,root,mode,resize,):       #root是文件根目录,mode是选择什么样的数据集,resize是图像重新调整大小
        super(Dataset_self, self).__init__()
        self.resize = resize
        self.root = root
        self.name_label = {}       #创建一个字典来保存每个文件的标签
        #首先得到标签相对于的字典(标签和名称一一对应)
        for name in sorted(os.listdir(os.path.join(root))):     #排序并且用列表的形式打开文件夹
            if not os.path.isdir(os.path.join(root,name)):      #不是文件夹就不需要读取
                continue
            self.name_label[name] = len(self.name_label.keys())  #每个文件的名字为name_Label字典中有多少对键值对的个数
        #print(self.name_label)
        self.image,self.label = self.make_csv('images.csv')       #编写一共函数来读取图片和标签的路径
        #在得到image和label的基础上对图片数据进行一共划分  (注意:如果需要交叉验证就不需要验证集,只划分为训练集和测试集)
        if mode == 'train':
            self.image ,self.label= self.image[:int(0.6*len(self.image))],self.label[:int(0.6*len(self.label))]
        if mode == 'val':
            self.image ,self.label= self.image[int(0.6*len(self.image)):int(0.8*len(self.image))],self.label[int(0.6*len(self.label)):int(0.8*len(self.label))]
        if mode == 'test':
            self.image ,self.label= self.image[int(0.8*len(self.image)):],self.label[int(0.8*len(self.label)):]
    # 获得图片和标签的函数
    def make_csv(self,filename):
        if not os.path.exists(os.path.join(self.root,filename)):  #如果不存在汇总的目录就新建一个
            images = []
            for image in self.name_label.keys():                            # 让image到name_label中的每个文件中去读取图片
                images += glob.glob(os.path.join(self.root,image,'*jpg'))   #加* 贪婪搜索关于jpg的所有文件
            #print('长度为:{},第二张图片为:{}'.format(len(images),images[1]))
            random.shuffle(images)                                         #把images列表中的数据洗牌
            # images[0]: ./data\ants\382971067_0bfd33afe0.jpg
            with open(os.path.join(self.root,filename),mode='w',newline='') as f :  #创建文件
                writer = csv.writer(f)
                for image in
### 使用ResNet模型训练自定义数据集 #### 准备环境和导入库 为了使用ResNet模型来训练自定义数据集,在Python环境中安装必要的依赖包,如`torch`, `torchvision`以及用于图像处理的工具。确保已经设置好了合适的开发环境。 ```bash pip install torch torchvision matplotlib pillow scikit-image ``` #### 加载并预处理数据 针对特定应用领域内的自定义数据集,通常需要执行一系列预处理操作以适应所选框架的要求。这包括但不限于调整大小、裁剪、翻转等增强技术,使输入符合预期标准[^3]。 ```python from torchvision import transforms, datasets import os data_transforms = { 'train': transforms.Compose([ transforms.RandomResizedCrop(224), transforms.RandomHorizontalFlip(), transforms.ToTensor(), transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]) ]), 'val': transforms.Compose([ transforms.Resize(256), transforms.CenterCrop(224), transforms.ToTensor(), transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]) ]), } image_datasets = {x: datasets.ImageFolder(os.path.join(data_dir, x), data_transforms[x]) for x in ['train', 'val']} dataloaders = {x: torch.utils.data.DataLoader(image_datasets[x], batch_size=4, shuffle=True, num_workers=4) for x in ['train', 'val']} dataset_sizes = {x: len(image_datasets[x]) for x in ['train', 'val']} class_names = image_datasets['train'].classes ``` #### 初始化ResNet模型 利用PyTorch提供的API可以方便地获取预训练好的ResNet模型,并根据实际需求对其进行适当修改以便更好地服务于目标任务。这里展示了如何基于ResNet50构建一个新的分类器。 ```python import torchvision.models as models model_ft = models.resnet50(pretrained=True) for param in model_ft.parameters(): param.requires_grad = False num_ftrs = model_ft.fc.in_features model_ft.fc = nn.Linear(num_ftrs, number_of_classes) ``` #### 定义损失函数与优化算法 选择适合于当前任务类型的损失计算方式(例如交叉熵),同时指定一个有效的梯度下降策略来进行参数更新。考虑到可能存在的过拟合风险,建议引入正则化机制或早停法作为辅助措施之一[^1]。 ```python criterion = nn.CrossEntropyLoss() optimizer_conv = optim.SGD(model_ft.fc.parameters(), lr=0.001, momentum=0.9) exp_lr_scheduler = lr_scheduler.StepLR(optimizer_conv, step_size=7, gamma=0.1) ``` #### 训练模型 通过循环迭代整个训练集合多次的方式逐步改善模型性能直至满足收敛条件为止;期间定期评估验证集上的表现情况从而决定何时停止训练过程。 ```python device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") def train_model(model, criterion, optimizer, scheduler, num_epochs=25): since = time.time() best_model_wts = copy.deepcopy(model.state_dict()) best_acc = 0.0 for epoch in range(num_epochs): print('Epoch {}/{}'.format(epoch, num_epochs - 1)) print('-' * 10) # Each epoch has a training and validation phase for phase in ['train', 'val']: if phase == 'train': model.train() else: model.eval() running_loss = 0.0 running_corrects = 0 for inputs, labels in dataloaders[phase]: inputs = inputs.to(device) labels = labels.to(device) outputs = model(inputs) _, preds = torch.max(outputs, 1) loss = criterion(outputs, labels) if phase == 'train': optimizer.zero_grad() loss.backward() optimizer.step() running_loss += loss.item() * inputs.size(0) running_corrects += torch.sum(preds == labels.data) if phase == 'train': scheduler.step() epoch_loss = running_loss / dataset_sizes[phase] epoch_acc = running_corrects.double() / dataset_sizes[phase] print('{} Loss: {:.4f} Acc: {:.4f}'.format( phase, epoch_loss, epoch_acc)) if phase == 'val' and epoch_acc > best_acc: best_acc = epoch_acc best_model_wts = copy.deepcopy(model.state_dict()) print() time_elapsed = time.time() - since print('Training complete in {:.0f}m {:.0f}s'.format( time_elapsed // 60, time_elapsed % 60)) print('Best val Acc: {:4f}'.format(best_acc)) model.load_state_dict(best_model_wts) return model ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值