[深度应用]·实战掌握PyTorch图片分类简明教程
[深度应用]·实战掌握PyTorch图片分类简明教程
个人网站--> http://www.yansongsong.cn/
项目GitHub地址--> https://github.com/xiaosongshine/image_classifier_PyTorch/
1.引文
深度学习的比赛中,图片分类是很常见的比赛,同时也是很难取得特别高名次的比赛,因为图片分类已经被大家研究的很透彻,一些开源的网络很容易取得高分。如果大家还掌握不了使用开源的网络进行训练,再慢慢去模型调优,很难取得较好的成绩。
我们在[PyTorch小试牛刀]实战六·准备自己的数据集用于训练讲解了如何制作自己的数据集用于训练,这个教程在此基础上,进行训练与应用。
2.数据介绍
数据 下载地址
这次的实战使用的数据是交通标志数据集,共有62类交通标志。其中训练集数据有4572张照片(每个类别大概七十个),测试数据集有2520张照片(每个类别大概40个)。数据包含两个子目录分别train与test:
为什么还需要测试数据集呢?这个测试数据集不会拿来训练,是用来进行模型的评估与调优。

train与test每个文件夹里又有62个子文件夹,每个类别在同一个文件夹内:

我从中打开一个文件间,把里面图片展示出来:

其中每张照片都类似下面的例子,100*100*3的大小。100是照片的照片的长和宽,3是什么呢?这其实是照片的色彩通道数目,RGB。彩色照片存储在计算机里就是以三维数组的形式。我们送入网络的也是这些数组。
3.网络构建
1.导入Python包,定义一些参数
import torch as t
import torchvision as tv
import os
import time
import numpy as np
from tqdm import tqdm class DefaultConfigs(object): data_dir = "./traffic-sign/"
data_list = ["train","test"] lr = 0.001
epochs = 10
num_classes = 62
image_size = 224
batch_size = 40
channels = 3
gpu = "0"
train_len = 4572
test_len = 2520
use_gpu = t.cuda.is_available() config = DefaultConfigs()
2.数据准备,采用PyTorch提供的读取方式(具体内容参考[PyTorch小试牛刀]实战六·准备自己的数据集用于训练)
注意一点Train数据需要进行随机裁剪,Test数据不要进行裁剪了
normalize = tv.transforms.Normalize(mean = [0.485, 0.456, 0.406],
std = [0.229, 0.224, 0.225]
) transform = {
config.data_list[0]:tv.transforms.Compose(
[tv.transforms.Resize([224,224]),tv.transforms.CenterCrop([224,224]),
tv.transforms.ToTensor(),normalize]#tv.transforms.Resize 用于重设图片大小
) ,
config.data_list[1]:tv.transforms.Compose(
[tv.transforms.Resize([224,224]),tv.transforms.ToTensor(),normalize]
)
} datasets = {
x:tv.datasets.ImageFolder(root = os.path.join(config.data_dir,x),transform=transform[x])
for x in config.data_list
} dataloader = {
x:t.utils.data.DataLoader(dataset= datasets[x],
batch_size=config.batch_size,
shuffle=True
)
for x in config.data_list
}
3.构建网络模型(使用resnet18进行迁移学习,训练参数为最后一个全连接层 t.nn.Linear(512,num_classes))
def get_model(num_classes):
model = tv.models.resnet18(pretrained=True)
for parma in model.parameters():
parma.requires_grad = False
model.fc = t.nn.Sequential(
t.nn.Dropout(p=0.3),
t.nn.Linear(512,num_classes)
)
return(model)
如果电脑硬件支持,可以把下述代码屏蔽,则训练整个网络,最终准确率会上升,训练数据会变慢。
for parma in model.parameters():
parma.requires_grad = False
模型输出
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)
(maxpool): MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1, ceil_mode=False)
(layer1): Sequential(
(0): BasicBlock(
(conv1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(relu): ReLU(inplace)
(conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
)
(1): BasicBlock(
(conv1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(relu): ReLU(inplace)
(conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
)
)
(layer2): Sequential(
(0): BasicBlock(
(conv1): Conv2d(64, 128, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
(bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(relu): ReLU(inplace)
(conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(downsample): Sequential(
(0): Conv2d(64, 128, kernel_size=(1, 1), stride=(2, 2), bias=False)
(1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
)
)
(1): BasicBlock(
(conv1): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(relu): ReLU(inplace)
(conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
)
)
(layer3): Sequential(
(0): BasicBlock(
(conv1): Conv2d(128, 256, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
(bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(relu): ReLU(inplace)
(conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(downsample): Sequential(
(0): Conv2d(128, 256, kernel_size=(1, 1), stride=(2, 2), bias=False)
(1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
)
)
(1): BasicBlock(
(conv1): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(relu): ReLU(inplace)
(conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
)
)
(layer4): Sequential(
(0): BasicBlock(
(conv1): Conv2d(256, 512, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
(bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(relu): ReLU(inplace)
(conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(downsample): Sequential(
(0): Conv2d(256, 512, kernel_size=(1, 1), stride=(2, 2), bias=False)
(1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
)
)
(1): BasicBlock(
(conv1): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(relu): ReLU(inplace)
(conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
)
)
(avgpool): AvgPool2d(kernel_size=7, stride=1, padding=0)
(fc): Sequential(
(0): Dropout(p=0.3)
(1): Linear(in_features=512, out_features=62, bias=True)
)
)
4.训练模型(支持自动GPU加速,GPU使用教程参考:[开发技巧]·PyTorch如何使用GPU加速)
def train(epochs):
model = get_model(config.num_classes)
print(model)
loss_f = t.nn.CrossEntropyLoss()
if(config.use_gpu):
model = model.cuda()
loss_f = loss_f.cuda()
opt = t.optim.Adam(model.fc.parameters(),lr = config.lr)
time_start = time.time()
for epoch in range(epochs):
train_loss = []
train_acc = []
test_loss = []
test_acc = []
model.train(True)
print("Epoch {}/{}".format(epoch+1,epochs))
for batch, datas in tqdm(enumerate(iter(dataloader["train"]))):
x,y = datas
if (config.use_gpu):
x,y = x.cuda(),y.cuda()
y_ = model(x)
#print(x.shape,y.shape,y_.shape)
_, pre_y_ = t.max(y_,1)
pre_y = y
#print(y_.shape)
loss = loss_f(y_,pre_y)
#print(y_.shape)
acc = t.sum(pre_y_ == pre_y)
loss.backward()
opt.step()
opt.zero_grad()
if(config.use_gpu):
loss = loss.cpu()
acc = acc.cpu()
train_loss.append(loss.data)
train_acc.append(acc)
#if((batch+1)%5 ==0):
time_end = time.time()
print("Batch {}, Train loss:{:.4f}, Train acc:{:.4f}, Time: {}"\
.format(batch+1,np.mean(train_loss)/config.batch_size,np.mean(train_acc)/config.batch_size,(time_end-time_start)))
time_start = time.time()
model.train(False)
for batch, datas in tqdm(enumerate(iter(dataloader["test"]))):
x,y = datas
if (config.use_gpu):
x,y = x.cuda(),y.cuda()
y_ = model(x)
#print(x.shape,y.shape,y_.shape)
_, pre_y_ = t.max(y_,1)
pre_y = y
#print(y_.shape)
loss = loss_f(y_,pre_y)
acc = t.sum(pre_y_ == pre_y)
if(config.use_gpu):
loss = loss.cpu()
acc = acc.cpu()
test_loss.append(loss.data)
test_acc.append(acc)
print("Batch {}, Test loss:{:.4f}, Test acc:{:.4f}".format(batch+1,np.mean(test_loss)/config.batch_size,np.mean(test_acc)/config.batch_size))
t.save(model,str(epoch+1)+"ttmodel.pkl")
if __name__ == "__main__":
train(config.epochs)
训练结果如下:
def train(epochs):
model = get_model(config.num_classes)
print(model)
loss_f = t.nn.CrossEntropyLoss()
if(config.use_gpu):
model = model.cuda()
loss_f = loss_f.cuda()
opt = t.optim.Adam(model.fc.parameters(),lr = config.lr)
time_start = time.time()
for epoch in range(epochs):
train_loss = []
train_acc = []
test_loss = []
test_acc = []
model.train(True)
print("Epoch {}/{}".format(epoch+1,epochs))
for batch, datas in tqdm(enumerate(iter(dataloader["train"]))):
x,y = datas
if (config.use_gpu):
x,y = x.cuda(),y.cuda()
y_ = model(x)
#print(x.shape,y.shape,y_.shape)
_, pre_y_ = t.max(y_,1)
pre_y = y
#print(y_.shape)
loss = loss_f(y_,pre_y)
#print(y_.shape)
acc = t.sum(pre_y_ == pre_y)
loss.backward()
opt.step()
opt.zero_grad()
if(config.use_gpu):
loss = loss.cpu()
acc = acc.cpu()
train_loss.append(loss.data)
train_acc.append(acc)
#if((batch+1)%5 ==0):
time_end = time.time()
print("Batch {}, Train loss:{:.4f}, Train acc:{:.4f}, Time: {}"\
.format(batch+1,np.mean(train_loss)/config.batch_size,np.mean(train_acc)/config.batch_size,(time_end-time_start)))
time_start = time.time()
model.train(False)
for batch, datas in tqdm(enumerate(iter(dataloader["test"]))):
x,y = datas
if (config.use_gpu):
x,y = x.cuda(),y.cuda()
y_ = model(x)
#print(x.shape,y.shape,y_.shape)
_, pre_y_ = t.max(y_,1)
pre_y = y
#print(y_.shape)
loss = loss_f(y_,pre_y)
acc = t.sum(pre_y_ == pre_y)
if(config.use_gpu):
loss = loss.cpu()
acc = acc.cpu()
test_loss.append(loss.data)
test_acc.append(acc)
print("Batch {}, Test loss:{:.4f}, Test acc:{:.4f}".format(batch+1,np.mean(test_loss)/config.batch_size,np.mean(test_acc)/config.batch_size))
t.save(model,str(epoch+1)+"ttmodel.pkl")
if __name__ == "__main__":
train(config.epochs)
训练10个Epoch,测试集准确率可以到达0.86,已经达到不错效果。通过修改参数,增加训练,可以达到更高的准确率。
[深度应用]·实战掌握PyTorch图片分类简明教程的更多相关文章
- [深度应用]·实战掌握Dlib人脸识别开发教程
[深度应用]·实战掌握Dlib人脸识别开发教程 个人网站--> http://www.yansongsong.cn/ 项目GitHub地址--> https://github.com/xi ...
- Go 语言图片处理简明教程
虽然 Go 语言主要用于 Web 后端以及各类中间件和基础设施开发,也难免遇到一些图像处理的需求.Go 语言提供的 image 标准库提供了基本的图片加载.裁剪.绘制等能力,可以帮助我们实现一些绘图需 ...
- 对比学习:《深度学习之Pytorch》《PyTorch深度学习实战》+代码
PyTorch是一个基于Python的深度学习平台,该平台简单易用上手快,从计算机视觉.自然语言处理再到强化学习,PyTorch的功能强大,支持PyTorch的工具包有用于自然语言处理的Allen N ...
- 深度学习之神经网络核心原理与算法-caffe&keras框架图片分类
之前我们在使用cnn做图片分类的时候使用了CIFAR-10数据集 其他框架对于CIFAR-10的图片分类是怎么做的 来与TensorFlow做对比. Caffe Keras 安装 官方安装文档: ht ...
- [深度应用]·Keras实现Self-Attention文本分类(机器如何读懂人心)
[深度应用]·Keras实现Self-Attention文本分类(机器如何读懂人心) 配合阅读: [深度概念]·Attention机制概念学习笔记 [TensorFlow深度学习深入]实战三·分别使用 ...
- TensorFlow 2.0 深度学习实战 —— 浅谈卷积神经网络 CNN
前言 上一章为大家介绍过深度学习的基础和多层感知机 MLP 的应用,本章开始将深入讲解卷积神经网络的实用场景.卷积神经网络 CNN(Convolutional Neural Networks,Conv ...
- TensorFlow深度学习实战---图像识别与卷积神经网络
全连接层网络结构:神经网络每两层之间的所有结点都是有边相连的. 卷积神经网络:1.输入层 2.卷积层:将神经网络中的每一个小块进行更加深入地分析从而得到抽象程度更高的特征. 3 池化层:可以认为将一张 ...
- 源码分析——迁移学习Inception V3网络重训练实现图片分类
1. 前言 近些年来,随着以卷积神经网络(CNN)为代表的深度学习在图像识别领域的突破,越来越多的图像识别算法不断涌现.在去年,我们初步成功尝试了图像识别在测试领域的应用:将网站样式错乱问题.无线领域 ...
- 深度学习实战篇-基于RNN的中文分词探索
深度学习实战篇-基于RNN的中文分词探索 近年来,深度学习在人工智能的多个领域取得了显著成绩.微软使用的152层深度神经网络在ImageNet的比赛上斩获多项第一,同时在图像识别中超过了人类的识别水平 ...
随机推荐
- guid.go
] = byte(g) hex.Encode(h[:], b[:]) return h }
- HTTP 常见状态码解析
1XX 表示消息 2XX 表示成功 3XX 表示重定向 4XX 表示请求错误 5XX 表示服务器端错误 消息:请求已被接受,需要继续处理.由于 HTTP/1.0 协议中没有定义任何 1xx 状态码. ...
- 「SDOI 2018」反回文串
题目大意: 求字符集大小为$k$长度为$n$的经循环移位后为回文串的数量. 题解: 这题是D1里最神的吧 考虑一个长度为$n$回文串,将其循环移位后所有的串都是满足要求的串. 但是显然这样计算会算重. ...
- BZOJ_2588_Spoj 10628. Count on a tree_树剖+主席树
BZOJ_2588_Spoj 10628. Count on a tree_树剖+主席树 题意: 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastan ...
- Hadoop2.41的HA的配置与启动
我配置HA机制创建了7台虚拟机 1.修改Linux主机名2.修改IP3.修改主机名和IP的映射关系 ######注意######如果你们公司是租用的服务器或是使用的云主机(如华为云主机.阿里云主机等) ...
- eShopOnContainers 知多少[6]:持久化事件日志
1. 引言 事件总线解决了微服务间如何基于集成事件进行异步通信的问题.然而只有事件总线正常运行,微服务之间基于事件的通信才得以运转. 而现实情况是,总有这样或那样的问题,导致事件总线不稳定或不可用,比 ...
- Failed to fetch URL http://dl-ssl.google.com/android/repository/addons_list-2.xml, reason:
http://blog.csdn.net/gyming/article/details/8168166/ 最近接受的这个项目需要Android SDK Tools revision 22.6.2 or ...
- 为什么range不是迭代器?range到底是什么类型?
迭代器是 23 种设计模式中最常用的一种(之一),在 Python 中随处可见它的身影,我们经常用到它,但是却不一定意识到它的存在.在关于迭代器的系列文章中(链接见文末),我至少提到了 23 种生成迭 ...
- CRM实施目标、需求、策略、厂商、流程等基本介绍全解
事实证明,有不少实施了CRM系统的企业经历了失败.这是为何?而据一个在线CRM论坛调查其失败的原因: 67%是因为缺乏组织和管理变革去适应CRM:如组织机构未调整.未融入企业文化.流程不清 ...
- Android 项目中用得最多最火的第三方框架可能都在这里了
分类 二级分类 框架名称 简介 Star 数 最近更新 UI 刷新 SmartRefreshLayout 智能下拉刷新框架 14k 18天 UI 刷新 Android-PullToRefresh 比较 ...