Pytorch从零开始实战05

Pytorch从零开始实战——运动鞋识别

本系列来源于365天深度学习训练营

原作者K同学

文章目录

  • Pytorch从零开始实战——运动鞋识别
    • 环境准备
    • 数据集
    • 模型选择
    • 数据可视化
    • 模型预测
    • 总结

环境准备

本文基于Jupyter notebook,使用Python3.8,Pytorch2.0.1+cu118,torchvision0.15.2,需读者自行配置好环境且有一些深度学习理论基础。本次实验的目的是了解如何设置动态学习率。
第一步,导入常用包。

import torch
import torch.nn as nn
import matplotlib.pyplot as plt
import torchvision
import torchvision.transforms as transforms
import torchvision.datasets as datasets
import torch.nn.functional as F
import random
from time import time
import numpy as np
import pandas as pd
import datetime
import gc
import os
os.environ['KMP_DUPLICATE_LIB_OK']='True'  # 用于避免jupyter环境突然关闭
torch.backends.cudnn.benchmark=True  # 用于加速GPU运算的代码

设置随机数种子,428不好用,这次设置为55

torch.manual_seed(55)
torch.cuda.manual_seed(55)
torch.cuda.manual_seed_all(55)
random.seed(55)
np.random.seed(55)

创建设备对象,检测设备

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
device

数据集

本次实验是对运动鞋图片进行分类任务,共579张图片,是一个二分类任务,标签为adidas、nike,两种类别的图片分别存放在不同的文件夹中。

展示图片函数

def plotsample(data):fig, axs = plt.subplots(1, 5, figsize=(10, 10)) #建立子图for i in range(5):num = random.randint(0, len(data) - 1) #首先选取随机数,随机选取五次#抽取数据中对应的图像对象,make_grid函数可将任意格式的图像的通道数升为3,而不改变图像原始的数据#而展示图像用的imshow函数最常见的输入格式也是3通道npimg = torchvision.utils.make_grid(data[num][0]).numpy()nplabel = data[num][1] #提取标签 #将图像由(3, weight, height)转化为(weight, height, 3),并放入imshow函数中读取axs[i].imshow(np.transpose(npimg, (1, 2, 0))) axs[i].set_title(nplabel) #给每个子图加上标签axs[i].axis("off") #消除每个子图的坐标轴

查看classNames

import pathlib
data_dir = './data/snk/train'
data_dir = pathlib.Path(data_dir) # 转成pathlib.Path对象data_paths = list(data_dir.glob('*')) # [PosixPath('data/snk/train/adidas'), PosixPath('data/snk/train/nike')]
classNames = [str(path).split("/")[3] for path in data_paths]
classNames # 二分类问题 ['adidas', 'nike']

使用transforms来预处理原始数据,统一尺寸、转换为张量、标准化

train_transforms = transforms.Compose([transforms.Resize([224, 224]),transforms.ToTensor(),transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) # 标准化
])test_transforms = transforms.Compose([transforms.Resize([224, 224]),transforms.ToTensor(),transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) # 标准化
])# 根据文件名设置标签
train_dataset = datasets.ImageFolder("./data/snk/train/", transform=train_transforms)
test_dataset = datasets.ImageFolder("./data/snk/test/", transform=train_transforms)

随机查看5张图片

plotsample(train_dataset)

在这里插入图片描述
使用DataLoader划分数据集,batch_size = 32

batch_size = 32
train_dl = torch.utils.data.DataLoader(train_dataset,batch_size=batch_size,shuffle=True,)
test_dl = torch.utils.data.DataLoader(test_dataset,batch_size=batch_size,shuffle=True,)len(train_dl.dataset), len(test_dl.dataset) # 503 76

模型选择

本次还是选择简单的卷积神经网络,这次写法使用Sequential,表示这一块是一个单独的模块。

class Model(nn.Module):def __init__(self):super().__init__()self.conv1 = nn.Sequential(nn.Conv2d(3, 12, kernel_size=5), # 220nn.BatchNorm2d(12),nn.ReLU())self.conv2 = nn.Sequential(nn.Conv2d(12, 12, kernel_size=5), # 216nn.BatchNorm2d(12),nn.ReLU())self.pool3 = nn.Sequential(nn.MaxPool2d(2)             # 108)self.conv4 = nn.Sequential(nn.Conv2d(12, 24, kernel_size=5),  # 104nn.BatchNorm2d(24),nn.ReLU())self.conv5 = nn.Sequential(nn.Conv2d(24, 24, kernel_size=5),  # 100nn.BatchNorm2d(24),nn.ReLU())self.pool6 = nn.Sequential(nn.MaxPool2d(2))self.dropout = nn.Sequential(nn.Dropout(0.2))self.fc = nn.Sequential(nn.Linear(50 * 50 * 24, len(classNames)))def forward(self, x):x = self.conv1(x)x = self.conv2(x)x = self.pool3(x)x = self.conv4(x)x = self.conv5(x)x = self.pool6(x)x = self.dropout(x)x = x.view(-1, 50 * 50 * 24)x = self.fc(x)return x

模型初始化

from torchsummary import summary
# 将模型转移到GPU中
model = Model().to(device)
summary(model, input_size=(3, 224, 224))

在这里插入图片描述
定义训练函数

def train(dataloader, model, loss_fn, opt):size = len(dataloader.dataset)num_batches = len(dataloader)train_acc, train_loss = 0, 0for X, y in dataloader:X, y = X.to(device), y.to(device)pred = model(X)loss = loss_fn(pred, y)opt.zero_grad()loss.backward()opt.step()train_acc += (pred.argmax(1) == y).type(torch.float).sum().item()train_loss += loss.item()train_acc /= sizetrain_loss /= num_batchesreturn train_acc, train_loss

定义测试函数

def test(dataloader, model, loss_fn):size = len(dataloader.dataset)num_batches = len(dataloader)test_acc, test_loss = 0, 0with torch.no_grad():for X, y in dataloader:X, y = X.to(device), y.to(device)pred = model(X)loss = loss_fn(pred, y)test_acc += (pred.argmax(1) == y).type(torch.float).sum().item()test_loss += loss.item()test_acc /= sizetest_loss /= num_batchesreturn test_acc, test_loss

定义一些超参数

loss_fn = nn.CrossEntropyLoss()
learn_rate = 0.0001
opt = torch.optim.SGD(model.parameters(), lr=learn_rate)

定义学习率衰减函数,大概意思是随着epoch的增加,学习率会持续变小,使得模型更容易收敛

def adjust_rate(opt, epoch, start_lr):lr = start_lr * (0.92 ** (epoch // 2))for param_group in opt.param_groups:param_group['lr'] = lr

开始训练

import time
epochs = 30
train_loss = []
train_acc = []
test_loss = []
test_acc = []T1 = time.time()best_acc = 0
PATH = './my_model.pth'for epoch in range(epochs):adjust_rate(opt, epoch, learn_rate)model.train()epoch_train_acc, epoch_train_loss = train(train_dl, model, loss_fn, opt)model.eval() # 确保模型不会进行训练操作epoch_test_acc, epoch_test_loss = test(test_dl, model, loss_fn)if epoch_test_acc > best_acc:best_acc = epoch_test_acctorch.save(model.state_dict(), PATH)print("model save")train_acc.append(epoch_train_acc)train_loss.append(epoch_train_loss)test_acc.append(epoch_test_acc)test_loss.append(epoch_test_loss)print("epoch:%d, train_acc:%.1f%%, train_loss:%.3f, test_acc:%.1f%%, test_loss:%.3f"% (epoch + 1, epoch_train_acc * 100, epoch_train_loss, epoch_test_acc * 100, epoch_test_loss))
print("Done")
T2 = time.time()
print('程序运行时间:%s毫秒' % ((T2 - T1)*1000))

但是效果好像不是很好,模型训练的时候卡在某个极小值不动了
在这里插入图片描述
经过实验,将学习率改为0.001,效果是最好的。

import time
epochs = 30
train_loss = []
train_acc = []
test_loss = []
test_acc = []T1 = time.time()best_acc = 0
PATH = './my_model.pth'for epoch in range(epochs):model.train()epoch_train_acc, epoch_train_loss = train(train_dl, model, loss_fn, opt)model.eval() # 确保模型不会进行训练操作epoch_test_acc, epoch_test_loss = test(test_dl, model, loss_fn)if epoch_test_acc > best_acc:best_acc = epoch_test_acctorch.save(model.state_dict(), PATH)print("model save")train_acc.append(epoch_train_acc)train_loss.append(epoch_train_loss)test_acc.append(epoch_test_acc)test_loss.append(epoch_test_loss)print("epoch:%d, train_acc:%.1f%%, train_loss:%.3f, test_acc:%.1f%%, test_loss:%.3f"% (epoch + 1, epoch_train_acc * 100, epoch_train_loss, epoch_test_acc * 100, epoch_test_loss))
print("Done")
T2 = time.time()
print('程序运行时间:%s毫秒' % ((T2 - T1)*1000))

在训练集上已经达到百分百准确率了,在测试集上的表现也很好。
在这里插入图片描述

数据可视化

import warnings
warnings.filterwarnings("ignore")               #忽略警告信息
plt.rcParams['font.sans-serif']    = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False      # 用来正常显示负号
plt.rcParams['figure.dpi']         = 100        #分辨率epochs_range = range(epochs)plt.figure(figsize=(12, 3))
plt.subplot(1, 2, 1)plt.plot(epochs_range, train_acc, label='Training Accuracy')
plt.plot(epochs_range, test_acc, label='Test Accuracy')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')plt.subplot(1, 2, 2)
plt.plot(epochs_range, train_loss, label='Training Loss')
plt.plot(epochs_range, test_loss, label='Test Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')
plt.show()

在这里插入图片描述

模型预测

from PIL import Image classes = list(train_dataset.class_to_idx)def predict_one_image(image_path, model, transform, classes):test_img = Image.open(image_path).convert('RGB')plt.imshow(test_img)  # 展示预测的图片test_img = transform(test_img)img = test_img.to(device).unsqueeze(0) # 增加维度model.eval()output = model(img)_,pred = torch.max(output,1)pred_class = classes[pred]print(f'预测结果是:{pred_class}')

使用2.jpg开始预测

predict_one_image(image_path='./data/snk/test/adidas/2.jpg', model=model, transform=train_transforms, classes=classes)

预测结果是:adidas

在这里插入图片描述

总结

学习率衰减是一个很有用的东西,但有的时候,使用学习率衰减好像还不如不使用学习率衰减,感觉容易提前收敛。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/138986.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

点击切换播放图片

<template><!-- banner组件 --><div class"wrap-box"><div class"image-container"><img :src"currentImage" alt"Image"></div><div class"controls"><div class"btn&q…

元宇宙虚拟展览馆,感受虚拟世界不一样的展览体验

引言&#xff1a; 随着科技的迅猛发展&#xff0c;元宇宙概念逐渐进入了大众的视野。不同于传统展览馆&#xff0c;元宇宙虚拟展览馆为人们提供了一个虚拟的展示空间&#xff0c;打破了时空的限制。 一、什么是元宇宙虚拟展览馆&#xff1f; 元宇宙虚拟展览馆是一种结合了虚拟…

【学习笔记】RabbitMQ02:交换机,以及结合springboot快速开始

参考资料 RabbitMQ官方网站RabbitMQ官方文档噼咔噼咔-动力节点教程 文章目录 四、RabbitMQ &#xff1a;Exchange 交换机4.1 交换机类型4.2 扇形交换机 Fanout Exchange4.2.1 概念4.2.1 实例&#xff1a;生产者4.2.1.1 添加起步依赖4.2.1.2 配置文件4.2.1.3 JavaBean进行配置4.…

A股风格因子看板 (2023.10 第05期)

该因子看板跟踪A股风格因子&#xff0c;该因子主要解释沪深两市的市场收益、刻画市场风格趋势的系列风格因子&#xff0c;用以分析市场风格切换、组合风格暴露等。 今日为该因子跟踪第05期&#xff0c;指数组合数据截止日2023-09-30&#xff0c;要点如下 近1年A股风格因子检验统…

小程序框架

目录 一.什么是小程序框架 二.视图层 先建立四个包 数据绑定 条件渲染 ​编辑 使用模板 事件系统 所有a.js 输出结果 ​编辑 三.跳转 a页面跳b页面 ​编辑 a页面跳c页面 测试结果 四.生命周期 一级跳一级 一级跳二级 二级跳二级 页面隔代跳转 一.什么是小程…

钢铁异常分类140篇Trans 学习笔记 小陈读paper

钢铁异常分类 对比学习 比较好用 1.首先&#xff0c;为每个实例生成一对样本&#xff0c; 来自同一实例的样本被认为是正例&#xff0c; 来自不同实例的样本被认为是负例。 2.其次&#xff0c;这些样本被馈送到编码器以获得嵌入。 3.在对比损失[16]的影响下&#xff0c; …

机器人命令表设计

演算命令 CLEAR 将数据 1 上被指定的编号以后的变数的内容&#xff0c;以及数据 2 上仅被指定的个数都清除至 0。 INC 在被指定的变数内容上加上 1。 DEC 在被指定的变数内容上减掉 1。 SET 在数据 1 上设定数据 2。 ADD 将数据 1 和数据 2 相加&#xff0c;得出的结果保存在数…

基于springboot实现汉服文化分享平台项目【项目源码+论文说明】计算机毕业设计

摘要 本论文主要论述了如何使用JAVA语言开发一个汉服文化平台网站 &#xff0c;本系统将严格按照软件开发流程进行各个阶段的工作&#xff0c;采用B/S架构&#xff0c;面向对象编程思想进行项目开发。在引言中&#xff0c;作者将论述汉服文化平台网站的当前背景以及系统开发的…

WPF 用户控件依赖注入赋值

前言 我一直想组件化得去开发WPF&#xff0c;因为我觉得将复杂问题简单化是最好的 如何组件化开发 主窗口引用 <Window x:Class"WpfApp1.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.…

机器学习算法 —— 1. K近邻算法

K近邻算法 1. K近邻算法简介2. K近邻算法常见距离度量2.1 欧氏距离&#xff08;Euclidean Distance&#xff09;2.2 曼哈顿距离&#xff08;Manhattan Distance &#xff09;2.3 切比雪夫距离&#xff08;Chebyshev Distance&#xff09;2.4 闵可夫斯基距离&#xff08;Minkows…

宏电股份RedCap产品亮相迪拜华为MBBF,并参与RedCap全球商用阶段性成果发布

10月10-11日&#xff0c;由华为主办的第十四届全球移动宽带论坛&#xff08;MBBF&#xff09;在阿联酋迪拜成功举办。MBBF期间&#xff0c;华为联合宏电股份等产业伙伴集中发布RedCap商用阶段性成果。本次发布是RedCap产业的关键里程碑&#xff0c;标志着RedCap在全球已具备规模…

【马蹄集】—— 概率论专题

概率论专题 目录 MT2226 抽奖概率MT2227 饿饿&#xff01;饭饭&#xff01;MT2228 甜甜花的研究MT2229 赌石MT2230 square MT2226 抽奖概率 难度&#xff1a;黄金    时间限制&#xff1a;1秒    占用内存&#xff1a;128M 题目描述 小码哥正在进行抽奖&#xff0c;箱子里有…