目录
学期知识总结
第一章 绪论
首先是了解整体知识框架:这个学期主要的深度学习框架如下,分为机器学习、神经网络、概率图模型。
那么有一个问题是:机器学习和深度学习的区别到底在哪里呢?
首先,目的不同,机器学习的主要目的在于分类和回归,在于“表示学习”,而深度学习的主要目的在于通过学习好的特征表示从而达到预测和识别的效果。
换句话说,“机器学习”相当于教会机器如何看书、如何看懂书,而“深度学习”相当于教会机器如何利用看书得到的知识解决特定的问题。
然后学习的内容也不算太相同,从广义概念上讲,机器学习比深度学习的概念要广,深度学习属于机器学习中的一部分;从深度概念上讲,机器学习的方法只是深度学习中的一部分,深度学习除去机器学习中的基础方法外,还需要学习各种精细的“网络”与“算法”。
“神经网络天然不是深度学习,但深度学习天然是神经网络。”
第二章 机器学习
1.机器学习的三要素
(1).模型
线性方法:
广义线性方法:
(2).学习准则
目标:寻找假设空间中的参数,让预测的模型和真实值很好的拟合
·经验风险最小化:找到一组参数,使得训练集上的平均损失最小
·结构风险最小化:参数正则化,限制模型能力,避免过度最小化经验风险(解决过拟合问题)
结构风险 = 经验风险+正则化项
(3).优化算法
提前停止、梯度下降、批量梯度下降、随机梯度下降、小批量梯度下降
2.机器学习常见损失函数有:
第三章 线性模型
1.线性分类模型
·Logistics函数(Softmax函数)
2.Softmax回归
感知器Perceptron、支持向量机SVM用于分类,机器学习已经学过相关的基础知识了。
第四章 前馈网络
1.神经网络
(1)前馈神经网络(全连接神经网络、多层感知器)
前馈神经网络模型一般有四层神经元,分别是输入层、隐藏层、输出层,全连接即相邻两层之间的神经元全部两两连接,整个网络从输入层向输出层单向传输。
·反向传播算法的含义:
第L层的一个神经元的误差项是所有与该神经元相连的第L+1层的神经元的误差项的权重和,然后再乘上该神经元激活函数的梯度。
·使用误差反向传播算法的前馈神经网络训练过程
①前馈计算第一层的净输入和激活值直到最后一层;
②反向传播计算每一层的误差项;
③计算每一层参数的偏导数,并更新参数;
(2)自动梯度计算:
训练两个阶段组成:
①前向传播:计算损失函数
②反向传播:计算参数梯度,使用链式法则计算权重相对于损失函数的梯度
(3)激活函数:
激活函数的性质:
①连续并可导(允许少数点上不可导)的非线性函数
②激活函数及其导函数要尽可能的简单
③激活函数的导函数的值域要在一个合适的区间内
常见激活函数:sigmoid函数,也叫Logistic函数,图像呈一个“s”状。
·梯度消失:
在神经网络的构建过程中,随着网络层数的增加,理论上网络的拟合能力也应该是越来越好的。但是随着网络变深,参数学习更加困难,容易出现梯度消失问题。
由于Sigmoid型函数的饱和性,饱和区的导数更接近于0,误差经过每一层传递都会不断衰减。当网络层数很深时,梯度就会不停衰减,甚至消失,使得整个网络很难训练,这就是所谓的梯度消失问题。
在深度神经网络中,减轻梯度消失问题的方法有很多种,一种简单有效的方式就是使用导数比较大的激活函数,如:ReLU。
由图可以看出,左图是两个函数,右边是两个函数的导数。使用Sigmoid作为激活函数时,它的导数在饱和区域(接近1或-1)非常接近于零。这意味着当误差信号通过多个层传播回输入层时,每一层的梯度都会不断缩小,因为每一层的导数都小于1。随着层数的增加,梯度不断减小,最终可能变得非常小,甚至趋于零。当梯度接近零时,权重更新几乎没有效果,导致网络停止学习。而ReLU激活函数在正区域的导数为1,这意味着它不会导致梯度消失问题。
·死亡ReLU问题
ReLU激活函数可以一定程度上改善梯度消失问题,但是在某些情况下容易出现死亡ReLU问题,使得网络难以训练。
这是由于当x<0时,ReLU函数的输出恒为0。在训练过程中,如果参数在一次不恰当的更新后,某个ReLU神经元在所有训练数据上都不能被激活(即输出为0),那么这个神经元自身参数的梯度永远都会是0,在以后的训练过程中永远都不能被激活。
一种简单有效的优化方式就是将激活函数更换为Leaky ReLU、ELU等ReLU的变种。
·解决方法:
·合适的参数初始化对于避免死亡ReLU问题至关重要,常见的初始化方法包括Xavier初始化、He初始化等,它们有助于保持参数的合理范围,防止参数过小。
·一些变种的ReLU激活函数,如Leaky ReLU和Parametric ReLU(PReLU),引入了小的正斜率,即当输入小于零时,仍然有一定的输出,从而减轻了死亡ReLU问题。
·批量归一化可以在每层的激活函数前进行归一化,有助于避免参数的剧烈变化。
·残差连接可以在网络中引入跨层的信息传递,有助于解决梯度传播问题。
将ReLU激活函数的变种Leaky ReLU、ELU和relu进行比较,得到以下结果:
从图中可以看出,当x<0时,ReLU的导数(红线)为0,而其他两个函数则均不为0,且当x>0时,三种函数的导数与函数本身结果相同。因此可以很好地解决死亡ReLU问题。
第五章 卷积神经网络
1.卷积
(1)为什么要使用卷积网络?
·全连接神经网络的缺点是什么?
①参数过多,效率低下,训练困难,会导致过拟合;
②将图像展开为向量,会丢失空间信息
③局部不变形特征:自然图像中的图像都具有局部不变性特征(尺度缩放、平移、旋转等操作不影响其语义信息),而全连接前馈网络很难提取这些局部不变特征。
但卷积网络可以很好地解决这些问题。
(2)卷积
一维卷积常用于信号处理中,用于计算信号的延迟累积。
二维卷积:图像以二维矩阵的形式输入到神经网络中,因此需要二维卷积。
·互相关和卷积的区别仅仅在于卷积核是否进行翻转,互相关也可以称为不翻转卷积。
·卷积常用于特征提取,卷积结果:特征图/特征映射,图像与卷积核加权累加得到卷积后的特征图。
·填充:在输入周围添加0(零填充)的作用:减少边缘信息丢失,输入输出图像尺寸一致。
2.卷积的网络结构
(1)多个卷积层:卷积层分别提取不同的特征
多输出通道,即计算出每条单输出通道的结果后进行向量加。
①卷积层1:提取初级特征,如边、角、线等;
②卷积层2:初级特征组合得到中级特征,如形状等;
③卷积层3:中级特征组合得到高级特征,如语义等。
高级特征:通常具有一定的语义特征,比如人脸、车轮、房屋结构等
(2)池化层:压缩特征,降低维度
①选择窗口大小(通常是2到3)
②选择间隔(通常是2)
③使用窗口遍历特征图
④每个窗口取最大值
(3)激活层:通常使用ReLUs线性修正单元作为激活函数(当x小于0时,函数始终为0,当x大于0时,x与函数的值成正比,即将所有负数变成0),对数值进行微调,防止梯度消失
(4)多次结合反复使用卷积、激活、池化后,最终使用全连接层,将三个特征图合并在一起进行比较。计算最大向量的平均数以后确定图片的分类。
卷积整体趋向于更小的卷积核和更深的结构。
3.卷积的典型网络
(1)CNN的反向传播算法
(2)转置卷积:将低维特征映射到高维特征
(3)空洞卷积:也称为膨胀卷积,通过给卷积核插入“空洞”来变相地增加其大小
如何增加输出单元的感受野?
①增加卷积核的大小
②增加层数来实现
③在卷积之前进行汇聚操作
4.lenet-5
5.AlexNet
6.残差网络
4.卷积网络的应用
物体检测、图像分割、图像标题的生成、图像风格变换、图像的生成、自动驾驶、对抗样本
第六章 循环神经网络
1.简单循环网络(SRN)
·前馈网路存在的问题:
连接在层与层之间,每层节点间无连接。输入和输出的维数固定,不能任意改变,无法处理时序数据,即每次输入都是独立的,无法和前一次输入联系起来。
·序列数据:时间序列、符号序列、生物序列
·如何给网络增加记忆能力:
1.延时神经网络
2.由外部输入的非线性自回归模型
3.循环神经网络
长程依赖问题:
2.随时间反向传播算法
3.长短期记忆神经网络(LSTM)
但LSTM也不能完全解决长程依赖问题,因此叫做长-短期神经网络。
4.门控线性单元(GRU)
比起LSTM,GRU使用更新门和重置门,作用和那三个门也有点像。
第七章优化问题 可以直接看之前的内容。
心得体会
忘了是上课还是实验课的时候老师提过,“深度学习让我们更了解代码,刚开始学python的时候我们接触lenet和卷积都不知道应该如何下手。”
当时听到这段话真是很有感触,还记得学习python的最后两节实验课内容是分别需要用pytorch实现手写数字的分类和tensorflow实验Cifar10数据集的分类。手写数字的分类还能在网上找到参考内容,但tensorflow那个好像当时全班几乎都全军覆没——全没做出来。找手写数字分类程序的时候我还在想:应该如何通过只能输出“‘Li Ming’,‘swim’”的小小输入框实现数字的分类呢?然后跑代码的时候就看到输入框就像中了病毒一样一直在滚数据,不知道这个实验结果是对是错,但实在是被吓了一跳。
再到学习机器学习实验时,第一个实验任务是使用二维绘制图像实现分类,当时大家都不会做,觉得很难。毕竟机器学习实验前的实验课是python,那会儿大家都还照着课本照猫画虎呢,机器学习一下子就没有可以参考的代码,无从下手了。
好不容易学完了机器学习,一到深度学习的实验课我更懵了,还把实验报告发给朋友吐槽来着:机器学习好歹还能再网上找个代码,直接一抄,写点分析就解决了。深度学习连题目都看不懂,网上找到的代码更是各走各的一块一块的,连一个完整代码都没有。究竟要怎么写?
直到前几天学习大数据,老师让我们找出之前学习过的机器学习的代码来,我再看机器学习的代码,没想到印象里自己绞尽脑汁写出的心得体会居然那么简陋,就那么一丁点。要是现在的我来写实验报告,一定是把里面用到的整体思想、各函数的功能、该程序的特点、有没有什么缺陷和不足。都仔仔细细地分析一遍。
这样回忆一遍,比起当初对代码的一知半解,现在虽然还是不会写,但至少有耐心把代码看明白了——也确实是进步,这说明大学三年来也没白学。
虽然以后的我再看现在写过的实验报告,还是会心想:当初的我怎么就写了这么点?不把实验报告写个两三天能叫一篇好实验报告吗?敷衍!实在是敷衍!
但是至少现在的我能自己把程序修改以后好好跑出来,能好好看错误了,能对着数值分布图把lstm的结构看一看理解理解,能对着程序说出自己的理解和感悟来,已经算是进步了。
另一点进步则是:敢于自己看代码了。之前我对于代码总有种像英语一样的恐惧心理,乍一看上去就觉得自己是不会的、看不懂的。但自从开始写csdn的作业以后(虽然只写了几次,但也是我进步的开始……),我开始试着不去复制其他同学已经写完的作业,而是凭着自己的理解、自己查找的资料,一个字一个字地写,一句一句地总结。
在写作业12的时候我查找到了很多英文文献,并且自己动脑筋,将代码生成的模型修改成了颜色更好看的图片,并且在作业13给每个动图添加了一个新算法运行的轨迹,也就是将5个算法轨迹图改成了6个。而且,敢于敲代码这一点也应用在了博弈论上,我博弈论两个大作业都没有抄网上可参考的代码,而是自己敲自己写的,得分也蛮不错的,挺高的。
虽然这个学习听课时间不算长,期末考试大概也不会成绩很好,但我也很满足了。成绩易得,进步难求,相信在学习深度学习的这段过程中我的收获足以受用至少十年了。