原理及步骤

数据处理

PyTorch中对于数据集的处理有三个非常重要的类:DatasetDataloaderSampler,它们均是 torch.utils.data 包下的模块(类)。它们的关系可以这样理解:

Dataset是数据集的类,主要用于定义数据集

Sampler是采样器的类,用于定义从数据集中选出数据的规则,比如是随机取数据还是按照顺序取等等

Dataloader是数据的加载类,它是对于Dataset和Sampler的进一步包装,即其实Dataset和Sampler会作为参数传递给Dataloader,用于实际读取数据,可以理解为它是这个工作的真正实践者,而Dataset和Sampler则负责定义。我们训练、测试所获得的数据也是Dataloader直接给我们的。

Dataset

Dataset 位于 torch.utils.data 下,我们通过定义继承自这个类的子类来自定义数据集。它有两个最重要的方法需要重写,实际上它们都是类的特殊方法:

__getitem__(self, index):传入参数index为下标,返回数据集中对应下标的数据组(数据和标签)
       __len__(self):返回数据集的大小

Dataset的目标是根据你输入的索引输出对应的image和label,而且这个功能是要在__getitem__()函数中完成的,所以当你自定义数据集的时候,首先要继承Dataset类,还要复写__getitem__()函数。

Dataloader

Dataloader对Dataset(和Sampler等)打包,完成最后对数据的读取的执行工作,一般不需要自己定义或者重写一个Dataloader的类(或子类),直接使用即可,通过传入参数定制Dataloader,定制化的功能应该在Dataset(和Sampler等)中完成了。

Sampler

Sampler类是一个很抽象的父类,其主要用于设置从一个序列中返回样本的规则,即采样的规则。Sampler是一个可迭代对象,使用step方法可以返回下一个迭代后的结果,因此其主要的类方法就是 __iter__ 方法,定义了迭代后返回的内容。

SequentialSampler

SequentialSampler就是一个按照顺序进行采样的采样器,接收一个数据集做参数(实际上任何可迭代对象都可),按照顺序对其进行采样。

RandmSampler

RandomSampler 即一个随机采样器,返回随机采样的值,第一个参数依然是一个数据集(或可迭代对象)。还有一组参数如下:

replacement:bool值,默认是False,设置为True时表示可以采出重复的样本
       num_samples:只有在replacement设置为True的时候才能设置此参数,表示要采出样本的个数,默认为数据集的总长度。有时候由于replacement置True的原因导致重复数据被采样,导致有些数据被采不到,所以往往会设置一个比较大的值.

SubsetRandomSampler

SubsetRandomSampler可以设置子集的随机采样,多用于将数据集分成多个集合,比如训练集和验证集的时候使用:

WeightedRandomSampler

WeightedRandomSampler和RandomSampler的参数一致,但是不在传入一个dataset,第一个参数变成了weights,只接收一个一定长度的list作为 weights 参数,表示采样的权重,采样时会根据权重随机从 list(range(len(weights))) 中采样,即WeightedRandomSampler并不需要传入样本集,而是只在一个根据weights长度创建的数组中采样,所以采样的结果可能需要进一步处理才能使用。weights的所有元素之和不需要为1。

BatchSampler

以上的四个Sampler在每次迭代都只返回一个索引,而BatchSampler的作用是对上述这类返回一个索引的采样器进行包装,按照设定的batch size返回一组索引,因其他的参数和上述的有些不同:
       sampler:一个Sampler对象(或者一个可迭代对象)
       batch_size:batch的大小
       drop_last:是否丢弃最后一个可能不足batch size大小的数据

collate_fn

Dataloader其实还有一个比较重要的参数是 collate_fn,它接收一个 callable 对象,比如一个函数,它的作用是将每次迭代出来的数据打包成batch。
       举个例子,如果我们在Dataloader中设置了batch_size为8,实际上,从Dataloader所读取的数据集Dataset中取出数据时得到的是单独的数据,比如我们的例子中,每次采样得到一个tuple:(image, label),因此collate_fn 的作用就有了,它负责包装batch,即每从数据集中抽出8个这样的tuple,它负责把8个(image, label)包装成一个list: [images, labels],这个list有两个元素,每一个是一个tensor,比如第一个元素,实际上是一个 8×size(image) 的tensor,即给原来的数据增加了一维,也就是最前边的batch的维度,labels也同理。
       有时候我们可能会需要实现自己的包装逻辑,所以需要自定义一个函数来完成定制化的如上的内容,只要将该函数名传递给collate_fn参数即可。

pytorch两个基本对象:Tensor(张量)和Variable(变量)

其中,tensor不能反向传播,variable可以反向传播。

tensor的算术运算和选取操作与numpy一样,一次你numpy相似的运算操作都可以迁移过来。

variable是一种可以不断变化的变量,符合反向传播,参数更新的属性。pytorch的variable是一个存放会变化值的地理位置,里面的值会不停变化,像装糖果(糖果就是数据,即tensor)的盒子,糖果的数量不断变化。pytorch都是由tensor计算的,而tensor里面的参数是variable形式。

代码及注释

import torch # 需要的各种包
import torch.nn as nn
from torch.autograd import Variable
import torch.utils.data as data
import matplotlib.pyplot as plt
import torchvision # 数据库模块# 数据预处理
# 将training data转化成torch能够使用的DataLoader,这样可以方便使用batch进行训练
torch.manual_seed(1) # reproducible 将随机数生成器的种子设置为固定值,这样,当调用时torch.rand(x),结果将可重现# Hyper Parameters
EPOCH = 1 # 训练迭代次数
BATCH_SIZE = 50 # 分块送入训练器
LR = 0.001 # 学习率 learning ratetrain_data = torchvision.datasets.MNIST(root='./mnist/', # 保存位置 若没有就新建train=True, # training settransform=torchvision.transforms.ToTensor(), # # converts a PIL.Image or numpy.ndarray to torch.FloatTensor(C*H*W) in range(0.0,1.0)download=True
)test_data = torchvision.datasets.MNIST(root='./MNIST/')# 如果是普通的Tensor数据,想使用 torch_dataset = data.TensorDataset(data_tensor=x, target_tensor=y)
# 将Tensor转换成torch能识别的dataset
# 批训练, 50 samples, 1 channel, 28*28, (50, 1, 28 ,28)
train_loader = data.DataLoader(dataset=train_data, batch_size=BATCH_SIZE, shuffle=True)test_x = Variable(torch.unsqueeze(test_data.test_data, dim=1), volatile=True).type(torch.FloatTensor)[:2000]/255.
# torch.unsqueeze 返回一个新的张量,对输入的既定位置插入维度 1test_y = test_data.test_lables[:2000]
# 数据预处理# 定义网络结构
# 1)class CNN需要·继承·Module
# 2)需要·调用·父类的构造方法:super(CNN, self).__init__()
# 3)在Pytorch中激活函数Relu也算是一层layer
# 4)需要·实现·forward()方法,用于网络的前向传播,而反向传播只需要·调用·Variable.backward()即可。
# 输入的四维张量[N, C, H, W]
class CNN(nn.Module):def __init__(self):super(CNN, self).__init__()# nn.Sequential一个有序的容器,神经网络模块将按照在传入构造器的顺序依次被添加到计算图中执行,# 同时以神经网络模块为元素的有序字典也可以作为传入参数# nn.Conv2d 二维卷积 先实例化再使用 在Pytorch的nn模块中,它是不需要你手动定义网络层的权重和偏置的self.conv1 = nn.Sequential( #input shape (1,28,28)nn.Conv2d(in_channels=1, #input height 必须手动提供 输入张量的channels数out_channels=16, #n_filter 必须手动提供 输出张量的channels数kernel_size=5, #filter size 必须手动提供 卷积核的大小 # 如果左右两个数不同,比如3x5的卷积核,那么写作kernel_size = (3, 5),注意需要写一个tuple,而不能写一个列表(list)stride=1, #filter step 卷积核在图像窗口上每次平移的间隔,即所谓的步长padding=2 #con2d出来的图片大小不变 Pytorch与Tensorflow在卷积层实现上最大的差别就在于padding上), # output shape (16,28,28) 输出图像尺寸计算公式是唯一的 # O = (I - K + 2P)/ S +1nn.ReLU(), # 分段线性函数,把所有的负值都变为0,而正值不变,即单侧抑制nn.MaxPool2d(kernel_size=2) #2x2采样,28/2=14,output shape (16,14,14) maxpooling有局部不变性而且可以提取显著特征的同时降低模型的参数,从而降低模型的过拟合) self.conv2 = nn.Sequential(nn.Conv2d(16, 32, 5, 1, 2), #output shape (32,7,7)nn.ReLU(),nn.MaxPool2d(2))# 因上述几层网络处理后的output为[32,7,7]的tensor,展开即为7*7*32的一维向量,接上一层全连接层,最终output_size应为10,即识别出来的数字总类别数# 在二维图像处理的任务中,全连接层的输入与输出一般都设置为二维张量,形状通常为[batch_size, size]self.out = nn.Linear(32*7*7, 10) # 全连接层 7*7*32, num_classesdef forward(self, x):x = self.conv1(x) # 卷一次x = self.conv2(x) # 卷两次x = x.view(x.size(0), -1) #flat (batch_size, 32*7*7) # 将前面多维度的tensor展平成一维 x.size(0)指batchsize的值# view()函数的功能根reshape类似,用来转换size大小output = self.out(x) # fc out全连接层 分类器return output
# 定义网络结构# 查看网络结构
cnn = CNN()
print(cnn) # 使用print(cnn)可以看到网络的结构详细信息,可以看到ReLU()也是一层layer
# 查看网络结构# 训练 需要特别指出的是记得每次反向传播前都要清空上一次的梯度,optimizer.zero_grad()
# optimizer 可以指定程序优化特定的选项,例如学习速率,权重衰减等
optimizer = torch.optim.Adam(cnn.parameters(), lr=LR) # torch.optim是一个实现了多种优化算法的包# loss_fun CrossEntropyLoss 交叉熵损失
# 信息量:它是用来衡量一个事件的不确定性的;一个事件发生的概率越大,不确定性越小,则它所携带的信息量就越小。
# 熵:它是用来衡量一个系统的混乱程度的,代表一个系统中信息量的总和;信息量总和越大,表明这个系统不确定性就越大。
# 交叉熵:它主要刻画的是实际输出(概率)与期望输出(概率)的距离,也就是交叉熵的值越小,两个概率分布就越接近
loss_func = nn.CrossEntropyLoss() # 该损失函数结合了nn.LogSoftmax()和nn.NLLLoss()两个函数 适用于分类# training loop
for epoch in range(EPOCH):for i, (x, y) in enumerate(train_loader):batch_x = Variable(x)batch_y = Variable(y)output = cnn(batch_x) # 输入训练数据loss = loss_func(output, batch_y) # 计算误差 # 实际输出, 期望输出optimizer.zero_grad() # 清空上一次梯度loss.backward() # 误差反向传递 只需要调用.backward()即可optimizer.step() # cnn的优化器参数更新
# 训练# 预测结果
# cnn.eval()
test_output = cnn(test_x[:10])
pred_y = torch.max(test_output, 1)[1].data.numpy().squeeze()
# torch.max(input, dim)函数
# torch.max(test_output, 1)[1]  取出来indices 每行最大值的索引
# 输入 input是softmax函数输出的一个tensor
# 输入 dim是max函数索引的维度0/1,0是每列的最大值,1是每行的最大值
# 输出 函数会返回两个tensor,第一个tensor是每行的最大值;第二个tensor是每行最大值的索引。
# squeeze()函数的功能是:从矩阵shape中,去掉维度为1的。例如一个矩阵是的shape是(5, 1),使用过这个函数后,结果为(5,)。
print(pred_y, 'prediction number')
print(test_y[:10], 'real number')
# 预测结果

参考文章:

Pytorch实现卷积神经网络CNN - Peter-Young - 博客园

使用PyTorch实现CNN_dongyangY的博客-CSDN博客_cnn pytorch

Pytorch实现简单CNN模型 - 知乎

CNN简单理解+PyTorch示例实现_「已注销」的博客-CSDN博客_pytorch实现cnn代码讲解

其他文章内容已被汇总至代码注释中,忘记出处,抱歉

PyTorch实现CNN相关推荐

  1. Pytorch和CNN图像分类

    Pytorch和CNN图像分类 PyTorch是一个基于Torch的Python开源机器学习库,用于自然语言处理等应用程序.它主要由Facebookd的人工智能小组开发,不仅能够实现强大的GPU加速, ...

  2. Pytorch之CNN:基于Pytorch框架实现经典卷积神经网络的算法(LeNet、AlexNet、VGG、NIN、GoogleNet、ResNet)——从代码认知CNN经典架构

    Pytorch之CNN:基于Pytorch框架实现经典卷积神经网络的算法(LeNet.AlexNet.VGG.NIN.GoogleNet.ResNet)--从代码认知CNN经典架构 目录 CNN经典算 ...

  3. 卷积神经网络、比较MLPS和CNNS、滤波器、CNN各层的作用、在Pytorch可视化CNN

    1.33.卷积神经网络 1.33.1.卷积 和 神经网络 1.33.1.1.比较MLPS和CNNS 1.33.1.2.计算机如何看图像? 1.33.1.3.建立自己的滤波器 1.33.2.完整的卷积神 ...

  4. MINIST深度学习识别:python全连接神经网络和pytorch LeNet CNN网络训练实现及比较(三)...

    版权声明:本文为博主原创文章,欢迎转载,并请注明出处.联系方式:460356155@qq.com 在前两篇文章MINIST深度学习识别:python全连接神经网络和pytorch LeNet CNN网 ...

  5. 基于PyTorch搭建CNN实现视频动作分类任务代码详解

    数据及具体讲解来源: 基于PyTorch搭建CNN实现视频动作分类任务 import torch import torch.nn as nn import torchvision.transforms ...

  6. Pytorch中CNN入门思想及实现

    CNN卷积神经网络 基础概念: 以卷积操作为基础的网络结构,每个卷积核可以看成一个特征提取器. 思想: 每次观察数据的一部分,如图,在整个矩阵中只观察黄色部分3×3的矩阵,将这[3×3]矩阵·(点乘) ...

  7. 03.PyTorch与CNN(4-1 机器学习和神经网络的基本概念(1))

    03.PyTorch与CNN(4-1 机器学习和神经网络的基本概念(1)) 一, 4-1 机器学习和神经网络的基本概念(1) 来自慕课网 一, 4-1 机器学习和神经网络的基本概念(1)

  8. 【深度学习基础】SENet——PyTorch实现CNN的SE结构改造

    [深度学习基础][深度学习基础]SENet--PyTorch实现CNN的SE结构改造 1 论文关键信息 1.1 SE block 1.1.1 squeeze 1.1.2 Exitation 2 pyt ...

  9. 使用PyTorch搭建CNN神经网络

    使用pytorch搭建CNN神经网络 卷积运算的基本原理 单层卷积运算 valid convolution same convolution CNN的基本结构 数据输入层 卷积层 池化层 全连接层 数 ...

  10. 基于pytorch使用实现CNN 如何使用pytorch构建CNN卷积神经网络

    基于pytorch使用实现CNN 如何使用pytorch构建CNN卷积神经网络 所用工具 文件结构: 数据: 代码: 结果: 改进思路 拓展 本文是一个基于pytorch使用CNN在生物信息学上进行位 ...

最新文章

  1. Xamarin XAML语言教程构建ControlTemplate控件模板 (三)
  2. 教育部:全国高考延期一个月,湖北北京再行决定
  3. 转:初学者简易 .vimrc编写指南
  4. 新手怎么读懂一个中型的Django项目
  5. 拷贝boost::exception的测试程序
  6. Guava入门~Strings
  7. linux带参数post调用接口,CURL命令模拟Http Get/Post以及带cookies调用接口
  8. Python可视化——绘制折线图
  9. 汽车4S店经营状况分析
  10. 办公必备APP,收藏有料
  11. 如何使用Axure制作产品需求文档prd
  12. Mac 开发工具汇总
  13. Linux之恢复删除的数据
  14. JS 基础知识点与高频考题解析
  15. Docker 镜像和容器
  16. 消除笔哪个p图软件有?快把这些软件收好
  17. c#通过串口及CAN模块实现上位及下位机通讯
  18. 算法设计例题分析 食物链
  19. html 表情转换器,HTML5高仿微信聊天、微信聊天表情|对话框|编辑器功能
  20. 创业实践案例课程答案

热门文章

  1. iOS直播点赞动画,iOS直播心型点赞动画
  2. C++标准程序库读书笔记-第四章通用工具
  3. Java基础之continue与break区别
  4. Struts2 初探
  5. 复杂作业车间调度-单机调度问题研究
  6. VS2010/MFC编程入门之二十六(常用控件:滚动条控件Scroll Bar)
  7. MFC(VS2010)编程实例之一(Edit Control控件)
  8. NSGA-Ⅱ算法C++实现(测试函数为ZDT1)
  9. 从零基础入门Tensorflow2.0 ----四、18.读取tfrecords文件并与tf.keras结合使用
  10. 网易编程题目——相反数: