深度学习理论知识
文章目录
写在前面
老师要求我赶紧入门机器学习,从CS231n开始,我将在这里放一些学习纪录,方便参考。之后更高阶的东西将在本系列第二篇中介绍
CS231n
CS231n bilibili
textbook
深度视觉必学
一些CNN在计算机视觉领域的工作以及一些计算机视觉数据集:link
CSDN上作业实现及讲解
CSDN上笔记
卷积神经网络发展
这里我先把脉络简单罗列一下,之后在第二篇再来详细学习这些经典的工作
- 1998 LeCun
- 2012 Krizhevsky AlexNet
- VGG
- GoogleNet
- ResNet
机器学习分类器
KNN
- distance metric :L1 distance 会随着坐标轴的转动而改变(一般每个数据有明确意义的时候例如员工的年龄,工资等,可以使用L1,我的理解是这种情况下,坐标不太会变?),而L2 distance可以避免这个问题
- 学会将数据集分为训练集、验证集和测试集
- 设置交叉验证集,这种方式将训练集分为多份,循环选择其中一份作为验证集,可以验证哪组参数更加稳定。对小数据集有用,深度学习中不经常使用。
- KNN在图像检测领域不使用:检测时间过长;这种向量距离不太适合应用在图像;KNN的维度灾难
线性分类器
- 线性分类器的偏置项, 给定一个偏好值。
这里有两种解释:第一是几何划分;第二是将线性分类器比作模板匹配 link - 线性分类器中的问题:非线性- 损失函数:这里的解释是将权重系数作为输入参数,来判断哪个 X X X更好。 - SVM Hingeloss,这里 s y i {s}_{y_i} syi指的是训练样本的真实分数,这里的1也可以换成其他值。 如果将损失函数加上平方呢?不同的损失函数为了量化不同的错误到底有多坏。平方以后对及其严重的错误有更好的抑制。
- 正则项,通常使用的有 L2 正则、L1正则、Elastic net正则、Max norm regularization、Dropout……
- Softmax Classifier ( Mltinomial logistic Regression),用的是交叉熵损失。有两种解释:首先是交叉熵解释;其次是概率解释,用极大似然估计来解释。 A nice feature of this view is that we can now also interpret the regularization term R(W) in the full loss function as coming from a Gaussian prior over the weight matrix W, where instead of MLE we are performing the Maximum a posteriori (MAP) estimation. link
- 对比 softmax 与SVM ,前者会使已经正确的分类上面积累更多的概率质量,SVM只关心分类失败的东西。
- 对比这篇和吴恩达讲的SVM,实际上吴恩达讲的SVM正是一种软间隔的SVM。
优化方法
- 求梯度的方法
- 有限差分发(类似于用于梯度验证中的方法) ,速度非常慢
- 使用解析梯度
- 调试测量:用数值梯度验证解析梯度
- 随机梯度下降(这里没有理解之后在来研究吧)
- 对于支持向量机,这里使用的优化方法是梯度下降,在不可导点使用次梯度
- 另外在编程实现梯度计算的时候还是遇到了很大的麻烦,尤其是向量化编程遇到很大的问题,这里有一些推导
图像的特征
用原始像素值输入似乎不太好。同时,可以吧原来线性不可分的特征运用坐标转换转换成线性可分的情况。
两步走策略
- 计算图片的各种特征
- 将不同的特征向量合到一起,得到图像的特征表述,传入分类器。
- 例子:
- 光谱直方图,颜色特征;
- 方向梯度直方图,HOG;
- 词袋bag of words,类似于统计一段话中各个单词出现的次数,首先定义视觉单词字典,然后对图像进行小的随机块采样,对其进行聚类。第二部进行编码,
- 图像特征vs ConvNets
- ConvNets并不需要提前提取特征,而是直接学习图像的特征。
介绍神经网络
梯度反向传播——是链式法则的递归调用
σ ( x ) = 1 1 + e − x \sigma(x)=\dfrac{1}{1+e^{-x}} σ(x)=1+e−x1的对 x x x的导数为: ( 1 − σ ( x ) ) σ ( x ) (1-\sigma(x))\sigma(x) (1−σ(x))σ(x)
- 对于
max gate
被最大值选中的那个的梯度为上游的梯度,没有被选中的项梯度置0; - 对于
mul gate
add gate
正常求导 - 对于分支,gradient add at branches;
- 雅克比矩阵
- 各种各样的激活函数
卷积神经网络
卷积神经网络的历史——一些比较重要的网络
- LeNet-5 (Gradient-based learning applied to document recognition 1998)
- AlexNet (ImageNet Classification with Deep
Convolutional Neural Networks 2012) - ConvNet
卷积神经网络
- 全连接层(fully connected layer) :将三维的图片展开成一维的向量,并用权重系数点乘。例如输入一个 32 × 32 × 3 32\times32\times3 32×32×3的图片,拉成 3072 × 1 3072\times1 3072×1的向量,然后进行 W x \boldsymbol Wx Wx得到 10 × 1 10\times1 10×1的向量。
- 卷积层(Convolution Layer),可以保留空间结构,而不是把它展开成向量,权重系数是一个卷积核,将这个卷积核在图像中滑动。计算的时候可以对应位置直接相乘相加,也可以拉成一个向量,再进行点积运算,他们的结果是相同的。和狭义上的卷积不同,这里的卷积并不需要将卷积核翻转 18 0 ∘ 180^\circ 180∘。我们逐像素的遍历每个像素点,最后 32 × 32 × 3 32\times32\times3 32×32×3变成了 28 × 28 × 1 28\times28\times1 28×28×1的activation maps。当然这里也可以按照其他的步长进行滑动。同时,我们可以使用多个同样大小的卷积核得到多个activation maps。我个人的理解,这里类似于普通神经网络的第二层的操作,同样也是同尺度的复制,然后随机初始化。卷积的输出大小可以用 ( N − F ) / s t r i d e + 1 (N-F)/stride+1 (N−F)/stride+1来求出。当然也可以补零(pad)或者其他方法来扩充边缘的输出 ( N + 2 P − F ) / s t r i d e + 1 (N+2P-F)/stride+1 (N+2P−F)/stride+1,这样可以保持原尺寸输出,在卷积层级联的时候,如果不做pad,尺寸会迅速减小,课程里讲,迅速减小会损失一些信息,只能用很少的值来表示图像。BTW, 1 × 1 1\times1 1×1conv layers make perfect sense.
- ConvNet 是一些卷积层的序列,级联而成。
- 感受野: 5 × 5 5\times5 5×5 filter——> 5 × 5 5\times5 5×5 receptive field;
- 池化层:让生成的表示更小,更容易管理,在深度方向上不做降采样。一般不在池化层pad,直接降采样。实践中常用
2
∗
2
2*2
2∗2的池化核
- 最大池化法, 用的更多,因为最大池化可以用来这个神经元受激活的程度。
- 均值池化
训练卷积神经网络
激活函数
- Sigmoid函数:饱和时将失去梯度,梯度回传时将传回0,梯度梯度消失;其次sgmoid函数是一个非0中心的函数,这样的输出结果传到下游会出问题,当所有的输入x都为正值时,就会把上游传来得梯度符号传下去,这就会导致所有对权重的梯度要么全为正值,要么全为负值;求指数花费很多的计算资源。总是不要用。
- tanh函数:[-1,1],0中心,饱和时同样会让梯度消失。总之也尽量不要用。
- ReLU函数: f ( x ) = m a x ( 0 , x ) f(x)=max(0,x) f(x)=max(0,x),计算成本低,收敛速度快;但不是一个0中心的输出;同时又不对称,当初始化不好的时候,有一部分数据将无法激活函数,所以在初始化时要加一个正偏置。
- Leaky ReLU函数, f ( x ) = m a x ( 0.01 x , x ) f(x)=max(0.01x,x) f(x)=max(0.01x,x),不会挂掉。
- PReLU函数: f ( x ) = m a x ( α x , x ) f(x)=max(\alpha x,x) f(x)=max(αx,x)
- ELU函数:计算时需要计算指数,对比ReLU对噪声有更好的鲁棒性。
- Maxout “Neuron” ; m a x ( w 1 T x + b 1 , w 2 T x + b 2 ) max(w_1^Tx+b_1,w_2^Tx+b_2) max(w1Tx+b1,w2Tx+b2),不会饱和也不会die。
数据处理
- 数据处理归一化。
- 进行零中心处理(减去均值),做一些归一化。进行归一化有助于提升抗扰动性,如下图,归一化后即使进行一定的旋转仍然能够分类。 用于测试的数据也要做同样的操作。
- 数据压缩,PCA(互相关矩阵对角化)以及白化数据,使数据的互相关矩阵为单位阵。用于测试的数据也要做同样的操作。
- 参数初始化,不能0初始化,否则同一层神经元将做同样的事情。小神经网络可以使用的是小数随机初始化,零均值。但是对于更深的神经网络,小数随机初始化(使用tanh激活函数)会使后面的层激活输出标准差减小,这是因为输入的加权和接近于0,导致后面层的输入越来越趋近于0,输出也趋近于0,然后最后梯度也接近于0;如果使用大随机数进行初始化,所有的神经元基本上都会饱和,因此对于大型网络一个比较好的方式是Reasonalbe initialization(Xavier initialization。如图:
但是当使用ReLU时,每次都有一半的神经元被置0,导致方差减半,可以通过如图的方式: - Batch Normalization参考这个是为了将输入调整到一个合适的位置,首先使每一维都单位高斯分布(我也不知道为什么要这样做。但这里好像中心极限定理啊)要计算每一维均值方差,然后规范化。Batch Normalization通常在卷积层之后,非线性层之前(控制饱和的程度)。第二部还要进行缩放: 注意这里的 γ 和 β \gamma 和 \beta γ和β都是学习到的参数,这样做是为了使其更具有灵活性。Note:在测试阶段,均值和方差不会基于batch计算,而是规定一个训练时所用的经验值。Batch Normalization的反向传播
训练
- 首先要确保能够过拟合,要先从小数据集开始,关闭正则项,看对于训练集是否能训练到1.00精度损失降为0。然后拿出所有的训练集,从小正则项开始并尝试一些学习率,损失不下降说明学习率太低,损失NaN了说明学习率太高,一般选在1e-3到1e-5之间。
- 我们如何选择超参数,执行交叉验证,执行几个epoch,先选择一个区间。我们要追踪 权值更新和权值大小的比例,一般0.001左右比较好。==(这里没听懂,到时候remake吧)==反正学习率和正则系数是比较重要的。
优化:优化方法介绍
An overview of gradient descent optimization algorithms
为什么动量真的有效 这个写的太好了
- BGD
- SGD随机梯度下降:当损失函数在某一方向特别敏感而在某一方向不敏感时,会得到之字形的路线,这并不是好事情;同时,SGD很可能会使函数卡在鞍点(出现的概率更大)和局部最小值;另外,随机梯度下降遇到噪声收敛时间长。
- SGD+Momentum:增加了摩擦系数
ρ
\rho
ρ一般取0.9or0.99,添加一个动量
有另一种动量称为Nesterov Momentum为了能够同时计算做出以下改进
- AdaGrad 对梯度进行平方和累加,让后更新时将梯度除以这个累加值,相对的增大小梯度方向的速度,减小大梯度反向的速度。但是随着迭代更新速度越来越慢。可能会困在局部极值点。不经常使用
- RMSProp,这个不错感觉
- Adam算法,在第一步的时候很可能步子太大所以要用无偏估计矫正。这是比较好的一个算法
- 学习率 ,学习率的设置方法是先不用衰减,观察损失曲线。
- 二阶优化,前面的方法都是一阶优化,相当于泰勒展开的一阶导项,二阶导更为准确。这就需要求海森矩阵
- 牛顿步长
缺点是这个计算矩阵乘法太慢 - L-BFGS
- 牛顿步长
提高泛化能力,缓解过拟合
- 模型集成,多个模型结果求平均;使用训练过程出现过得多个模型平均;Polyak averaging
- 正则化
- add term to loss:L2;L1;Elastic net
- Dropout:训练时,每次前向传播,随机将一些神经元激活函数输出置零,一般在全连接层。抑制了神经元之间的相互适应????在测试时,随机屏蔽会导致输出的随机性,我们想要平均这些输出结果。如多次采样测试,平均化,但是仍无法消除随机性。一个好的逼近方法是在测试时不进行屏蔽,而是用dropout概率乘以输出。
- 一个常用的方法:训练时添加一些随机性,测试时抵消掉随机性,例如:batch normalization。
- 数据增强:随机的仿射变换,翻转,随机的裁剪,色彩抖动
- DropConnect
- fractional max pooling
- 随机深度,丢掉一些层
迁移学习 Transfer Learning
当从一个多类任务迁移到一个少类任务时,这里说的方法是冻结前面几层,只修改和训练最后一层。对新的特征不适用
当我们开始一个没有大型数据集的项目时,应该从已经训练好的预训练模型开始,重新初始化一些部分,然后根据自己的训练集调整
深度学习软件
GPU和CPU
- GPU非常适合并行计算,例如:矩阵的乘法
- GPU编程
- CUDA(NVDIA only)困难
- 有一些库:cuBLAS,cuFFT,cuDNN,etc
- OpenCL 类似于CUDA 跨平台,但性能不如CUDA
- CUDA(NVDIA only)困难
- CPU/GPU通信 如何避免从硬盘中读数据成为瓶颈
- 将 所有的数据读到RAM中
- 用SSD替代机械硬盘
- 使用多线程预取数据
- 深度学习框架
- Torch-> PyTorch(Facebook)
- Theano->TensorFlow (google)
- Paddle(Baidu)
- 为什么要选择深度学习框架
- 不用管细节
- numpy不能再GPU上运行,必须自己计算梯度
- TensorFlow,注意numpy到TensorFlow之间的数据传输,CPU和GPU的数据传输,解决考的是将权重从占位符转换为变量。(需要的时候再学吧)
- Pytorch:PyTorch Official Tutorial
- 是一种动态计算图
- 定义了三层抽象; Tensor(张量):类似于numpy但是可以运行再GPU上;Variable(变量):计算图中的节点,存储数据和梯度;module(模块):是一个神经网络层。
- Tensor:这里不需要再使用numpy了;为了在GPU上运行,需要将tensor转换成cuda数据格式
- Variable:是计算图中的一个节点,
可视化理解,卷积神经网络内部的原理
可视化
- first layer 可视化滤波器,每个卷积核可以看做图像,模板匹配,特征提取
- 最后一层,全连接层,
- 可以想着把前面的所有网络当成特征提取,然后得到一个特征向量,最后用于分类,也就是说我们甚至可以用最近相邻来对这些特征向量分类。
- 另一个角度解释:把数据给降维(没理解!!!),传统的数据降维的方法:PCA,t-SNE。
- 中间层,权重层很难被解释,但是激活层具有一定的可解释性
- 输入图像的那个部分影响了分类
- 遮挡试探
- 显著图 ——运用梯度
- guided backprop
- 梯度上升,生成图像,计算对图像的损失,然后上升合成
- 愚弄图像
重构
- 特征重构
- 神经网络纹理合成 gram矩阵
- 风格迁移
Recurrent Neural Networks 递归(循环)神经网络
- Vanilla(一般的) Neural Network :给出单一个输出结果
- Recurrent Neural Networks 可以实现一对多的模型,多对一的模型,多对多的模型
RNN
具有内部隐藏态。(有点像时序电路hhh,这难道是从数电里面获取的灵感???)
可以看到每次循环的过程中,使用的是相同的权重矩阵,当进行梯度计算时,整个模块W的梯度,等于每个循环过程计算的梯度之和。
可以有多对一,多对多,一对多的形式
训练RNN
- 截断反向传播算法,虽然序列可能很长,但是我们只计算子序列的梯度值
- 梯度流
注意力模型
- 硬注意力和软注意力
Long Short Term Memory (LSTM)
用来解决梯度爆炸和梯度消失的问题
image captioning 为图片打上自然语言标签
识别和分割
分类和定位
用两个全连接层,一个分类,一个分割,分割的损失一般用L2或L1损失
- 人的姿态定位
目标检测
- 围绕对象画框并标出类别,与分类和定位不 同,对象识别通常每张图片不值一个目标
- 数据库:PASCAL VOC数据库
- 滑动窗口的方法:将图像切块,对每一块进行分类决策,新增一个background类
- 候选区:建立候选清单,候选区网络找到区域,然后定位。速度快,召回率高
具体的网络
-
R-CNN
- R-CNN
- fast R-CNN
共享了卷积操作,速度瓶颈就是寻找region proposals - faster R-CNN 让网络自身去预测ROI区域
-
前馈模型(detect without proposals)
- YOLO 将图像划分成grid,然后每个图像网格预测
图像分割
- 图像分割的idea( 语义分割)
- sliding window 计算复杂度高
- 全连接层,通过pad保持一样的图像大小,输出每个像素的评分,一次性计算,损失函数是交叉熵损失对每一个像素进行分析。由于卷积保持了同尺寸,使得计算代价太大,解决方法可以先下采样(pooling,strided convolution)然后再上采样
- 上采样的方法
- 去池化:nearest neighbor,
- 去池化:bed of nails(填零),
- 最大 unpooling 还原池化时的位置,其他全部填零
- 卷积转置:输入像素点放在中心,然后以卷积核的权重复制在周围,卷积转置名字的由来,这里写错了,左边那个x应该是z。步长为2的情况类似。
用33 步长为2的卷积核可能会产生棋盘效应,所以可能用44步长为2的卷积核
- 数据集 微软COCO数据集
- 实例分割,是目标检测和图像分割的结合
- mask R-CNN
在faster R-CNN基础上增加了用来判断像素的分支,mask R-CNN 可以添加姿态检测等其他的分支
- mask R-CNN
- 全景分割 Panoptic Segmentation 全景分割
以上的相关网络深入将放到第二部分
生成模型——无监督学习
无监督学习获取数据集成本低
下图是2017年的模型分类
pixelRNN/CNN
VAE
- 自编码器,
- encoder有很多种如:线性+非线性,全连接,relu CNN等
- 为什么学到的特征要降维,因为要找到有意义的特征
- 解码器: 线性+非线性,全连接,relu CNN等
- variational autoencoder 我们想要一个生成数据的概率模型
GAN
看不懂看博客吧
先训练判别器网络,再训练生成器网络
- 网站: the Gan zoo
强化学习
什么是强化学习
马尔科夫决策过程
- MDP就是强化学习的数学表达,强化学习满足马尔科夫性,即:当前状态完全刻画了世界的状态
- 最佳策略:能够最大化奖励总和
- Q值函数,一个轨迹的好坏用来表示,一个状态行动的好坏用Q值来表示
由于不可计算,所以用一个方程来估计状态,用Q-learning
Q-learning
- experience replay
听不懂,看链接吧
policy Gradient
- 强化算法
入土了,自学吧
深度学习硬件
专用硬件有 FPGA和ASIC,ASIC是固定的硬件
由于硬件成本,8位和16位的硬件更多
高效的推断算法
- Pruning 剪枝,对权重进行排序,干掉小的
- weight sharing
权值共享后变得离散
也可以 哈夫曼编码 - 量化
- 低秩分解,SVD
- 二元三元网络
- winograd transformation 卷积的一种等价方式
高效的训练算法
- 并行计算,单线程频率陷入瓶颈
- 将图片切块
- 输出特征映射
- 对全连接层 切成两半
- 参数并行化
- mixed precision with FP16 and FP32
- 模型蒸馏
- tensor core 是一个指令,实现4*4的举证之间的乘法,一个时钟周期完成混合精度的乘法
高效的推断硬件
TPU是一个ASIC
高效的训练硬件
对抗训练by lan
- 现代神经网络输出是输入的分段线性函数,但是由于要乘在一起,所以参数和输出之间是非线性的关系
- 构建对抗样本的方式
其中一种:FGSM
- 很多二次的模型可以很好的抵抗扰动,如RBFs