Skip to content

Latest commit

 

History

History
102 lines (84 loc) · 9.34 KB

Learning.md

File metadata and controls

102 lines (84 loc) · 9.34 KB

这2天主要是学习 Pytorch使用与常见的网络模型的实现,参考的 github 地址是:https://github.com/kuangliu/pytorch-cifar

概念

  • 张量 Tensor
  • 神经网络的训练过程:神经网络的训练数据的处理与导入、经过神经网络的层然后输出结果与期望的结果进行比较,这里用损失函数 LOSS 函数代表实际输出与期望输出之间的误差(前向传播),然后优化器(optimizer)会根据 LOSS 和神经网络的情况,更新网络参数(反向传播),使得 LOSS 值缩小。
  • 激活函数:激活函数的作用是在神经网络中加入非线性,使得网络可以更好的拟合复杂的问题
    • sigmoid 函数:
    • ReLU 函数:是一种效果更好,收敛更快的激活函数,能够缓解梯度消失的问题。ReLU 是目前现有大部分 CNN 首选的激活函数。
  • 批大小、mini-batch、epoch:批大小就是每次训练,调整网络参数之前所选取的样本的数量。epoch 指学习完一遍数据集,例如样本数量为 1000,batch 为 100,那么需要将数据集分成 10 次训练,网络参数也会调整 10 次,而读取完一次完整的数据就称为一个 epoch.但是这并不是说网络结构就是最优的了,我们需要重复的学习这个数据集,注意的是每一个 epoch 都需要打乱顺序。批大小越大的话则需要占用更大的显卡,需要更昂贵的显卡,SGD 中的梯度会更准确,网络更容易陷入鞍点和极值点的逆汤。批大小越小的话,网络训练越慢。研究人员的经验是,对于常见的问题,最优的批大小往往在16到256之间,太小则会训练过慢,太大则性能不佳。
  • 学习速率:可以简单的理解为梯度下降中的步长。学习率太大的话,由于每步迈得太大,出现了明显的震荡,有可能会使网络崩掉。学习速率太小的话则训练速度会更慢。在实际训练中通常使用以下的方案:最初的 x 个 epoch 使用 a 的学习率,然后每过 y 个 epoch 将学习速率将为原来的 b 分之一。
  • 神经网络的初始化:神经网络的初始化包括权重和偏置。参数的初始化不能全为零,通常将网络的初始权重设为正态分布的随机数。
  • 调参:调整网络训练的超参数(hyper-parameters)的过程称为“调参”,这里有2个概念需要搞清楚,网络的参数是指网络的权重和偏置,这个参数是通过反向传播学习到的。网络的超参数则包括学习速率、批大小、网络架构(如每层的神经元的数目)等。例如将训练的样本增大,学习率降低,可以发现每个 epoch 后可以得到更准确的指,但是训练的过程变慢了。
  • 梯度爆炸
  • 过拟合:训练的第一步通常是数据的收集,当数据收集好之后我们并不会将它们全部用于训练模型,因为我们训练网络的目标是希望他能在现有的数据上获得较好的性能,也希望在未来的新数据获取较好的性能。所以一般训练的过程通常分为2部分:
    • 保证能学好现有的数据:如果学习不好称为欠拟合
    • 验证在新数据上的性能,这称为泛化能力:
      • 在旧数据集性能好,在新数据集性能差,说明泛话能力差,称为过拟合
      • 如果在新的数据集上性能也好,称为泛化能力强
  • 神经网络的正则化:过拟合是提高神经网络性能的主要账号
  • 有监督学习与无监督学习
    • 有监督学习:在数据集中,对于每个输入 X,都有现成的输出目标 Y (可称为标签),模型的目标是从 X 找到 Y。有监督学习中最常见的是回归与分类。
    • 无监督学习:无监督学习的特点是,只有大量的数据 X 而没有对应的标签 Y
  • 梯度下降算法:SGD、Adam、Adagrad、momentum 等,现有的深度学习的框架都内置了这些算法
  • 神经网络的正则化:神经网络的正则化是为了避免过拟合
    • 修改损失函数:L2 和 L1 正则化:会在原来的损失函数上加上一个正则化项,
    • 修改网络架构:Dropout 正则化:每次训练的时候随机删除 50% 的隐含层神经元(将神经元的权重视为 0,并且在更新权重的时候不更新它们的权重)
  • SoftMax 层、交叉熵损失
    • SoftMax 层:相当于对概率做归一化处理,例如在图像分类中,如果每张图像只能属于一个分类那么,分类的概率需要满足2个条件,第一个是每一个分类的概率都要在 0% 到 100% 之间,第二个是所有的分类的概率之和等于 100%。如果每张图像可属于多个分类,则总概率可以大于1,此时可以用 sigmoid 作为输出的非线性激活函数,因为 sigmoid 的值一定是 0 到 1 之间.
    • 交叉熵:对于分类的问题,损失函数推荐使用交叉熵损失

卷积神经网络

  • CNN 设计的初衷是来源于人类对视觉信息的识别过程。深度学习 CNN 通过卷积层与池化层将不同位置的特征都提取出来,进而消除前馈神经网络对未知的依赖性。卷积神经网络大概就是卷积层、池化层、激活函数、全连接层的组合。
  • 概念:

  • 卷积层:是 CNN 的重要的组件,通过卷积核提取图像特征,还能够优化计算量。关于卷积的计算过程参考这篇文章,有动画的能够较好的理解卷积的过程:https://mp.weixin.qq.com/s/zDMhFpREX8kCrh4GDkbEpA
  • 池化:
  • Inception:用于消除不同图像大小的影响
  • Flatten 层和全连接层:当抓取到足以用来识别图片的特征之后,接下来的问题就是如何进行分类,通过 Flatten 层展开之前的特征图,并结合全连接层(FC)将结果映射到可分的空间。这里的 FC 其实就是个分类器的作用。可以这么理解卷积层、池化层和激活函数层等操作都是将原始的数据映射到隐含层特征空间,而全连接层起到的作用则是将学习到的特征映射到样本标记空间。
  • 1 x 1 卷积:通过 N 个 1x1 的卷积,只需要少量的参数就能将 M 张图像变成 N 张图像。如果希望改变通道数或者图像的尺寸,最简单的方法就是使用 1X1 的卷积层。
  • 批规范化(Batch Normalization,BN):BN 原理是让网络中间数据的分布尽量规范,就像校准准星,可显著的加入深度网络的训练,而且有一定的正则化能力。使用 BN 后分布会更加稳定、对称而且均值会更接近0,有利于神经元的训练与改善过拟合。

Pytorch 框架实现常见的 CNN 框架

VGG 模型

  • 该模型算是比较简单的结构,可以参考其论文https://arxiv.org/pdf/1409.1556.pdf 吴恩达的笔记 https://www.cnblogs.com/szxspark/p/8442049.html

  • 图片说明:表格中 convK-N 代表有 N 个 KxK 卷积,maxpool 代表最大池化,FC-N 代表 N 个全连接神经元,所有的卷积后面都有 ReLU 层。最大池化层是负责缩小图像,大小与步长都为2

    ` import torch import torch.nn as nn

    cfg = { 'VGG11': [64, 'M', 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'], 'VGG13': [64, 64, 'M', 128, 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'], 'VGG16': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'M', 512, 512, 512, 'M', 512, 512, 512, 'M'], 'VGG19': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 256, 'M', 512, 512, 512, 512, 'M', 512, 512, 512, 512, 'M'], }

    class VGG(nn.Module):#模型都是继承自 nn.Module def init(self, vgg_name):#init 定义了可学习的参数 super(VGG, self).init() self.features = self._make_layers(cfg[vgg_name]) self.classifier = nn.Linear(512, 10)

    def forward(self, x):#forward 实现了前向传播的过程 out = self.features(x) out = out.view(out.size(0), -1) out = self.classifier(out) return out

    def _make_layers(self, cfg): layers = [] in_channels = 3 for x in cfg: if x == 'M':#M 代表最大池化层 layers += [nn.MaxPool2d(kernel_size=2, stride=2)] else: layers += [nn.Conv2d(in_channels, x, kernel_size=3, padding=1), nn.BatchNorm2d(x), nn.ReLU(inplace=True)] in_channels = x layers += [nn.AvgPool2d(kernel_size=1, stride=1)] return nn.Sequential(*layers)

    def test(): net = VGG('VGG11') x = torch.randn(2,3,32,32) y = net(x) print(y.size())`

  • ResNet模型

  • ResNet 引入了残差网络的概念,神经网络越深,效果往往越好,但是极深的网络并不容易训练。 如图所示,x 表示输入,F(x) 表示残差块在第二层激活函数之前的输出,即 F(x)=W2σ(W1x),其中 W1 和 W2 表示第一层和第二层的权重,σ 表示 ReLU 激活函数。(这里省略了 bias。)最后残差块的输出是 σ(F(x)+x)。ResNet 网络就是由基本的残差模组组成的。对代码的解读参考 https://blog.csdn.net/alxe_made/article/details/84424577 以下是我自己写的对代码的注释