当前位置:网站首页>cs231n学习记录
cs231n学习记录
2022-08-05 05:25:00 【ProfSnail】
cs231n是斯坦福大学开设的深度学习与计算机视觉结合的一门课程,许多地方都可以找到这门课程的公开资源。由于最近在做计算机视觉相关的工作,所以学习一下这门课程的内容,并对这门课程中一些有启发的内容进行记录。鉴于许多地方已经有比较完善和系统的笔记体系,我就不做事无巨细的学习笔记了。与此前的博文一样,这篇博文也会随着我的学习深入而不断更新的。
在此前粗略学习卷积神经网络过程的时候,尤其是计算反向传播时候的梯度问题时,往往卡在了池化层的反向梯度计算上。链式传导规则得到的启发是,使用最大值池化,在反向传播过程中从上游传下来的梯度,会被完整的送给之前取过最大值的分支;前向传播时,不是最大值的那些分支,将无法收到反向传播过来的梯度值。对于平均值池化,前向传播时候的函数是 f ( x ) = ( x 1 + x 2 + x 3 + x 4 ) / 4 f(x)=(x_1+x_2+x_3+x_4)/4 f(x)=(x1+x2+x3+x4)/4,这也是一个加法与除法结合的式子,完全可以使用求导方法,将上游梯度值传导到下游中。
简而言之,神经网络梯度传导计算的规则,基于了一大串链式求导规则,熟练运用链式规则才可以将梯度传导运用娴熟。此外,某层想要知道反向传播时候的梯度,只需要在这层记住是如何传导进来的,这便于构造某个类,以存储计算法则和求导法则。这件事情在Pytorch中做的不错。激活函数的一些总结。这门课程总算让我搞清了三年前的一个心结,也就是梯度消失到底意味着什么?
sigmod函数会在自变量趋于无穷的时候,函数变得平滑。这种平滑对应于反向传播时候的梯度求导是相当不公平的,反向求导时候得到的梯度值非常小,接近于0,这也就导致了即使上游传导下来的梯度值很大,再继续向下游传播的时候,只会传播回去一个接近0的值,这就导致了梯度消失问题。
类似的,说到饱和状态,这也是我此前很模糊的一个概念。所谓饱和,可以联想到化学中的饱和溶液,当水里面已经溶解了充分多的盐的时候,再继续加盐,无论加多少,水已经无法继续溶解这些盐了,盐将会以晶体颗粒的形式继续存在于水中。神经网络的饱和可以由此类推,也就是说,当网络收敛到一定程度的时候,无法再通过梯度传播等方式对网络中的参数进行修正,这种状态可以称为饱和状态。解决梯度消失的方法在课程中讲了讲,似乎是tanh和ReLu函数可以解决,不过已经学过去了两三个礼拜,忘得差不多了。这次博客主要不是做回忆录的,优先写完这篇博客,等以后回顾此前内容的时候,再将这一段解决方案补上。印象中,ReLu函数存在许多变体,包括LeakyReLu,能够让函数在正数部分一直保证存在梯度,在负数或者不关心的部分,也会有一个比较小的梯度值。
关于偏置项的含义。计算激活函数的时候,总会比较 w x + b wx+b wx+b与0的大小,以作为是否激活的依据。之前的理解仅限于与0作比较。学习之后发现,其实是wx与b作比较,b是确定是否激活的阈值,即threshold。这件事情挺重要,神经网络在调参的时候,反向传播也会对b进行修正,这是否意味着,经过不断的学习,是否接受刺激的下限也在不断调整中呢。或是说,其实这个阈值不应该调整,而是作为某件一以贯之的事情,从头至尾?我更偏向于前面的推论。
多层感知机,可以解决异或分类问题。这件事情我之前一直比较困惑,心里没有一个明确的答案。既然课程中已经盖棺定论了,我也就不必纠结了。
课程中会不断涉及到正则化这个概念。正则化,正则谁?而且正则这个概念,不止出现在深度学习的条目中,也出现在了传统机器视觉中的一些理论中。正则这个观念,不太理解。
批量归一化。学习这一段的时间是大半夜了,有点犯困,现在回想起来没有特别多能记住的地方。批量归一化的主要观点是,希望通过将训练用的数据,回归到以0为中心的、方差均匀的点上。这样做的优势在于,经过归一化,可以使得位于中心点的直线斜率发生改变时,对于偏离中心点的数据影响不那么明显。
之所以选用批量归一化,而非全局归一化,是出于计算能力有限的角度。如果进行全局所有数据归一化,耗费的时间之久往往难以接受。课程中还谈及了一些参数的初始化方法,我认为这也相当有用,可惜没有记住。等回顾的时候再补充这一段吧。如果权重初始化过小,传播过程中的数值就会越来越小,导致没有数据被学习到。如果初始化参数过大,就会出现此前说过的饱和现象,也没有办法进行学习。较好的初始化,会让每一层的权重都得到有效的学习。
有关损失函数等高图怎么看。
刚才给出了一个损失函数的等高图图像,图像中心的点,是损失函数的极小值点。周围一圈一圈的线,是由所有损失误差相等的点构成的,并且离中心越远,这圈椭圆形的线上代表的损失数值就越大。意味着如果垂直方向进行移动,不需要移动多远,就会从一个比较高的误差,移动到另一个比较小的误差线上去;而如果想要同样在两个等高圈里面进行移动的话,水平移动就需要移动更远的距离。所以当横着和竖着的变化速率是相同的时候,竖着进行移动和修正,很有可能更快的移动,甚至直接越过了最优的平面线,而横着移动半天也到不了最低值。这就引出了一种对于不同方向的参数(向量中的不同位置),分别学习和修正的方法。随机梯度下降(SGD,Stochastic Gradient Decent)出现的另一个问题是,驻留在局部极小值的点,或者是较为平滑的曲线附近,由于这个地方的梯度值为0,随机梯度下降方法就会停留在此,而丧失继续寻找的动力。解决方法是提供初始速度,即使在移动过程中遇到了平滑点,由于初始速度依然还在,没办法立刻收手停下来,因此还会继续滑下去。如果发现刚刚走过了,梯度就会拉着往回走,直到走到极值点,或者最小值点为止,这就像高中物理题一样,小球受到表面摩擦力的影响, 如果初速度很大,他可能翻过小山坡,如果初速度不够大,他可能就停在当前的小低谷里面了。刚刚我说的这种方法,被称作动量优化方法,SGD+Momentum。
之前的动量修正是在当前点上进行的。这种方法会有一个改进,称作Nesterov Momentum,改进后的方案则是,先按照速度走一走,看一下走完之后的效果如何,并按照移动之后的位置计算梯度值。回到原始位置之后,修正路线。AdaGrad是针对不同位置梯度变化速率不同,而提出的修正策略。该策略的思路是,累加梯度的平方,如果在某个方向上一直都在做修正,而且修正的很快,就除以这个较大的数字,从而让此方向上的修正速度没那么快;如果这个方向的梯度一直很小,除以一个比较小的数字,会让修正的速度变快。另外,由于梯度一直在积累,会导致除数的平方和的值越来越大,最后的学习速率更高。这样的效果其实正是希望的。
不过AdaGrad方法还有一个弊端,也正是刚刚最后说到的,学习速度越来越慢,导致在非凸优化的时候,聚集在某个局部极值点附近,无法进一步移动和修正。这并非什么好事情。RMSProp优化方案是针对这一点提出的,他让梯度平方和没有那么顺利的一直进行累加,而是受到衰减率的制约,使得累加速度并不很快。结合动量方法以及衰减策略的优点,提出了类似Adam的算法。
但是这个方法也有缺陷,在初始化过程中,second_momentum会由于beta=0.99变得很小,移动的步长会因分母更小而变大。Adam方法使用迭代的次数加以约束,防止出现上述问题。同时,这里也给出了Adam优化方法使用的参数。学习速率的调整。学习速率可以在一定步骤之后折半,或者使用指数、倒数等方法衰减。但是Adam方法已经有了步长逐渐变少的调整方法,学习速率缩减策略不必与Adam配合使用。
二阶优化策略。这个公式目前看不懂,等到数学功底更强一点的时候再回头看。
课程中提到的二阶函数优化策略,同样由于数学式子比较猛,没看懂。大概意思是内存容量不足,海森矩阵是个n*n的矩阵,存不下来。于是用了下面的这种拟合策略。模型集成方法是一种将多个独立训练的模型,加起来进行平均的策略。这种策略能够稳定提升两个百分点左右的效果,用来提高模型的泛化能力。
使用随机dropout方法提高数据和模型的全局通用性能。之前提到的,什么是正则化,指的大概是这种能够让模型可以不那么拟合非常过分的、即使少一些地方、改变模型的部分选择条件,也能够继续适用之前的学习成果。这应该就是正则化的一种通用思维模式吧,简而言之,就是防止过拟合。
另外,课程中提到了,当使用dropout的时候,会按照概率p随机剔除掉一些神经元,这在卷积神经网络中体现在随机删除某个通道,而在全连接神经网络中就会体现为随机置某些神经元为0。为了补偿这种概率上的损失,在测试的时候,将计算结果乘以概率p,表示为其随机剔除之后的数学期望值。
其他的正则化方法,比如在损失函数计算的时候,加上所有权重的平方和、权重的绝对值和,以及二者的线性组合方法;或者是对于某张图像进行随机采样,并做图像旋转、翻转等操作,都是一些比较标准的正则化方法,可以有效减少模型对训练数据的过拟合情况。也可以对图像对比度、PCA主成分分析的时候加上一些随机扰动,在不改变数据总体含义的情况下,防止过拟合的情况出现。
DropOut方法有一种变体形式,是dropout connect,随机将一些连接舍弃掉,即随机的将某些权重w赋值为0。迁移学习。迁移学习这件事情听起来很酷,但是按照课程中提到的,当已经有现成训练好的神经网络之后,例如训练好的VGG卷积神经网络,冰冻前几层卷积层,并且修改最后的输出层数,重新训练最后全连接层 的参数即可。这是一种很好的利用已有神经网络,迁移到小数据集时候的做法。
当数据集不是那么小的时候,使用微调方法修改全部的学习参数,但是仅仅采用原始学习率的十分之一,这就会让过强的泛化能力集中到比较中等的自己的数据集上来了。
当已训练好的模型与待迁移的数据模型比较相似时,可以使用上述方法进行微调。但是两者有较大差别的时候,小数据集很难做到数据迁移,而大的数据集则需要更多的训练。迁移学习这件事情还是比较常见的。应该尽可能多的使用cuDNN对神经网络代码进行加速,以及尽量多的利用GPU的高速运算能力。
Tensorflow, Pytorch, Caffe. Caffe从UC Berkeley进化到Facebook的Caffe2,从NYU/Facebook的Torch进化到Facebook的Pytorch,从U Montreal的Theano进化到Google的Tensorflow,框架发展的速度很快。
有一个临时的想法。既然人的记忆过程是遵循艾宾浩斯遗忘曲线的,神经网络学习过程中,每次喂给他的小数据集称作一个批次。每次喂给他的批次,是否可以通过人为使用遵循艾宾浩斯遗忘曲线的方式进行喂送呢。以在学习某个新批次的特征图过程时候,复习过去的特征图。也就是人为设计一个新的dataloader。我觉得是可行的。准备试一试。
临时的想法。在介绍GooleNet的时候,看到整段神经网络分为三段,前段和中段有一个输出,并产生反向传播的梯度。这种想法蛮有趣,因为之前学习的时候有讲过可能会出现神经网络传播过程中出现的梯度消失问题,这种问题可能会随着深度的逐步加深,而越发明显的出现在神经网络的前端部分。这种感觉类似加油站,开车回老家经过很远的路程,如果中间不加油就很难传播回到老家的地方了。值得思索。
临时的想法。残差神经网络的一个重要之处在于他证明了通过适当的设计模型,更深的神经网络可以导致更好的训练结果。这就为后面继续使用更深的神经网络提供了信念支持。当训练的数据不只是方形数据,比如之前图像的三维数据的时候,卷积方式也不是之前所用的方形卷积核;训练的数据变成了一维数据,或者两维三维数据,但是这些数据在空间上面没有相关性,也就是说他们不是在立体世界中有对应关系的时候,可以采用其他的一维或者对应维度的卷积方法,以达到同样提供残差训练方式的效果。
LeNet是最早成功应用卷积神经网络识别图像的网络模型,模型简单,仅包含卷积层、池化层和全连接层。在手写数字的识别中得到了成功的运用。
2012年AlexNet横空出世,使用深度卷积神经网络模型大杀四方。终于看明白AlexNet网络中上下两层的图片是什么意思了。早期用于训练的计算机容量不足,并且参数的数量巨大,不得不将神经网络的训练过程分布到两个显卡上面。另一个解决我疑惑的地方是,确实两个GPU之间,在某些卷积层中并不进行相互通信。只用得到最初的一半特征,在GPU上面进行训练。但是仍然有疑问,AlexNet在中间部分层里面,GPU之间是有相互通信的,他们是如何进行通信的?以及神经网络的并行训练,底层细节是怎么样的,目前也不太清楚。
VGG神经网络模型在2014年提出,并且取得了不错的好成绩。这里的一个重要思想是堆叠更小的卷积核,以实现代替更大卷积核的效果。堆叠可以代替大核的原理是,重叠导致每次层数上升时候,都会将边缘的四个位置区域的细节体现出来,因此这种方法是可以解释得到的。拥有更少的参数,并且获得了更深的神经网络。是一个不错的提升方案,但是内存占用、参数数量还是太多了。这就导致每次训练过程中,很难一批次训练更多的输入图像,因为需要保存的内存中参数占的位置太多,不够放的。VGG网络还发现局部响应归一化没什么用,就给删掉了。总算搞明白GoogleNet里面的Inception是什么原理了。他虽然分叉了,但是通过padding填充,使得多种卷积核卷积得到的特征图是相同维度的,这样就可以将多个维度的特征图结合起来了,这是很多年的疑惑了。另一个疑惑也解开了,为什么会使用各种1×1的卷积核,这样做的目的是在大面积卷积之前,降低输入图像的深度,也就是使用1×1卷积核的数量变为输入图像深度的一半;卷积运算结束之后,又可以通过1×1的卷积核,恢复到更深的深度上。这种方法被称为“瓶颈层”,很有趣的设定。再有一个被解开的疑问,就是为什么会有多个输出,这件事情已经在上文中解释过了,所以不再赘述。
GooogleNet真的有很多值得好好考虑的东西,他甚至还有一条,使用Inception的各种卷积核之间,这件事情是可以并行的。计算性能属实是一个值得研究的问题,将计算的各个步骤设计成为可以并行计算的步骤,会是一个提高计算速度的方法。
ResNet残差神经网络(2015年)的讲解更是让我多年的困惑得以解决。残差,残差是啥意思。残差是说每一层的输入,距离这个网络真正学习完东西之后,对应的输出层,之间的差值。直觉上来说,不再需要训练各个层的实际数值,只需要训练这个delta差值就可以了。从未想过会有这样一种网络,看来还要多多开阔脑筋。ResNet同样用到瓶颈层,以降低训练时候所需的参数。
瓶颈层的概念源自于Nin网络。许多工作也在向宽度神经网络延伸。随机深度模型,是一种基于全局整合的神经网络模型结构,他会随机选择一段深度中的网络参数进行训练。分形神经网络架构也是为了降低深度,来提高梯度反向传播时候的效率。密连接神经网络的设计初衷,也是为了提高网络层与层之间的紧密关系,方便梯度顺利传播。
在残差神经网络训练的过程中,误差函数被加上了L2正则化项。这件事情在第一次学的时候没有意识到,等到下一次将RNN复习的时候才发现的。L2正则化项是给误差函数加上了一个数值,这个数值是所有神经网络中的参数的平方和。为了最小化误差函数,会让参数尽可能的变小,所以也为残差神经网络提供了一中直入直出的模型概念。他会迫使神经网络放弃那些没什么用的层,也就是让这些冗余层的参数值趋于0。
残差神经网络。由于神经网络中的输出是两部分的加和,分别是卷积前的输入和卷积之后得到的残差,因此在反向传播的过程中,从上游传下来的梯度,可以直接被传递给输入层。在一定程度上减少了梯度消失的可能性。
VGG或者GoogleNet神经网络,放弃了最后的大量全连接层神经网络参数,而选择采用更精巧的设计,以保持网络深度。他们选择的是在末尾使用全局池化的方法,而非大量参数的全连接层。
RNN循环神经网络。循环神经网络不采用每个时间片计算得到的分数最高的类别作为下一层的输入,而是通过采样(Sample)的方法进行选择。他似乎没有说采样是如何运算的,讲到的是使用概率的方法进行采样。我的理解是得分越高,被选中的概率越大;得分低同样也有机会被选择作为下一层神经元的输入。
VGG设置的先收敛11层网络再逐步提升网络层数的设计,以及GoogleNet的底层神经网络反馈层,都是在批量正则化(批量标准化)这种方法大面积使用之前设计的。在有了Batch Normalization之后,这些方法就逐步不用了。
RNN神经网络可以用于处理一对多,多对多,多对一,之类的不同数目变量的问题,比如文本翻译,图片描述等任务。由于语料库可能会相当的庞大,并且随着时间序列的增长,需要反向传导的路径也就更长,所以使用稠密矩阵会让运算过程非常缓慢,在RNN中倾向于使用One-Hot向量的方式。One-Hot怎么翻译我不清楚,只是知道他的意思是,一个行或者列向量中只有一个位置是1,而其他位置都是0,是1的位置唯一对应了语料库中的一个元素,可能是某个单词或者是某个字符,或者是某个位置,或者是其他某种编码方式得到的内容。
在RNN神经网络学习一个长的语料库时候,为了防止一次迭代时间过长,他选择了一种截断训练的方式。截断(Truncated)训练意味着每隔一段距离进行一次反向传播。根据研究显示,在学习过程中,一部分循环神经网络中的部分神经元节点,会用来专门学习某种特定的结构,在某些结构之中呈现出被激活的状态,在其他不关心的部分中,就会被暂时关闭。
如何控制变长的输入或者输出呢?答案是在语料库里面设置开始标志和结束标志,当预测到了结束标志的时候,就会停止这个预测的过程了。
循环神经网络可以通过设计特定的结构查看在某个时间段内的注意力放在了哪些地方。注意力机制分成了两种,一种是软注意力机制,它采用加权和的方式,查看各个地方的注意力的总和;另一种是硬注意力机制,这强制在图像中只能有一个被注意的点。这一段其实我有点没太看明白,PPT上面每一步都在做两件事情,这两件事情是如何去做的。可能以后还会来读一下这篇提到的论文吧,看看具体是如何实现的。
循环神经网络也可以增加循环的深度,这里的意思是提供更多的隐藏单元层,让每一个时间片内都可以传播更多次。但是这样做只需要堆叠三到四次就算挺深的了,不用做更多次的堆叠。
Vanilla RNN网络有一个缺点,他在循环神经网络层数过深的时候,每一次传回来的梯度都要包括同样的权重矩阵W,当W进行多次累乘的时候,要么是梯度爆炸,要么是梯度消失,网络很难受。一种解决方法是,传播回来的梯度如果超过阈值就进行缩放,但是这样太暴力了,所以进化成了LSTM,长短期记忆神经网络,拥有ifog(input,forget,output,gate)四个不同的中间元,前三个都使用了sigmod作为非线性函数,用来归到0和1之间,最后一个是tanh函数,用来归到-1和1之间。
GRU框架(Gated recurrent unit),因为讲的不是很仔细,所以我的理解也不是十分深入。我的直观感受是,他使用了另外的一种隐藏状态神经元的处理方法, 让传播过程和组合过程更加复杂一些,以期求得更好的网络表现结果。
边栏推荐
- docker部署完mysql无法连接
- System basics - study notes (some command records)
- The size of the screen adaptation
- Detailed explanation of ten solutions across domains (summary)
- Passing parameters in multiple threads
- NACOS配置中心设置配置文件
- Wireshark packet capture and common filtering methods
- 干货!教您使用工业树莓派结合CODESYS配置EtherCAT主站
- VRRP overview and experiment
- ES2020新特性
猜你喜欢
Mina断线重连
numpy.random使用文档
BIO,NIO,AIO实践学习笔记(便于理解理论)
docker部署完mysql无法连接
By solving these three problems, the operation and maintenance efficiency will exceed 90% of the hospital
Operation and maintenance engineer, come and pick up the wool
GetEnumerator method and MoveNext and Reset methods in Unity
sql server duplicate values are counted after
干货!教您使用工业树莓派结合CODESYS配置EtherCAT主站
BIO, NIO, AIO practical study notes (easy to understand theory)
随机推荐
程序员应该这样理解I/O
DevOps - Understanding Learning
numpy.random使用文档
Alibaba Cloud Video on Demand
LeetCode practice and self-comprehension record (1)
wc, grep, tar, vi/vim
What?CDN cache acceleration only works for accelerating static content?
产品学习资料
docker部署完mysql无法连接
D46_Force applied to rigid body
单片机期末复习大题
The size of the screen adaptation
Chengyun Technology was invited to attend the 2022 Alibaba Cloud Partner Conference and won the "Gathering Strength and Going Far" Award
Operation and maintenance engineer, come and pick up the wool
摆脱极域软件的限制
初识网页与浏览器
ev加密视频转换成MP4格式,亲测可用
VLAN介绍与实验
[ingress]-ingress exposes services using tcp port
浏览器兼容汇总