首页IT科技pytorch faster rcnn训练自己的数据集(Pytorch自定义数据集模型完整训练流程)

pytorch faster rcnn训练自己的数据集(Pytorch自定义数据集模型完整训练流程)

时间2025-06-17 08:24:33分类IT科技浏览5309
导读:Pytorch模型自定义数据集训练流程...

Pytorch模型自定义数据集训练流程

我们以kaggle竞赛中的猫狗大战数据集为例搭建Pytorch自定义数据集模型训练的完整流程              。

1              、任务描述

Cats vs. Dogs(猫狗大战)数据集是Kaggle大数据竞赛某一年的一道赛题              ,利用给定的数据集                     ,用算法实现猫和狗的识别                     。 其中包含了训练集和测试集       ,训练集中猫和狗的图片数量都是12500张且按顺序排序              ,测试集中猫和狗混合乱序图片一共12500张       。

下载地址:https://www.kaggle.com/c/dogs-vs-cats/data

卷积神经网络(CNN)是一类包含卷积计算且具有深度结构的前馈神经网络                     ,是深度学习的代表算法之一              。卷积神经网络具有表征学习能力       ,能够按其阶层结构对输入信息进行平移不变分类       ,因此也被称为“平移不变人工神经网络              ”                     。

默认对图像分类各种算法已经熟悉                     ,卷积                     、池化       、批量归一化              、全连接等各种结构具体细节这里不讨论              ,有不懂的可自行学习       。

2                     、导入各种需要用到的包

import torch import torchvision from torchvision import datasets, transforms import torch.utils.data import matplotlib.pyplot as plt from torch.utils.data import TensorDataset,DataLoader,Dataset from torch.utils.tensorboard import SummaryWriter import torch.nn.functional as F from torch import nn import numpy as np import os import shutil from PIL import Image import warnings warnings.filterwarnings("ignore")

3       、分割数据集

下载猫狗大战数据集       ,并解压       。

解压完成后                     ,通过以下代码实现数据集预处理(剔除不能正常打开的图片              ,打乱数据集等);然后对数据集进行分割,其中90%的数据集作为train训练                     ,另外10%的数据集作为test测试                     。 # 分割数据集                     ,将全部数据分成0.9的Train和0.1的Test source_path = r"./kagglecatsanddogs_5340/PetImages/" # 如果不存在文件夹要新建一个 if not os.path.exists(os.path.join(source_path, "train")): os.mkdir(os.path.join(source_path, "train")) train_dir = os.path.join(source_path, "train") if not os.path.exists(os.path.join(source_path, "test")): os.mkdir(os.path.join(source_path, "test")) test_dir = os.path.join(source_path,"test") ## 将Cat和Dog文件夹全部移到train目录下,然后再从train目录下移动10%到test目录下 for category_dir in os.listdir(source_path): if category_dir not in ["train", "test"]: shutil.move(os.path.join(source_path,category_dir), os.path.join(source_path,"train")) ## 开始移动              ,移动前先剔除不能正常打开的图片 for dir in os.listdir(train_dir): category_dir_path = os.path.join(train_dir, dir) image_file_list = os.listdir(category_dir_path) # 取出全部图片文件 for file in image_file_list: try: Image.open(os.path.join(category_dir_path, file)) except: os.remove(os.path.join(category_dir_path, file)) image_file_list.remove(file) np.random.shuffle(image_file_list) test_num = int(0.1*len(image_file_list)) #移动10%文件到对应目录 if not os.path.exists(os.path.join(test_dir,dir)): os.mkdir(os.path.join(test_dir,dir)) if len(os.listdir(os.path.join(test_dir,dir))) < test_num: # 只有未移动过才需要移动                     ,否则每运行一次都会移动一下 for i in range(test_num): shutil.move(os.path.join(category_dir_path,image_file_list[i]), os.path.join(test_dir,dir,image_file_list[i]))

4       、将数据转成pytorch标准的DataLoader输入格式

1                     、先对数据集进行预处理       ,包括resize成224*224的尺寸              ,因为vgg_net模型需要的输入尺寸为[N, 224, 224, 3];随机翻转                     ,随机旋转等       ,另外对数据集做Normalize标准化       ,其中的mean=[0.485, 0.456, 0.406],std=[0.229, 0.224, 0.2]是从ImageNet数据集上的百万张图片中随机抽样计算得到的                     ,以上这些内容主要是数据增强              ,增强模型的泛化性       ,有更好的预测效果              。

2              、然后将预处理好的数据转成pytorch标准的DataLoader输入格式                     ,       。 # 数据预处理 transform = transforms.Compose([ transforms.RandomResizedCrop(224),# 对图像进行随机的crop以后再resize成固定大小 transforms.ToTensor(), transforms.Normalize(mean=[0.485, 0.456, 0.406],std=[0.229, 0.224, 0.2]), # ImageNet全部图片的平均值和标准差 transforms.RandomRotation(20), # 随机旋转角度 transforms.RandomHorizontalFlip(p=0.5), # 随机水平翻转 ]) # 读取数据 root = source_path train_dataset = datasets.ImageFolder(root + /train, transform) test_dataset = datasets.ImageFolder(root + /test, transform) # 导入数据 train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=16, shuffle=True) test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=16, shuffle=False)

5       、导入预训练模型              ,并修改分类层

1                     、定义device,如果有GPU模型训练会自动用GPU训练                     ,否则会使用CPU;使用GPU训练                     ,只需在模型              、数据、损失函数上使用cuda()就行                     。

2                     、这边默认对分类图像算法都熟悉,可以自己构建vgg16的完整网络              ,在猫狗数据集上重新训练              。也可以下载预训练模型                     ,由于原网络的分类输出是1000类别的       ,但是我们的图片只有两类              ,所以需要修改分类层                     ,让模型能够适配我们的训练数据集。 device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") vgg16 = torchvision.models.vgg16(pretrained=True).to(device) print(vgg16) inputs = torch.rand(1, 3, 224, 224) # 拿一个随机tensor测试一下网络的输出是否满足预期 output = vgg16(inputs.to(device)) print("原始VGG网络的输出:",output.size()) # 构建新的全连接层 vgg16.classifier = torch.nn.Sequential(torch.nn.Linear(25088, 100), torch.nn.ReLU(), torch.nn.Dropout(p=0.5), torch.nn.Linear(100, 2)).to(device) inputs = torch.rand(1, 3, 224, 224) output = vgg16(inputs.to(device)) print("新构建的VGG网络的输出:",output.size())

6                     、开始模型训练

开始模型训练       ,我们这里只训练全连接分类层       ,将特征层的梯度requires_grad设置为False                     ,特征层的参数将不参与训练                     。

训练过程中保存效果最好的网络模型              ,以防掉线       ,可以从断点开始继续训练                     ,同时也可以用来做预测                     。

训练完成后              ,保存训练好的网络和参数,后面可以加载模型做预测。 writer = SummaryWriter("./logs/model") loss_func = nn.CrossEntropyLoss().to(device) learning_rate = 0.0001 #如果我们想只训练模型的全连接层 for param in vgg16.features.parameters(): param.requires_grad = False optimizer = torch.optim.Adam(vgg16.parameters(),lr=learning_rate) ## 断点续训开始 resume = False if resume: # 恢复上次的训练状态 print("Resume from checkpoint...") checkpoint = torch.load("./models/checkpoint/ckpt_best.pth") vgg16.load_state_dict(checkpoint[net]) optimizer.load_state_dict(checkpoint[optimizer]) epoch_ = checkpoint[epoch] + 1 #从上次记录的损失和正确率接着记录 loss = checkpoint[loss] total_test_loss = checkpoint["total_test_loss"] total_acc = checkpoint["total_acc"] else: total_acc = 0.0 epoch_ = 0 ##训练开始 total_train_step = 0 total_test_step = 0 min_acc = 0.0 for epoch in range(epoch_ , 10): print("-----------train epoch {} start---------------".format(epoch)) vgg16.train() for data in train_loader: optimizer.zero_grad() img, label = data output = vgg16(img.to(device)) loss = loss_func(output, label.to(device)) loss.backward() optimizer.step() total_train_step += 1 if total_train_step % 10 == 0: print("steps: {}, train_loss: {}".format(total_train_step, loss.item())) writer.add_scalar("train_loss", loss.item(), total_train_step) ## 测试开始                     ,看训练效果是否满足预期 total_test_loss = 0 vgg16.eval() with torch.no_grad(): for data in test_loader: optimizer.zero_grad() img, label = data output = vgg16(img.to(device)) loss = loss_func(output, label.to(device)) total_test_loss += loss accuary = torch.sum(output.argmax(1) == label.to(device)) total_acc += accuary total_test_step += 1 val_acc = total_acc.item() / len(test_dataset) total_acc = 0.0 ## 保存Acc最小的模型 if val_acc > min_acc: min_acc = val_acc torch.save(vgg16.state_dict(), "./models/2classes_vgg16_weight.pth") print("测试Acc: {} \n 模型保存成功!".format(min_acc)) # 保存模型和训练参数的全相关信息                     ,方便断点续训 checkpoint = { "net": vgg16.state_dict(), optimizer:optimizer.state_dict(), "loss": loss, "epoch": epoch, "total_test_loss": total_test_loss, "total_acc": total_acc } if not os.path.exists("./models/checkpoint"): os.mkdir("./models/checkpoint") torch.save(checkpoint, ./models/checkpoint/ckpt_best.pth) print("测试loss: {}".format(total_test_loss.item())) print("测试Acc: {}".format(val_acc)) writer.add_scalar("test_loss", total_test_loss.item(), total_test_step) writer.add_scalar("test_Acc", val_acc, total_test_step) torch.save(vgg16.state_dict(), "./models/2classes_vgg16_latest_{}.pth".format(val_acc))

7、利用训好的模型做预测

拿出一张图片做预测,首先导入预训练模型              ,同样改掉分类层                     ,然后导入预训练权重       ,预测图片类别              ,输出标签值和预测类别              。

import matplotlib.pyplot as plt img_path = r"./kagglecatsanddogs_5340/PetImages/test/Cat/1381.jpg" # 拿出要预测的图片 image = Image.open(img_path).convert("RGB") image.show() vgg16_pred = torchvision.models.vgg16(pretrained=True) vgg16_pred.classifier = torch.nn.Sequential(torch.nn.Linear(25088, 100), torch.nn.ReLU(), torch.nn.Dropout(p=0.5), torch.nn.Linear(100, 2)) transform = torchvision.transforms.Compose([ torchvision.transforms.Resize((224,224), interpolation=2), torchvision.transforms.ToTensor() ]) vgg16_pred.load_state_dict(torch.load("./models/2classes_vgg16_weight_15_0.9467513434294089.pth", map_location=torch.device(cpu))) print(vgg16_pred) image = transform(image) print(image.size()) image = torch.reshape(image, [1,3,224,224]) vgg16_pred.eval() with torch.no_grad(): output = vgg16_pred(image) # print("预测值为:",output) print("预测标签为:",output.argmax(1).item()) print("预测动物为:",train_dataset.classes[output.argmax(1)])
声明:本站所有文章                     ,如无特殊说明或标注       ,均为本站原创发布                     。任何个人或组织       ,在未征得本站同意时                     ,禁止复制              、盗用                     、采集       、发布本站内容到任何网站              、书籍等各类媒体平台       。如若本站内容侵犯了原著者的合法权益              ,可联系我们进行处理              。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
淘宝买二手主板(淘宝二手主机的坑在哪里,怎么避免?) 陆丰新闻网(陆丰在线网下载)