Pytorch手工实现ResNet50
用 Pytorch 手工实现 ResNet50
《吴恩达深度学习课程》第四课第二周的作业是:使用 Keras 和 Tensorflow
编写
ResNet50,用程序实现题目中描述的网络结构。由于程序填空提供了不少示例,做完后仍感觉理解不透彻,又使用
Pytorch 实现了一遍。
ResNet50 包含 49 个卷积层和 1
个全连接层,属于较大型的网络,实现起来略有难度。对于理解数据流、卷积层、残差、瓶颈层,以及对大型网络的编写和调试都有很大帮助。
使用的数据仍是第四课第二周中的手势图片识别,题目说明、Keras
例程和相关数据可从以下网址下载:https://blog.csdn.net/u013733326/article/details/80250818
Keras ResNet50 程序填空的代码可从以下网址下载:https://github.com/Kulbear/deep-learning-coursera/blob/master/Convolutional%20Neural%20Networks/Residual%20Networks%20-%20v1.ipynb
Tor ...
卷积网络CNN
卷积网络 CNN
卷积网络是近年来非常流行的网络结构,常用于处理图像(2
维卷积)和自然语言(1
维卷积)。在不明觉厉的情况下使用卷积层,往往使用别人设计的结构,凑参数往模型里塞,同复杂的原理书中的内容又有点对不上号。本篇从应用场景,具体用法入手,深入到每一个重要参数:具体用途、用法及计算方法。
为什么使用卷积网络
先来看看全连接网络的参数:
网络有三个输入 x1,x2,x3 和两个输出 y1,y2,具体计算方法是:
如果 y1 与 x3 没有什么关系,通过训练两者之间的参数 w31 可能趋近于
0,但该连接仍然存在。对于输入为 3 输出为 2 的网络需要训练 32=6
个参数。图片数据非常庞大,如果训练一张 10001000 像素,RGB
三通道的图片,则输入元素有 3M 个,如果第一个隐藏层有 1000
个元素,则需要训练 100010003*1000
个参数,使得网络非常庞大,同时需要非常大量的数据才能避免过拟合。
卷积网络的优势在于共享参数,比如一个 3x3
的检测物体边缘卷积核训练好后,即可用于整个图片,此时需要学习的参数只有
3x3=9 个,如果在一层中训练 20 个 ...
归一化
归一化
为什么使用归一化
如果输入有多个
feature,且它们的数值范围有很大差异,这样训练时学习率就不能设置得太大,以免大幅调参引发越界。反之,如果各个
feature
有相同的均值和方差,则可使用更高的学习率,使收敛更快。归一化解决了梯度爆炸和梯度消失的问题,使构建更深层的网络成为可能,还避免了梯度爆炸和梯度消失。
使用模型时需要保证训练数据和测试数据同分布。在机器学习中往往对输入数据进行归一化处理,在深度学习中则常对网络的每一层都做归一化处理,以保证每次处理的数据分布一致。这也使得层与层之间更加独立,依赖更小。Batch-Normalize(BN)论文中描述:加入
BN 方法后,模型训练提速 14 倍,且精度也有所提升。
Convariate shift(漂移)问题
从原理上看,归一化缓解了内部协变量的移位问题,即漂移问题。深度神经网络中每一层输入都依赖之前层的输出,在训练的不同阶段,前层输出的分布也不相同。调参幅度越大越可能使分布变化,因此,只能使用较小的学习率,这样又使得收敛变慢。
由调参引发的内部数据分布变化的问题叫做内部协变量的移位问题,也被称作漂移问题。归一化方法可以 ...
深度网络调参
深度网络调参
重要的超参数
深度学习网络有很多超参数,下面列出了一些比较重要,常常需要调节的超参数。
最重要
学习率
较重要
mini-batch size
hidden units
网络层数
动量参数
学习率衰减
算力不同的调参
算力不同、网络规模、数据量不同,也有不同的调参方法,当模型和计算量较小时,可以使用网格调参;在算力足够的情况下,使用多组参数并行训练模型;反之,如果算力不足,且模型和数据较大,可能需要手动调参,比如训练几天之后,手动下调学习率,动量等超参数,人为地逐渐推进训练过程。
网格调参和随机调参
机器学习中常使用网格调参,即将参数列成表格,按一定步长尝试所有组合的参数,这种方法适用于较小的网络。深度学习网络一般较大,训练时间较长,一般使用随机抽取方法,在重点区域进行更多的抽样(密度更大),这样在一开始不确定哪些超参数重要时,可以广撒网,越往后越有针对性,实现从粗到细调参,同时又兼顾各种可能性,以免陷入局部最优值,类似于蒙特卡洛方法。
非线性轴调参
非线性轴调参也是常见的调参问题,比如设置学习率常常是 0.1, 0.01,
0.001, 0.0001…这样就不能 ...
设置BatchSize
设置 BatchSize
BatchSize
是非常重要的超参数,它不仅影响训练速度,也影响模型精度。本篇来讨论如何选择
BatchSize。
BatchSize 是否越大越好?
BatchSize 一般指同时代入训练模型的实例个数,最直接的经验是如果 GPU
显存不大,又设置较大的 BatchSize 时直接报错“cuda runtime error(2): out
of memory”。
是不是只要机器性能允许,就要设置尽可能大的 Batch size
呢?同时训练多个实例比逐个代入单个实例训练速度又能提高多少?
下图为使用不同的 batchSize,在 LeNet 上训练 mnist
数据的效果,使用的框架为 Theano。
可以看到,使用较大的 batchSize 的确可以提速,但是 batchSize
大到一定程度后,效果并不十分明显。
从图中可以看到如果将所有数据全部代入一次迭代(左图),则在训练集上的代价函数下降比较平滑,如果切分成多个
Batch,代价函数不一定是下降的。这是由于每一个 Batch
中数据的难度不同,造成了代价函数忽大忽小。
如何选择 batch 大 ...
避免过拟合
避免过拟合
欠拟合和过拟合
欠拟合是指在训练集和测试集(或验证集)上模型效果都不好,一般由于模型能力不足导致;过拟合是指模型在训练集上表现好,而在测试集上表现不好,一般由于模型过度拟合了训练集中的噪声导致。本文主要讨论解决过拟合问题的方法。
L2 正则化
无论机器学习还是深度学习,L2 正则化项都用于限制参数 W
过大,它被累加在代价函数之中。
代价函数J除了计算每个实例的误差L,还加入网络中每层参数W的 2
范数的平方,并用λ作为参数,当λ较大时,就需要W接近0,才能得到较小的代价函数,这样一些无关紧要的参数就变成了0,从而减少了模型的复杂度,以及压缩后模型的规模。另外,较小的W也使层之间传递的数据变小,这样在使用
sigmoid 和 tanh
激活函数时,数据刚好集中在中间类似线性变换的一段,使非线性变换的结果类似线性变换。由于多个线性组合叠加相当于单个线性层,因此也倾向于简化模型。
如果使用 L1 正则化,参数矩阵将变得稀疏,根据经验,一般 L2
效果更好。L2
正则化方法可用于简化决策,但不适用于需要复杂决策的问题。使用该方法时,需要尝试多个λ值。
Dropout 方法
Dr ...
初始化网络参数
初始化网络参数
#深度学习
为什么要给网络参数赋初值
既然网络参数通过训练得到,那么其初值是否重要?设置初值不佳是否只影响收敛速度而不影响模型结果?网络参数是否可以设置为全
0 或者全 1?
假设网络的参数W初值都是0,如下图所示,无论输入任何X,第一层的输出A将都为0,再向前传递到
y 也是 0,使用误差函数调参时,每一层的梯度只与该层的输入和输出有关,由于
a1,a2
值相等,计算出的梯度调整的值,以及调整后的梯度也相等;第二次迭代也同理,由于
a1,a2 相等,w[2]中各单元的值也相等。因此该层有 100 个单元与 1
个单元没有差异,该问题被称为“对称性”问题。
试想将 w 设置成全 1,则有 a1=x1+x2,a2=x1+x2,a1 与 a2
值仍然相同,对称性问题依然存在。由此,一般将参数设置为随机值。
设置成随机值还不够,还需要设置成较小的随机值,试想如果 w 的均值在 0.5
附近,某一层的输入输出都为 500
个元素,那么经过该层乘和加的运算,输出约是输入值的 250
倍;如果存在多层,250x250x…,很快就爆炸了。如果在层后使用 Sigmoid
函数,将值映 ...
激活函数
激活函数
为什么使用激活函数
如果没有激活函数,神经网络就变成了线性模型,输出是输入的线性组合,使用一层与使用多层没有区别。如下式所示,输入为
x,经过线性层计算出 a1,将 a1 输入下个线性层得到
a2,展开后可以看出,最终得到的仍然是 wx+b
的线性组合,只是参数值不同。
图片.png
另外,线性层无法解决非线性问题,如在预测房价问题中,如果不使用激活函数,则房价可能计算成负值,这也与实际不符。理论上,加了激活函数后,模型可以逼近任意函数。
激活函数又分线性激活函数和非线性激活函数,一般使用的都是非线性激活函数,线性激活函数与线性层类似,只在输出层偶尔使用,不在此展开讨论。
何时使用激活函数
激活函数一般放置在线性变换之后,在线性变换和激活函数之间,常常插入归一化层,用于解决饱和的非线性激活函数问题(下面
Sigmoid 函数部分详细说明)。
如何选择激活函数
从一些当前流行的深度学习网络代码中,可以看到,当前使用的激活函数绝大部分是
ReLU;在一些特殊情况下,也使用 Sigmoid,比如二分类问题的最后一层使用
Sigmoid 将输出转换到 0-1 之间;又如使用注意 ...
浅析梯度迭代算法
浅析梯度迭代算法
梯度迭代类算法已成为目前各种领域的主流算法。各种现实中的问题分解抽象成机器可以处理的形式之后,基本都可归类为图像、自然语言处理、决策、时序、强化学习这几种类型,而当今解决这些问题的顶尖算法中,梯度迭代(梯度上升或梯度下降)都占据主流地位,比如决策类问题的比赛中,梯度下降决策树
GBDT
类算法是完全的主流,使用深度学习网络处理图片自然语言问题更毋庸置疑。
那么,梯度迭代算法究竟是什么?简单地说,就是代入数据,预测结果,如果结果偏大就调小参数,结果偏小就调大参数。举一个简单的例子,分为三个小问题:
问题一
假设父亲的智商影响儿子的智商,设父亲的智商为x,儿子的智商为y,y=wx,训练一个参数
w 学习二者之间的关系。目前有多个父子智商数据对,其中第一个数据:父亲智商
x=100,儿子智商 w=110,将 w 初值设为 w=1.0;学习率设为
0.00001,计算平均误差。
如下程序用于学习 w。
123456789101112131415161718192021import torch import matplotlib.pyplot as plt %matplo ...
Pytorch常用函数之一_数据类型
Pytorch 常用函数之一 _
数据类型
#Pytorch
编程语言和自然语言一样,不理解的词越多,对全文的理解就越差。掌握必要的基础知识,让后期看代码更加流畅。
机器学习需要掌握数据处理工具
Pandas、Numpy,同理,深度学习也需要掌握相应的工具,在 Pytorch
中数据存储在 Tensor
之中,本篇将介绍它们的基本用法以及与之相关的常用函数。
查看版本信息
包含头文件
11. import torch
1.查看 torch 版本
11. print(torch.__version__)
2.查看 CUDA 版本
11. print(torch.version.cuda)
GPU 相关操作
1. 查看当前是否支持 GPU
11. device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
2.GPU 相关的数据转换
123451. a = torch.Tensor([5]) 2. b = a.to('cuda') # ...