先说一个小知识,助于理解代码中各个层之间维度是怎么变换的。

卷积函数:一般只用来改变输入数据的维度,例如3维到16维。

Conv2d()

Conv2d(in_channels:int,out_channels:int,kernel_size:Union[int,tuple],stride=1,padding=o):
"""
:param in_channels: 输入的维度
:param out_channels: 通过卷积核之后,要输出的维度
:param kernel_size: 卷积核大小
:param stride: 移动步长
:param padding: 四周添多少个零
"""

一个小例子:

import torch
import torch.nn
# 定义一个16张照片,每个照片3个通道,大小是28*28
x= torch.randn(16,3,32,32)
# 改变照片的维度,从3维升到16维,卷积核大小是5
conv= torch.nn.Conv2d(3,16,kernel_size=5,stride=1,padding=0)
res=conv(x) print(res.shape)
# torch.Size([16, 16, 28, 28])
# 维度升到16维,因为卷积核大小是5,步长是1,所以照片的大小缩小了,变成28

卷积神经网络实战之ResNet18:

下面放一个ResNet18的一个示意图,

ResNet18主要是在层与层之间,加入了一个短接层,可以每隔k个层,进行一次短接。网络层的层数不是 越深就越好。

ResNet18就是,如果在原先的基础上再加上k层,如果有小优化,则保留,如果比原先结果还差,那就利用短接层,直接跳过。

ResNet18的构造如下:

ResNet18(
(conv1): Sequential(
(0): Conv2d(3, 64, kernel_size=(3, 3), stride=(3, 3))
(1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
)
(blk1): ResBlk(
(conv1): Conv2d(64, 128, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1))
(bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(extra): Sequential(
(0): Conv2d(64, 128, kernel_size=(1, 1), stride=(2, 2))
(1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
)
)
(blk2): ResBlk(
(conv1): Conv2d(128, 256, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1))
(bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(extra): Sequential(
(0): Conv2d(128, 256, kernel_size=(1, 1), stride=(2, 2))
(1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
)
)
(blk3): ResBlk(
(conv1): Conv2d(256, 512, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1))
(bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(extra): Sequential(
(0): Conv2d(256, 512, kernel_size=(1, 1), stride=(2, 2))
(1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
)
)
(blk4): ResBlk(
(conv1): Conv2d(512, 512, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1))
(bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(extra): Sequential()
)
(outlayer): Linear(in_features=512, out_features=10, bias=True)
)

程序运行前,先启动visdom,如果没有配置好visdom环境的,先百度安装好visdom环境

  • 1.使用快捷键win+r,在输入框输出cmd,然后在命令行窗口里输入python -m visdom.server,启动visdom

代码实战

定义一个名为resnet.py的文件,代码如下

import torch
from torch import nn
from torch.nn import functional as F # 定义两个卷积层 + 一个短接层
class ResBlk(nn.Module):
def __init__(self,ch_in,ch_out,stride=1):
super(ResBlk, self).__init__() # 两个卷积层
self.conv1=nn.Conv2d(ch_in,ch_out,kernel_size=3,stride=stride,padding=1)
self.bn1=nn.BatchNorm2d(ch_out)
self.conv2=nn.Conv2d(ch_out,ch_out,kernel_size=3,stride=1,padding=1)
self.bn2=nn.BatchNorm2d(ch_out) # 短接层
self.extra=nn.Sequential()
if ch_out != ch_in:
self.extra=nn.Sequential(
nn.Conv2d(ch_in,ch_out,kernel_size=1,stride=stride),
nn.BatchNorm2d(ch_out)
)
def forward(self,x):
"""
:param x: [b,ch,h,w]
:return:
"""
out=F.relu(self.bn1(self.conv1(x)))
out=self.bn2(self.conv2(out)) # 短接层
# element-wise add: [b,ch_in,h,w]=>[b,ch_out,h,w]
out=self.extra(x)+out
return out class ResNet18(nn.Module):
def __init__(self):
super(ResNet18, self).__init__() # 定义预处理层
self.conv1=nn.Sequential(
nn.Conv2d(3,64,kernel_size=3,stride=3,padding=0),
nn.BatchNorm2d(64)
) # 定义堆叠ResBlock层
# followed 4 blocks
# [b,64,h,w]-->[b,128,h,w]
self.blk1=ResBlk(64,128,stride=2)
# [b,128,h,w]-->[b,256,h,w]
self.blk2=ResBlk(128,256,stride=2)
# [b,256,h,w]-->[b,512,h,w]
self.blk3=ResBlk(256,512,stride=2)
# [b,512,h,w]-->[b,512,h,w]
self.blk4=ResBlk(512,512,stride=2) # 定义全连接层
self.outlayer=nn.Linear(512,10) def forward(self,x):
"""
:param x:
:return:
"""
# 1.预处理层
x=F.relu(self.conv1(x)) # 2. 堆叠ResBlock层:channel会慢慢的增加, 长和宽会慢慢的减少
# [b,64,h,w]-->[b,512,h,w]
x=self.blk1(x)
x=self.blk2(x)
x=self.blk3(x)
x=self.blk4(x) # print("after conv:",x.shape) # [b,512,2,2]
# 不管原先什么后面两个维度是多少,都化成[1,1],
# [b,512,1,1]
x=F.adaptive_avg_pool2d(x,[1,1])
# print("after pool2d:",x.shape) # [b,512,1,1] # 将[b,512,1,1]打平成[b,512*1*1]
x=x.view(x.size(0),-1) # 3.放到全连接层,进行打平
# [b,512]-->[b,10]
x=self.outlayer(x) return x
def main():
blk=ResBlk(64,128,stride=2)
temp=torch.randn(2,64,32,32)
out=blk(temp)
# print('block:',out.shape) x=torch.randn(2,3,32,32)
model=ResNet()
out=model(x)
# print("resnet:",out.shape) if __name__ == '__main__':
main()

定义一个名为main.py的文件,代码如下

import torch
from torchvision import datasets
from torchvision import transforms
from torch.utils.data import DataLoader
from torch import nn,optim
from visdom import Visdom
# from lenet5 import Lenet5
from resnet import ResNet18
import time def main():
batch_siz=32
cifar_train = datasets.CIFAR10('cifar',True,transform=transforms.Compose([
transforms.Resize((32,32)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225])
]),download=True)
cifar_train=DataLoader(cifar_train,batch_size=batch_siz,shuffle=True) cifar_test = datasets.CIFAR10('cifar',False,transform=transforms.Compose([
transforms.Resize((32,32)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225])
]),download=True)
cifar_test=DataLoader(cifar_test,batch_size=batch_siz,shuffle=True) x,label = iter(cifar_train).next()
print('x:',x.shape,'label:',label.shape) # 指定运行到cpu //GPU
device=torch.device('cpu')
# model = Lenet5().to(device)
model = ResNet18().to(device) # 调用损失函数use Cross Entropy loss交叉熵
# 分类问题使用CrossEntropyLoss比MSELoss更合适
criteon = nn.CrossEntropyLoss().to(device)
# 定义一个优化器
optimizer=optim.Adam(model.parameters(),lr=1e-3)
print(model) viz=Visdom()
viz.line([0.],[0.],win="loss",opts=dict(title='Lenet5 Loss'))
viz.line([0.],[0.],win="acc",opts=dict(title='Lenet5 Acc')) # 训练train
for epoch in range(1000):
# 变成train模式
model.train()
# barchidx:下标,x:[b,3,32,32],label:[b]
str_time=time.time()
for barchidx,(x,label) in enumerate(cifar_train):
# 将x,label放在gpu上
x,label=x.to(device),label.to(device)
# logits:[b,10]
# label:[b]
logits = model(x)
loss = criteon(logits,label) # viz.line([loss.item()],[barchidx],win='loss',update='append')
# backprop
optimizer.zero_grad()
loss.backward()
optimizer.step()
# print(barchidx)
end_time=time.time()
print('第 {} 次训练用时: {}'.format(epoch,(end_time-str_time)))
viz.line([loss.item()],[epoch],win='loss',update='append')
print(epoch,'loss:',loss.item()) # 变成测试模式
model.eval()
with torch.no_grad():
# 测试test
# 正确的数目
total_correct=0
total_num=0
for x,label in cifar_test:
# 将x,label放在gpu上
x,label=x.to(device),label.to(device)
# [b,10]
logits=model(x)
# [b]
pred=logits.argmax(dim=1)
# [b] = [b'] 统计相等个数
total_correct+=pred.eq(label).float().sum().item()
total_num+=x.size(0)
acc=total_correct/total_num
print(epoch,'acc:',acc)
print("------------------------------") viz.line([acc],[epoch],win='acc',update='append')
# viz.images(x.view(-1, 3, 32, 32), win='x') if __name__ == '__main__':
main()

测试结果

ResNet跑起来太费劲了,需要用GPU跑,但是我的电脑不支持GPU,头都大了,用cpu跑二十多分钟学习一次,头都大了。

Pytorch-卷积神经网络CNN之ResNet的Pytorch代码实现的更多相关文章

  1. 写给程序员的机器学习入门 (八) - 卷积神经网络 (CNN) - 图片分类和验证码识别

    这一篇将会介绍卷积神经网络 (CNN),CNN 模型非常适合用来进行图片相关的学习,例如图片分类和验证码识别,也可以配合其他模型实现 OCR. 使用 Python 处理图片 在具体介绍 CNN 之前, ...

  2. 深度学习之卷积神经网络CNN

    转自:https://blog.csdn.net/cxmscb/article/details/71023576 一.CNN的引入 在人工的全连接神经网络中,每相邻两层之间的每个神经元之间都是有边相连 ...

  3. 深度学习之卷积神经网络CNN及tensorflow代码实例

    深度学习之卷积神经网络CNN及tensorflow代码实例 什么是卷积? 卷积的定义 从数学上讲,卷积就是一种运算,是我们学习高等数学之后,新接触的一种运算,因为涉及到积分.级数,所以看起来觉得很复杂 ...

  4. 深度学习之卷积神经网络CNN及tensorflow代码实现示例

    深度学习之卷积神经网络CNN及tensorflow代码实现示例 2017年05月01日 13:28:21 cxmscb 阅读数 151413更多 分类专栏: 机器学习 深度学习 机器学习   版权声明 ...

  5. paper 162:卷积神经网络(CNN)解析

    卷积神经网络(CNN)解析: 卷积神经网络CNN解析 概揽 Layers used to build ConvNets 卷积层Convolutional layer 池化层Pooling Layer ...

  6. TensorFlow 2.0 深度学习实战 —— 浅谈卷积神经网络 CNN

    前言 上一章为大家介绍过深度学习的基础和多层感知机 MLP 的应用,本章开始将深入讲解卷积神经网络的实用场景.卷积神经网络 CNN(Convolutional Neural Networks,Conv ...

  7. 卷积神经网络(CNN)前向传播算法

    在卷积神经网络(CNN)模型结构中,我们对CNN的模型结构做了总结,这里我们就在CNN的模型基础上,看看CNN的前向传播算法是什么样子的.重点会和传统的DNN比较讨论. 1. 回顾CNN的结构 在上一 ...

  8. 卷积神经网络(CNN)反向传播算法

    在卷积神经网络(CNN)前向传播算法中,我们对CNN的前向传播算法做了总结,基于CNN前向传播算法的基础,我们下面就对CNN的反向传播算法做一个总结.在阅读本文前,建议先研究DNN的反向传播算法:深度 ...

  9. 卷积神经网络CNN总结

    从神经网络到卷积神经网络(CNN)我们知道神经网络的结构是这样的: 那卷积神经网络跟它是什么关系呢?其实卷积神经网络依旧是层级网络,只是层的功能和形式做了变化,可以说是传统神经网络的一个改进.比如下图 ...

  10. 【深度学习系列】手写数字识别卷积神经--卷积神经网络CNN原理详解(一)

    上篇文章我们给出了用paddlepaddle来做手写数字识别的示例,并对网络结构进行到了调整,提高了识别的精度.有的同学表示不是很理解原理,为什么传统的机器学习算法,简单的神经网络(如多层感知机)都可 ...

随机推荐

  1. Codeforces Round 303 (Div. 2)C. Kefa and Park(DFS、实现)

    @ 目录 题面 链接 题意 题解 代码 总结 题面 链接 C. Kefa and Park 题意 求叶节点数量,叶节点满足,从根节点到叶节点的路径上最长连续1的长度小于m 题解 这道题目主要是实现,当 ...

  2. MySQL汇总数和分组数据

    1.使用SQL语句对数据库表中的数据进行简单的汇总和分组,这里要注意 count(*) 是对表中的所有数据目进行计数,不管表列中包含的是空值还是非空值. 而使用count(column)是对特定的列中 ...

  3. docker部署监控Prometheus+Grafana

    目录 一.Prometheus简介 二.Prometheus基本原理 三.Prometheus架构图 四.Prometheus特性 五.Prometheus组件 六.Prometheus服务发现 七. ...

  4. 内部UI自动化测试培训之python基础

    这个文档的由来是公司内部UI自动化测试培训的资料.部门为了减少测试工作量,准备做UI自动化测试.我写python,其他同事都是java,所以python基础和UI自动化测试selenium的培训就由我 ...

  5. Abp.Zero 手机号免密登录验证与号码绑定功能的实现(二):改造Abp默认实现

    接下来我们重写原Abp的部分实现,来驳接手机号相关业务. 改造User类 重写PhoneNumber使得电话号码为必填项,和中国大陆手机号11位长度 public new const int MaxP ...

  6. 重新定义 vscode 命令行工具 code命令 code $profile

    vscode 默认命令行有问题 他那个每次都打开cli.js 目录名里面有空格 要 &开头后面跟双引号 所以从新定义后 变量是 $变量名 前面再加上& 就能调用那个exe了 后面再跟上 ...

  7. obs 录制教程 手机录屏用 向日葵 手机投屏 能用有线用有线的连接

    obs 录制教程 手机录屏用 向日葵 手机投屏 稍微有点卡 华为手机有个投屏 笔记本不支持这个 miracast 淘宝有卖 投屏设备的,搜 miracast 100多米 免费的就用向日葵就得了. 最新 ...

  8. Educational Codeforces Round 141:B. Matrix of Differences

    一.来源:Problem - B - Codeforces 二.题面 三.思路 我们先从一维思考如何构造尽可能多的数值差.以n=2为例,此时有1,2,3,4数,其中构成差值为3的方案有一个1,4,构成 ...

  9. 百度api经历

    底部参考文档,欢迎点击:https://www.runoob.com/http/http-content-type.html 这两天遇到了点糟心事,因为小伙伴走了.然后事情起因是这样的,来了个任务封装 ...

  10. Bitmap优化详谈

    目录介绍 01.如何计算Bitmap占用内存 1.1 如何计算占用内存 1.2 上面方法计算内存对吗 1.3 一个像素占用多大内存 02.Bitmap常见四种颜色格式 2.1 什么是bitmap 2. ...