About
- homepage;
- 2017 lecture video;
- 中文笔记
- 课程相关时间安排,课件,参考资料,作业详见homepage链接,以最新版为主;
- 官方的assignments和notes做得非常好,强烈推荐学习和反复观看;
- 时间原因,学习19版的时候恰好2020版春季课程将要开始,这一版换了team,里面加了不少新的research介绍,尤其是非监督,自监督之类的,因此会加入一下2020版的内容;
- 个人比较喜欢Justin Johnson的讲课风格和深度,因此配合他在UMICH (University of Michigan) 的 EECS498: Deep Learning for Computer Vision课一起看,可以相互补充(和CS231N有很大重叠, 但也些不同);
Lecture1. Introduction
Related courses in Stanford:
CS131: Computer Vision: Foundations and Applications
CS231a: Computer Vision, from 3D Reconstruction to Recognition
CS 224n: Natural Language Processing with Deep Learning
CS 230: Deep Learning
CS231n: Convolutional Neural Networks for Visual Recognition
Andrew Ng的CS229虽然不在列表中,但个人觉得也值得一看,毕竟也属于经典ML课程。
A Brief history of Computer Vision and CS 231n:
- 从史前生物产生视觉开始,到后面的人类对于视觉的研究:相机,生物学研究,以及陆续地对于计算机视觉/机器视觉的系统研究,在社会各个领域结合产生的特定任务的建模设计等工作,这里再一次提到了David Marr的《vision》一书对整个计算机视觉领域的奠基于推动作用。
- 介绍卷积神经网络CNN对计算视觉的推动作用,简介了CNN的历史以及在各个视觉有关问题上的强大作用。
- 推荐课本教材:《Deep Learning》 by Goodfellow, Bengio, and Courville.
Lecture2. Image Classification
material: 主讲人Justin Johnson编写的python numpy tutorial,个人觉得是个很不错的教程。
官方的notes1–image classification和notes2-linear classification是对本次课的一个总结,补充和拓展(其中第二个笔记大部分是下次课的内容,放在这里我猜可能是预习吧),可以说写得十分详细了,而且常温常新。
- 首先阐述对于计算机而言,为什么分类图片很难(光照,视点,类似纹理背景等);
- 介绍了一些传统方法对此的努力,但是这些方法效果不好,具有单一性,鲁棒性和generalization都很差;
- 引入data-drive approcah, 也就是收集数据,训练,预测三段式方法;
- 介绍Nearest Neighbours分类器,并阐释不同K值和distance metric选取的不同performance(L1和L2的选取与坐标轴旋转对数据引起的改变);
- 介绍交叉验证的作用,以及说明K-NN的维度诅咒(处理大数据吃力)和 predict速度慢的缺陷(需要一个个和训练集图片计算distance);
- 引入线性分类器,权重矩阵W,偏置矩阵b,并在第二个官网的notes中详细地介绍了SVM和Softmax两种loss衡量方式;
官网推荐的一篇阅读review A Few Useful Things to Konw About Machine Learnig,写于2012年,但是仍不过时,可以一读。文中写到的12个"folk wisdom":
- Learning = representation+evaluation+optimization;
- It’s generalization that counts;
- Data alone is not alone;
- Overfitting has many faces;
- Intuition falis in high dimensions;
- Theoretical guarantees are not what they seem;
- Feature engineering is the key;
- More data beats a cleverer algorithm;
- Learn many models, not just one;
- Simplicity does not imply accuracy;
- Representable does not imply learnable;
- Gneralization does not imply causation;
Lecture3. Loss Functions and Optimization
官方笔记:linear classification, optimization有更为详细的课程内容解释和总结;
其中linear classification笔记中有个交互式demo,主要用来体会SVM和Softmax来训练线性分类器的过程,包括调节正则项,学习率等超参数;
上节课引入linear classification,现在需要loss function定量分类器对分类结果与training data的GT之间的差异,需要一些optimization方式去有效寻找模型参数可以最小化loss;
介绍两种loss衡量metric: Multiclass SVM和Softmax,并认为两种方式在训练分类器时差异不会很大,SVM是为了拉大正确的score与非正确score之间的差值到设定的margin,所以分的越差惩罚越重,分的越好基本上不再去多费精力,而Softmax则不断将正确的probability拉的更高,错误的拉的更低;
由于满足loss function的权重矩阵W有无数个(针对linear classification),之间可成正比例关系,因此需要引入正则项让模型自己适应数据,得到generalization比较高的模型参数;
针对优化参数方法,通过随机搜索过渡到梯度下降gradient descent,在官方笔记中更加仔细地介绍了针对实际工程应用的梯度下降法(数值梯度,分析梯度等),满足计算性能之间的trade-off
最后针对图像特征,介绍了color histogram, HoG (Histogram of Oriented Gradients), Bag of Words等方法。将feature映射到更高维的空间,使分类问题变得容易,这也是CNN的一大作用,从而引入下一节主题;
在这里插一下sigmoid, softmax和cross entropy之间的联系,我们一般说的分类是单标签多分类,也就是说一张图片只会有一个标签,标签与标签之间是互斥的,而softmax计算的类别概率是类别互斥的,因为和为1,而针对多标签分类,也就是说一张图片可能有多个标签存在,标签之间不是非此即彼的,类别不互斥,此时用sigmoid激活函数,因为sigmoid是互相独立的计算,只判断此神经元是否属于该位置对应的类别,所以在计算多分类交叉熵时是每个神经元按照二分类交叉熵算然后求和平均。参考blog1, blog2.
梯度下降算法理解:
假设一个模型拟合表达式为:,其中一般都是矩阵,对于一个输入,我们希望计算的值与真实函数尽可能得接近,直接照着真实函数分布去“依葫芦画瓢”比较困难,所以来最小化他们之间得残差来搜索拟合函数的参数,假设我们用平方损失函数:,现在我们对每一个超参数求偏导,得到关于它得梯度(函数上升最快得方向),由于我们是想找最小值,所以要反方向走(实际可以在损失函数前加个符号,转为找最大值):
根据梯度,加上步长learning rate, 对参数进行更新:
通过不断地迭代,使函数往最小值逼近。在深度学习实际应用时,训练的数据样本可能很大,一次迭代要计算所有的样本会非常耗时,所以利用SGD方法,抽取一些数据作为batch,认为可以近似代表整体样本的分布,每次换不同的样本去学习,也可以得到近似的解(但这也只是工程近似)。深度学习中的模型拟合函数是非常庞大而又复杂的,结合BP加梯度下降可以使函数收敛到局部最小值。
Lecture4. Introduction to Neural Networks
这一节官方指定阅读的笔记为:optimization-2-bp, linear-classifier-bp; 此外还给了一些推荐的阅读材料,以供选择,其中包括一份向量,矩阵,BP的导数推导示意笔记,Yan leCun在1998年写的名为“Efficient BackProp"的论文,两篇解释BP的博客(1, 2)和MIT Artificial Intelligence公开课中有关BP讲解的课程视频,此外还有一篇ML中automatic differentiation的survey. 个人感觉如果对微积分和线性代数比较熟悉的话,看一下官方指定阅读的两篇笔记就差不多了,主要是为了深入理解BP,有时间的话也强烈推荐那篇推荐阅读的博客2,是Micahel Nielsen写的《nndl》教材中的一节,在入门DL的时候我就是看的这本书,十分经典耐读。BP的使用大多是对矩阵或者说tensor张量进行的,如果对矩阵求导不熟悉,或者想系统的学习巩固下,可以移步矩阵求导术-上和矩阵求导术-下,上-篇写的是标量对矩阵的求导方法,下-篇写的是矩阵对矩阵的求导方法,都是通过标量上全微分表达式来进行推广和计算的:
“导数与微分的联系是计算的枢纽,标量对矩阵的导数与微分的联系是,先对求微分,再使用迹技巧可求得导数,特别地,标量对向量的导数与微分的联系是;矩阵对矩阵的导数与微分的联系是,先对求微分,再使用向量化的技巧可求得导数,特别地,向量对向量的导数与微分的联系是。”(其中,分表代表标量,向量和矩阵)
我想对矩阵的求导可能是本节课的一个小重点以及后面进行DL理论学习的基石。
该课延续上一讲提出的linear classifier,介绍了神经元的概念,历史和应用,引入fully-connected network;
指出如果层数加多,再加上激活函数,损失函数等,网络所代表的拟合函数表达式将非常庞大而复杂,采用梯度下降的方式训练时,推出分析表达式非常不现实和实际(如果想要零时改变一个函数就要重新推算);
由于我们不关心函数梯度具体表达式,我们只是想通过计算梯度值来更新参数,所以采用computation graph的方式来逆推local gradient,forward + backpropagation形成一个完美体系(upstream gradient, local gradient);
在此课之前我推导过全连接和卷积神经网络的BP,就是当成链式法则”chain rules“来对待,而这次课给我了一个数学公式之外一个更加形象化理解,也即是”computation graph“和”门电路“:
Backpropagation can thus be thought of as gates communicating to each other (through the gradient signal) whether they want their outputs to increase or decrease (and how strongly), so as to make the final output value higher.
而网络通过一系列”add gate", “mul gate”, “max gate"等"gate"一步步垒成复杂的函数,而且部分组织可以组合成一个特殊的"gate”,也可以被分解成其他简易的"gate",方便我们进行梯度计算(注意variable分流forward之后bp要加起来+=)。通过简单的example可以了解到"gate" input和output之间的梯度分配关系,非常形象生动。
Lecture 5. Convolutional Neural Networks
该节课的官方笔记对卷积神经网络CNN来龙去脉和计算都介绍得很详细,同时也对每个层(Conv layer, pooling layer, fc layer)都做了全面的回顾和介绍。
另有一篇博客解释卷积神经网络中”卷积“一词和信号与系统中得卷积操作的联系,知乎也有个理解卷积的回答,看完之后可以加深对卷积核的理解。
- 首先介绍感知机,神经元和CNN的历史;
- 简介一个卷积神经网络的结构以及直觉上层级学习的内容和特征;
- 大部分时间讲解卷积的计算过程;
Assignment 1
reference:
参考培训机构深度之眼的cs231n-camp的文档
具体过程和结果参见这个repository
注意:一开始运行knn.ipynb
文件时可能显示scipy.misc.imread
缺失,这是因为新版的scipy
包去掉了imread
这个module,解决方法是可以在data_utils.py
中的from scipy.misc import imread
改为from imageio import imread
。
Lecture 6. Deep Learning Hardware and Software
讲义中包含的官方制作的两大深度学习框架(Pytorch, TensorFlow)的tutorial,我把它们直接下载下来放在GitHub便于观看。
2017版中该课在train neural network之后,19年改为之前,由于两年间框架格局也在发生改变,所以以最新版slides为主(17版主推TensorFlow,也花了一大半时间介绍TF,19版偏向于PyTorch)。
结合前面的tutorial一起看,可以当作非常好的入门学习材料。
Lecture 7–8. Training Neural Networks I & II
这两节课硬货非常非常的多,很多东西都值得深究。课程讲的不是很清楚,因为内容多,所以需要线下仔细看看笔记。笔记主要分为三个部分:
1.neural fc network model: 介绍来自脑启发的神经元neuron,常用的激活函数(sigmoid, tanh, ReLU, Leaky ReLU, Maxout, ELU, SELU),全连接神经网络的一些结构问题,比如是否可以拟合任意连续函数,多少层足够,多大足够,以及表征能力和前向计算等。
Sigmoid在训练时除了会有梯度消失的情况外还有输出不是0均值(zero-centered)的情况:这会导致后层的神经元的输入是非0均值的信号,这会对梯度产生影响。以 为例, 假设输入均为正数(或负数),那么对的导数(sigmoid的导数总是正的)总是正数(或负数),这样在反向传播过程中要么都往正方向更新,要么都往负方向更新,导致有一种捆绑效果,使得收敛缓慢。
“What neuron type should I use?” Use the ReLU non-linearity, be careful with your learning rates and possibly monitor the fraction of “dead” units in a network. If this concerns you, give Leaky ReLU or Maxout a try. Never use sigmoid. Try tanh, but expect it to work worse than ReLU/Maxout.
larger networks will always work better than smaller networks, but their higher model capacity must be appropriately addressed with stronger regularization (such as higher weight decay), or they might overfit. We will see more forms of regularization (especially dropout) in later sections.
2020.6更新:
最近Yolo v4使用了Mish激活函数,2020年新版CS231N也加入了Swish激活函数,后续可以实验看是否高于ReLU,但是可能要注意权重初始化的问题。
Swish:
Mish:
以及更多激活函数对比见此。
2.one time setup: 介绍数据预处理(先减去mean image,或者是mean RGB vector中心化,然后除以std进行normalization;进行PCA降维数据,进行decorrelated或者利用whitening得到各向同性的Gaussian blob;一般利用CNN训练时不需要进行太复杂的数据预处理),权重初始化(非常重要和经验化的一点,不要以零对权重进行初始化,而是随机高斯分布采样初始化,“Xavier” initialization, 并且进行w = np.random.randn(n) * sqrt(1/n)
对方差进行校准,为的是让输出的方差与输入的相同,后来何恺明的研究中表明,采用ReLU激活函数,初始化为w = np.random.randn(n) * sqrt(2.0/n)
见论文"Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification",在conv中n是kernel _size^2 * input _channels),batch normalization(直接作为一层插入FC/CNN与激活函数层之间,把batch数据进行标准高斯分布化,当然后面还有一个超参的逆向高斯化,主要是为了让网络自己去判断这哪种对自己适合是一种启发式处理),正则化(L1,L2正则化,一般L2更好些;Max norm constraints设置权重边界;Dropout进行组合训练或者是认为进行数据增强)和损失函数(classification, regression (最好不要硬来,因为没有规律,试着往分类转化), structured prediction)等问题。
权重初始化中还有一个transfer learning技巧,利用ImageNet的预训练模型,再根据自己的数据进行层的选择性finetune. 不过目前的研究来看,在object detection领域,自训练似乎比预训练更好(数据够多,卡够多的情况下,数据少还是老老实实用预训练吧),参照恺明大神的Rethinking ImageNet Pre-training。
Dropout: Forces the network to have a redundant representation; Prevents co-adaptation of features
对Dropout起防过拟合作用的解释–组合派和噪声派;对Inverted Dropout中神经元进行Dropout之后为何需要对余下工作的神经元进行rescale的一个解释–乘再除确保下一层输出期望不变
(除以p是为了保证训练和测试时输入给下一层的期望是一样的,那些失活的神经元损失的值会通过其他神经元补回来,这样就等于加强了某些神经元的鲁棒性,如果不除的话等于是随机挑选神经元训练,这样可能达不到预期的增强效果。)
Data Augmentation: translation, rotation, stretching(拉伸), shearing(修剪), lens distortions(镜头畸变), color jitter (颜色抖动)等等。
Batch Normalization(类似于”白化“,实现数据独立同分布,但是BN并没有实现独立同分布,仅仅是压缩再变换): 在前向传播时,分两种情况进行讨论:如果是在train过程,就使用当前batch的数据统计均值和标准差,并按照第二章所述公式对Wx+b进行归一化,之后再乘上gamma,加上beta得到Batch Normalization层的输出;如果在进行test过程,则使用记录下的均值和标准差,还有之前训练好的gamma和beta计算得到结果(作业中记录的值也是采用了指数权重滑动平均的方法)。
此外,CNN使用时叫spatial batchnorm,主要是考虑到卷积神经网络的参数共享特性。(知乎回答)
之前大家对BN的理解就是为了解决ICS (internal covariate shift),让每一层输入的分布不再变化莫测(网络需要不停调整参数适应数据分布变化),同时也要加上线性变换层保留一些模型需要的原始信息,也让输出的数据值落在激活函数的敏感区域,也可作为正则化的手段(进一步解读见:1, 2, 3)。
但是MIT 发表在NeurIPS 2018上的研究"How Does Batch Normalization Help Optimization"发现二者并无关系。研究者证明 BatchNorm 以一种基础的方式影响着网络的训练:它使相关优化问题的解空间更平滑了。这确保梯度更具预测性(见机器之心的翻译)。
另外,最近,2020 DeepMind刚出的论文"Batch Normalization Biases Deep Residual Networks Towards Shallow Paths"研究了BN为何可以提升深度残差网络的训练深度:”在初始化阶段,批归一化使用与网络深度的平方根成比例的归一化因子来缩小与跳跃连接相关的残差分支的大小。这可以确保在训练初期,深度归一化残差网络计算的函数由具备表现良好的梯度的浅路径(shallow path)主导“(见机器之心的报导)。另外还有一个问题是BN到底应该放在激活函数之前还是之后?放前面的原因是可能会让激活函数反应在饱和区域,放在后面是因为原意就是为了让隐藏层更好的学习,接收比较规范化的输入,目前来看,似乎大多数论文都是放前面,实际中可能要根据具体问题具体实验,比如小网络放前面,大网络放后面?知乎回答
出了上述几种变体外,还有个结合版本的Switchable Normalization,给IN, BN, LN分配权重,让网络自己去学习哪种归一化方式适合(总结1,总结2,在NLP中也UCB也通过观测BN的异常情况提出了最新的PN,见此)。
在防止模型过拟合方面,正则化方法除了对大权重进行惩罚外,还有引入“random noise”的思路,具体有以下几种(如下图所示)。2019年 CS231N 跟进潮流,新加了Cutout和Mixup方法,其中MixUp方法本人在custom dataset上用过,对小数量数据确实有用。
- The recommended preprocessing is to center the data to have mean of zero, and normalize its scale to [-1, 1] along each feature
- Initialize the weights by drawing them from a gaussian distribution with standard deviation of sqrt(2/n), where n is the number of inputs to the neuron. E.g. in numpy:
w = np.random.randn(n) * sqrt(2.0/n)
.- Use L2 regularization and dropout (the inverted version)
- Use batch normalization
- We discussed different tasks you might want to perform in practice, and the most common loss functions for each task
3.training dynamics & evaluation: 梯度检查,一些网络学习的注意事项,参数更新,超参搜索,模型ensemble等。这里的重点在于optimizer优化器,从一开始的普通SGD到带动量的SGD,然后是一些自适应学习率的优化器,比如目前最好用的Adam等。
Momentum updateing: 关于“动量”更新参数的动力学解释–“动量”应当是“阻尼系数”,点的质量和运动时间看成“1”,然后推导关于位置的更新;
Nesterov Momentum: 利用趋势点希望可以跳出“坑”的困境;
Second order optimization: quasi-Newton methods, 数学公式,Hessian矩阵,二阶方法是利用函数的曲率,也就是导数的导数来进行参数更新,速度会更快,但是Hessian阵难以计算,带数学推导的知乎推荐论文A Stochastic Quasi-Newton Method for Large-Scale Optimization. 2020.2.20,Google brain放出一篇二阶优化算法训练Transformer的论文Second Order Optimization Made Practical. 关于非线性优化方法的一些区别:一阶法(梯度下降,最速下降),二阶(牛顿法,拟牛顿法),共轭梯度等。
从本质上去看,牛顿法是二阶收敛,梯度下降是一阶收敛,所以牛顿法就更快。如果更通俗地说的话,比如你想找一条最短的路径走到一个盆地的最底部,梯度下降法每次只从你当前所处位置选一个坡度最大的方向走一步,牛顿法在选择方向时,不仅会考虑坡度是否够大,还会考虑你走了一步之后,坡度是否会变得更大。所以,可以说牛顿法比梯度下降法看得更远一点,能更快地走到最底部。(牛顿法目光更加长远,所以少走弯路;相对而言,梯度下降法只考虑了局部的最优,没有全局思想。)
根据wiki上的解释,从几何上说,牛顿法就是用一个二次曲面去拟合你当前所处位置的局部曲面,而梯度下降法是用一个平面去拟合当前的局部曲面,通常情况下,二次曲面的拟合会比平面更好,所以牛顿法选择的下降路径会更符合真实的最优下降路径。
Adam优化算法: 其实就是momentum + RMSProp,减缓mini-batch训练中的抖动,同时自适应更新学习率,对超参的选择比较鲁棒。相关解释:矩估计,指数加权移动平均与初始时刻阶段偏差修正,a review ppt.
The two recommended updates to use are either SGD+Nesterov Momentum or Adam.(有时候带动量的SGD法可能比Adam训练出的效果更好,但是调参的难度可能大点)
另有一篇大牛Sebastian Ruder写的An overview of gradient descent optimization algorithms,最近一次更新在2020.3.20,加入了新的优化器,博客中也提供了arXiv版本。
超参Hyperparameters主要包括网络架构,学习率以及其deacy 机制,参数更新机制,和正则化regularization选择及其强度。面对这些超参,在实验时可以通过以下步骤来进行:首先检查模型初始化是的loss,一般权重对每一类都是零认知的,所以会给出平均猜测;然后拿出小部分样本进行实验,进行初始化,给出一些学习率然后对其训练,从中挑出靠谱的;接着再组合学习率和deacy参数,看看哪些不错;然后对上面最好的进行长时间训练,一言以蔽之就是先在数据中的小范围中进行预演。此外也要注意learning rate中的deacy参数选择和加入时间,否则可能使学习不充分。训练刚开始可以采取warm up或者grad warm up处理,这个主要是针对大数据,大网络中权重的初始平稳问题,详见知乎回答。
To train a Neural Network:
- Gradient check your implementation with a small batch of data and be aware of the pitfalls.
- As a sanity check, make sure your initial loss is reasonable, and that you can achieve 100% training accuracy on a very small portion of the data
- During training, monitor the loss, the training/validation accuracy, and if you’re feeling fancier, the magnitude of updates in relation to parameter values (it should be ~1e-3), and when dealing with ConvNets, the first-layer weights.
- The two recommended updates to use are either SGD+Nesterov Momentum or Adam.
- Decay your learning rate over the period of the training. For example, halve the learning rate after a fixed number of epochs, or whenever the validation accuracy tops off.
- Search for good hyperparameters with random search (not grid search). Stage your search from coarse (wide hyperparameter ranges, training only for 1-5 epochs), to fine (narrower rangers, training for many more epochs)
- Form model ensembles for extra performance
Lecture 9. CNN Architecture
这一节主要讲CNN的几个经典结构(AlexNet, VGG, GoogLeNet, ResNet),课外阅读材料相关网络对应的论文。
推荐阅读Justin ho对CNN architecture的介绍文章,链接在此。
AlexNet: 开启CNN风潮的奠基之作,规划了CNN网络该有的部件(data augmentation, filter, maxpool, normalization, non-linearity activation function, fc, dropout, gpu加速等)。
VGG: 引入小卷积核,一方面小卷积核堆叠拥有大卷积核同样的感受野,另一方面还可以减小参数,同时加深网络,提高拟合精度。后续的网络基本吸取了VGG网络中小卷积核(3x3, p=1, s=1)提取特征,mxpool (s=2) downsample 特征图,同时在缩小后的特征图上加倍filter数量保持时间复杂度。
GoogLeNet: 受到Network in Network很大启发(一个是跨通道融合的1x1卷积核带来的MLP功能,提高局部特征的抽象表达能力,另一个是Global Average Pooling (GAP),单独利用特征图分类),同时提升网络的深度和宽度。
为了避免梯度消失,网络额外增加了2个辅助的softmax用于向前传导梯度(辅助分类器)。辅助分类器是将中间某一层的输出用作分类,并按一个较小的权重(0.3)加到最终分类结果中,这样相当于做了模型融合,同时给网络增加了反向传播的梯度信号,也提供了额外的正则化,对于整个网络的训练很有裨益。而在实际测试的时候,这两个额外的softmax会被去掉。
之后Google对inception进行改进到v4版本(详见blog),v2, v3主要是改小卷积核,v4是加入了Resnet的残差连接思想,然后将basic block或者bottleneck中的conv组合换成inception module。
GoogLeNet团队发表的有关GoogLeNet的论文:《Going deeper with convolutions》、《Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift》、《Rethinking the Inception Architecture for Computer Vision》、《Inception-v4, Inception-ResNet and the Impact of Residual Connections on Learning》
ResNet:加深网络可以获得更好的性能,但是采用常规方法堆叠卷积加深优化困难,实际效果不好。
恒等映射,深网络中有不少是对浅网络的缝补,深层网络中,如果保留那些浅层网络的性能,同时又考虑采用恒等映射,那么效果应该不会比单独用浅层网络更差。但是直接学习恒等映射不如学习输出与恒等映射的残差有效(redidual模块会明显减小模块中参数的值从而让网络中的参数对反向传导的损失值有更敏感的响应能力,虽然根本上没有解决回传的损失小的问题,但是却让参数减小,相对而言增加了回传损失的效果,也产生了一定的正则化作用),因此引入跳级连接,ResNet诞生(参考PRIS-SCMonkey,Pascal)。
后续的研究者一直在思考为什么ResNet会如此简洁高效,它到底在解决网络学习中的什么问题?1.degradation问题,梯度有效性被跳级连接解决(何恺明在论文中指出梯度消失爆炸问题已经被BN等normalization手段解决得很好了,跳级连接是为了深层的网络参数对梯度更加敏感,保持前面梯度的相关性,因为前向传播的时候将原始的信息带出一部分。当然ResNet也可以在一定程度上缓解梯度弥散的问题,但是这不是最主要的,详见这个知乎回答),且必须是1系数。多个浅层子网络代表的函数的组合函数,并不是真正意义上的深层特征网络。
**神经网络的退化才是难以训练深层网络根本原因所在,而不是梯度消散。**虽然梯度范数大,但是如果网络的可用自由度对这些范数的贡献非常不均衡,**也就是每个层中只有少量的隐藏单元对不同的输入改变它们的激活值,而大部分隐藏单元对不同的输入都是相同的反应,此时整个权重矩阵的秩不高。并且随着网络层数的增加,连乘后使得整个秩变的更低。**这也是我们常说的网络退化问题,虽然是一个很高维的矩阵,但是大部分维度却没有信息,表达能力没有看起来那么强大。残差连接正是强制打破了网络的对称性。(来自Orhan A E, Pitkow X. Skip connections eliminate singularities[J]. arXiv preprint arXiv:1701.09175, 2017.)
2.ResNet中恒等变换的意义目前有多种解释,我目前倾向的解释是这种残差结构是为了动态自适应拟合训练数据集网络深度的一种方法,它除了可以平稳甚至加速训练外(跳级连接让不同分辨率的feature组合,梯度的相关性得到了保持,后续的DenseNet则用了更多的不同分辨率的特征组合),就是可以根据你的问题去慢慢补充浅层网络解决的最主要的拟合之外的小边边角角,让最后的函数更加平滑。网络输出的残差部分可能在某个block接近0,可能某个部分比较大,所以是一种自适应复杂度。
ResNet是完成一个微分方程的差分形式,dx(t)/dt=H(t)=>x(t+1)=x(t)+H(t). 所以ResNet就是用微分方程来描述一个动态系统,寻找合适的H(t)来构造系统。采用这个结构的好处是H(t)具有某种自适应特性(相比于普通的CNN),对网络的深度不会过于敏感(自适应差分方程的步长),同时简化网络的结构,让网络结构更加均匀化,从几何角度看就是制造了一个更为平直的流形并在其上进行优化,导致系统的收敛性更好。
不同的网络结构实际上构造了不同的解空间的流形,并且部分的定义了其上的度量,而不同的度量引出不同的曲率分布,这对系统的收敛性能影响重大。所以不同网络结构的差异表现在:(1)网络结构是否和问题匹配,是否是一个包含了可能解的足够紧致的空间;(2)由网络结构所部分定义的度量是否导致一个比较平直的均匀的流形(度量还被所采用的代价函数所部分定义)。从这两个角度就可以定性和半定量的分析不同网络结构的特性和关系。
残差模块并不是就是恒等啊,我觉得可以理解为:当网络需要这个模块是恒等时,它比较容易变成恒等。而传统的conv模块是很难通过学习变成恒等的,因为大家学过信号与系统都知道,恒等的话filter的冲激响应要为一个冲激函数,而神经网络本质是学概率分布 局部一层不太容易变成恒等,而resnet加入了这种模块给了神经网络学习恒等映射的能力。
所以我个人理解resnet除了减弱梯度消失外,我还理解为这是一种自适应深度,也就是网络可以自己调节层数的深浅,不需要太深时,中间恒等映射就多,需要时恒等映射就少。当然了,实际的神经网络并不会有这么强的局部特性,它的训练结果基本是一个整体,并不一定会出现我说的某些block就是恒等的情况
在论文Deep Networks with Stochastic Depth中,作者设置概率p让residual block随机失活(均匀概率与线性概率,线性概率更有效些,符合ResNet的设计思想),只保留shortcut,结果精度也没有怎么下降,反而提高了训练速度,这也说明Identity Mapping的正确性。
对ResNet的改进以及后续其他网络:
Wide Residual Networks认为ResNet中有些block去掉也没有影响,所以residual是最主要的影响因素,作者尝试加倍block中的卷积核数量,而不是增加深度,结果发现效果更好,而且由于加深宽度可以由并行化计算解决,所以计算也更加快速。另外,作者也使用了卷积层上的dropout,结果也可以得到一些提升(论文指出何恺明他们是在identity part使用dropout效果不好,所以他们用在这,我想可能是因为拓宽了宽度,特征图增多,可能带来冗余信息,存在过拟合信息)。我没有仔细看论文,也没看源代码,不清楚作者是不是随机给特征图某个元素置0来进行的,实际上给卷积层做dropout的操作并不常见,一般都是BN就足够了,有部分研究是针对卷积层上或者特征图上的droput的,而且认为随机置某元素为0并不能起到作用,因为特征图一般是局部关联的,所以提出了区域置0,某个特征图置0等操作,见此知乎回答。
Aggregated Residual Transformations for Deep Neural Networks: ResNeXt,来自ResNet的作者,想法和上面的差不读,在一个block里采用多组重复卷积核操作,拓宽网络。
Squeeze-and-Excitation Networks : SENet是在网络的特征通道之间进行建模,显示地通过FC去得到通道之间的依赖关系,然后利用最后的sigmoid激活函数给每个通道附一个新的权重,依照这个重要程度去提升有用的特征抑制用处不大的特征 (feature recalibration)。相关介绍见作者胡杰在机器之心的解释。
FractalNet: Ultra-Deep Neural Networks without Residuals: 分形(从多个层次、多个角度、多个组成成分来共同解决一个问题)网络结构,类似于ResNet,但是认为深层网络的关键是浅层到深层的有效过度,residual representation不是必须的。分阶段组合不同分辨率特征,达到了类似于教师-学生机制、深度监督的效果。由于比较复杂,所以没有ResNet用的广泛,但是思想很有深度,其中最突出的contribution就是drop path。在下图的示意中,从输入到预测有很多条路可以走通,drop path机制就是随机失活某些路径,假如其中一条承担的作用是比较大,那么一旦被失活,其他网络就得承担全部的责任,加强其学习力度,所以一方面防止过拟合,另一方面让整个网络变得非常鲁棒,不会出现退化问题,参考此博客。
Densely Connected Convolutional Networks: CVPR2017 Best paper,写的也非常简洁通透。其dense block的设计是ResNet的“完全版”,不仅提高了特征的利用率,减小了参数,也减轻了梯度弥散,每一dense block单独产生的特征图层数也相对较少,也便于训练,具体解读见此博客。但是一开始的DenseNet虽然参数少,但是由于复杂的的skip connection和concatenate操作,中间量的存在会占用很多显存,作者后续论文Memory-Efficient Implementation of DenseNets减缓了这个问题,现在PyTorch等框架也应该自动解决了这个问题,在一定程度上。
MobileNet, ShuffleNet等轻量级计算网络,通过引入depthwise separable convolution, pointwise group convolution, channel shuffle (顺序重分配每组的channel到新的组,减少每个组单独流动信息的局限性)等操作改变传统卷积计算方式,来加速计算。详见知乎白裳的博客随笔和AI之路的详解。
Meta-learning,NAS自动搜索合适架构,开山之作是Google的Neural Architecture Search with Reinforcement Learning ,通过RNN确定架构中每个元素的参数,然后利用reinforcement learning奖励精度高的,惩罚精度差的,以此来学习。NAS领域交叉知识多,暂时无法深入理解。
Assignment 2
宝藏作业,值得认真做。
reference:
参考培训机构深度之眼的cs231n-camp的文档
具体过程和结果参见这个repository
在做CNN那一节时(ubuntu环境,如果是Windows环境可能需要安装python for c++等库),如果在fast_layer.py环节出现CS231n A2: Global name 'col2im_6d_cython' is not defined解决
,请关掉jupyter notebook,然后重新编译就可以了。
Lecture 10. Recurrent Neural Networks
这一节课主要讲RNN的网络结构(recursive neural network是树结构,recurrent neural network是chain结构),设计文本生成,image caption, visual question之类的网路,后面通过training问题提及了下LSTM。课程的目的在于希望NLP和CV两者结合,相辅相成,解决更为智能化的问题。
参考阅读材料方面主要是花书《deep learning》中的第十章: Sequence Modeling: Recurrent and Recursive Nets. 其内容不难理解,也都是介绍性文字,大部分细节都是列出论文便于感兴趣读者去进一步阅读。(个人觉得看好Justin Johnson的课件就差不多了,主要内容都是RNN结构和LSTM)
这里有一篇讲解LSTM的blog(嫌麻烦的可以直接看中文翻译版本)。
有关Justin Johnson课上提到的RNN的一些fun application可以在karpathy的这篇blog找到。
目前,有关机器翻译,文本生成等NLP问题自谷歌的”Attention is all you need“之后,基本上都直接采用self-attention机制了,但这并不代表RNN没有用,已被淘汰了,其在处理依赖时间序列问题还是有很多用武之地的。
Lecture 11. Gnerative Models
这节课没有官方推荐阅读材料,只有slides首先介绍监督学习和分监督学习的一些区别(有无外部label带来的监督信号,前者着重利用数据做任务,后者着重学习数据内部的结构和分布等)。
2020新版增加了CS236的VAE的notes和Ian Goodfellow在NIPS2016上的tutorial.
后面主要讲无监督学习中的一个核心问题density estimation,介绍跟此问题有关的三类generative models:
目前在生成式模型方面还未进行研究,所以暂时也没有啥思考,也就单纯把这节课当成一次introduction。课程中有关这三类模型的概念的公式也不搬过来了,直接看课件就好。
后续会好好研究一下GAN,那时会再专门写笔记讨论体会心得,先放几个不错的resources链接:
- review-A Review on Generative Adversarial Networks: Algorithms, Theory, and Applications
- paper list-the-gan-zoo
- how-to-train-gan-ganhacks
- 知乎文章-令人拍案叫绝的Wasserstein GAN
- researcher-Jun-Yan-Zhu
- Stanford-cs236-deep generative models
- UCB-cs294-deep unsupervised learning
2020.6更新:
普通的pixelRNN/CNNs是显示估计数据分布,即:,虽然效果不错,但是计算很慢,VAE是利用一个中间的隐变量来进行,即:
但是上述的VAE只能重建输入图片,如果想要重建满足输入数据分布下的另一个图片该怎么做?
我们可以选择为一个已知的比较简单的先验分布,比如高斯分布,是神经网络解码出的分布,但是前面的积分会使得整个过程intractable. 考虑后验概率,即,进一步地有:
现在我们先让encoder去让后验概率去近似我们设定的先验概率,比如说是标准正态分布,然后让decoder从拟合的后验概率中采样去重建图片。训练时重建输入图片,用以反向传播,测试时可以直接丢掉encoder,利用decoder随机从先验概率分布中采一个数然后decoder出新的图片。非常漂亮的思想!
此外,隐变量也是多维的,每个维度可以带便不同的图像特征,这样的话可以控制我们想要输出的图片内容。
以上的两种方法都在试图显示建立数据的分布,而GAN试图绕过复杂的数据分布建模,利用博弈的思想隐式建立数据分布,从而直接生成新的图片样本。
Lecture 12. Detection and Segmentation
这节课介绍了计算机视觉中比较重要的四个任务:classification, semantic segmentation, object detection, instance segmentation, slides做的很不错。
此外,18版的课程里有个两个相关的discussion section:Practical Object Detection and Segmentation,列出了经典的检测和分割结构,并给出了相应的代码实现链接和一些其他resources;Video Understanding.
1.semantic segmentation主要通过FCN的结构介绍了downsampling–upsampling这种经典结构,重点引出一般的upsampling的方法,比如unpooling (一种是最近邻补值,一种是记下pooling的索引,然后其他补零)和转置卷积(利用权重矩阵乘以每个元素,然后得到大的特征图区域,overlap的地方累加<累加只是一种处理手段,这方面或许可以有更好的办法恢复信息>)
转置卷积transpose convolution: upsampling的一种 ,unpooling, max unpooling, 为什么叫转置卷积更好点,Justin Johnson在课上也给了数学解释。(知乎问题)
空洞卷积Dilated Convolution:源自于语义分割领域,目前也大多用于语义分割领域。初衷是为了解决downsample丢失的信息会影响pixel-wise的分类。“dilated的好处是不做pooling损失信息的情况下,加大了感受野,让每个卷积输出都包含较大范围的信息”(知乎问题)
2.object detection和instance detection是交叉介绍的,因为后者是前者的集成,也顺带提及了human pose estimation,keypoint。这一部分的介绍相比2017版多了一些细节(尤其是RoI pooling<浮点数两次转整型处理,丢失proposal原始像素信息>和RoI Align<保留浮点数,利用双线性插值得到每个max pooling小区域的四个点,对小目标更好>)和scene graph, 3D检测,3D shape prediction等部分(3D Machine Learning应该是目前工业界比较看重的一个领域,在无人驾驶,增强现实等领域可以发挥作用)。其中object detection部分着重介绍了R-CNN系列,更详细的解释可以阅读另一篇博客。课程中也推荐一篇综述类型的paper: Speed/accuracy trade-offs for modern convolutional object detectors便于进一步了解(在我的另一篇R-CNN检测专题博客会有所提及)。
可变形卷积Deformable convolutional networks:受Andrew Zisserman的STN (Spatial Transformer Network) 启发,针对物体的形状自发的选择卷积的区域,而不是按照约定的矩形计算规则,更适合实际。在知乎回答中,有人说可变性卷积是对空洞卷积的一种generalization,增大了感受野 。
Lecture 13. Visualizing and Understanding
1.试图理解卷机神经网络是怎么做决策的,这些layers到底学了什么东西。因此引入了特征图可视化,看看网络对图像的那些区域或者blob甚至是pixel反应大些(感受野,遮挡,回传对pixel的梯度,gradient ascent等),激活的是哪些地方(这里面的针对像素的梯度上升方法与学习权重等参数的方法是对立统一的,固定神经元参数,给定zero 图像,加一些正则化方法,然后对图像进行优化,看看什么样的图像可以获得更高的类别分数),然后借此产生对抗样本adversarial example试图欺骗网络(17年的最后一课就是请Ian Goodfellow讲这个)。
2.利用可视化思想通过选定特定的layer对输入图像做gradient,然后更新图像,放大特征,产生DeepDream效果;
3.Neural Texture Synthesis, 利用Gram matrix对小区域图像进行延展;
4.Neural Style Transfer, 对输入图像进行特定风格的渲染。这项技术现在已经被商业化了,有不少手机APP和其他应用都有此功能!Justin Johnson也有个torch的实现。
但是得到一张转换的图片很慢,因为有很多的forward和backword,因此J.J做了个Fast Style Transfer, 训练另外一个网络来实现style transfer, 其中IN (instance norm)就是为了快速风格转换发明的。课程的slides里也提供了很多相关的paper,对细节感兴趣的可以看看。
有关神经网络可视化,个人觉得是个很有意义也和好玩的一个领域,它在一定程度上解释了模型为什么work,也可以结合一些idea做出可消费的funny application出来。~~Assignment3也有相关的作业,到时候应该可以深入学习理解下。~~从assignment3来看,为了让输入图像的风格靠近目标图像 (style loss),采用gram矩阵来编码模型各个层产生的通道之间的相关性,然后尽量让两幅图像的gram矩阵(以指定维度方向上的各个向量之间做内积)相近。gram矩阵代表图像特征中哪些特征是同时出现的,哪些是此消彼长,不相干的,而特征呢就相当于图像的某个特性,比如在修图的时候,我们会调调对比度,加些高光,调调饱和度等,为了得到我们想要的风格的图像,其中有些修图选项可以一起做,有些往大的值调,有些就得往小的调,gram矩阵也是类似的操作,缩小目标gram矩阵和输入gram矩阵之间的差异就等于是给图像加滤镜。此外,gram矩阵的对角线上还包含了每个特征图的原始信息,也就是说不仅有哪些特征(哪些修图选项),也有各个特征之间的联系(修图选项的调整值),因此可以大致代表图像的风格。(相关知乎问题)
相关blog: Hungryof的“谈谈图像的style transfer"系列—1, 2, 3
Discussion–Learning on videos
视频理解和3D machine learning 似乎成为现在CV中的两个新的热点。2020年的课程中也没有把视频理解放进前面的CV applications中,估计是考虑到视频理解中用的方法也是从那些分类,检测等基础任务中迁移过来的。从现在工业界短视频作为火热的媒介来看,视频理解的研究预计会出现比较大的需求和增长。
Discussion Section—learning on videos
其中提到目前主流的三种模型:
CNN + RNN: video understanding as sequence modeling
3D Convolution: embed temporal dimension to CNN
Two-stream: explicit model of motion (video = apperance + motion)
Lecture 14. Deep Reinforcement Learning
对于强化学习的印象只停留在一个框架的系统层面上:输入是状态(state),动作(action)和奖励(reward),输出时方案或者策略(policy),大意就是通过奖惩机制,在某个环境中为对象制定在初始状态实现目标的一系列策略。
强化学习的热度似乎没有神经网络,GAN等技术大,而且据我身边研究的朋友说,强化学习的学习难度有点高,具体没有细问,可能是模型,critic制作和训练的难度不低。一位bloger在他对强化学习简介的blog中说到:
强化学习的领导研究者Richard S. Sutton认为,只有这种学习法才考虑到 自主个体、环境、奖励 等因素,所以它是人工智能中最 top-level 的 architecture,而其他人工智能的子系统,例如 logic 或 pattern recognition,都应该在它的控制之下,我觉得颇合理。
个人认为,目前的强化学习方式确实是一个可以融合许多机器学习技术和模型的一个理论框架,视觉中的注意力机制可以用到,NAS中也可以用到,随着时间推移,可能会有更多的结合和应用会产生,甚至引导未来很多产业的落地。
一些相关resources:
Besides,这课件做得也挺好的,虽然Serena Yeung小姐姐讲的课让我一知半解,云里雾里的 :(
Assignment 3
reference:
参考培训机构深度之眼的cs231n-camp的文档
具体过程和结果参见这个repository
COCO_Caption数据集下载速度很能很慢,将链接放至迅雷可能快点,我这边是1~2M/s。
做RNN_Caption.ipynb
时出现类似assignment1的无法导出imread,imresize
问题,原因就是scipy
包现在不支持这个函数了,直接将scipy
从1.4退回到1.2.0即可。
在执行Look at the data
部分时出现[WinError 10054] 远程主机强迫关闭了一个现有的连接
错误,按照此博客的解释,可能是链接存在一些无法访问的情况,将“http"改成”https"即可,url = url.replace(http://", 'https://')
改完之后可以顺利访问,但是出现进程被占用
情况,解决方法同上面博客,修改image_utils.py
中的image_from_url
函数:
def image_from_url(url): |
在NetworkVisualization-Pytorch.ipynb
的load some ImageNet images
中,运行报错Object arrays cannot be loaded when allow_pickle=False
,通过这篇博客发现是自己numpy
版本过高问题,将其回退到1.16.1或1.16.2即可解决
在使用pytorch时,要注意对requires_grad=True
的Tensor和求梯度阶段需要用到的Tensor都不能用inplace operation,也就是不能直接对这些张量进行数值操作,最好加上.detach()曲线救国,见此。
在Generative_Adversarial_Networks_PyTorch.ipynb
中下载MNIST可能很慢,可以直接找到数据网址自己下载好数据集,然后放到代码自动创建的存放数据的文件夹中的raw
中,再次运行就可以不用在线下载,而是直接读取在process了。还有一种办法是改变源代码的中的urls到本地,详情可见here.
2017 Invited Talk-Efficient Methods and Hardware for Deep Learning, Song Han
CS231N每年都会邀请不同的专家来做一些专题介绍,由于2017年以后都没release视频了,所以就直接看17年的talk了,正好17年的这两个topic都比较不错,在应用上都很重要,因此也很值得学习下。
韩松在该领域算是比较有名的一位,他在此节课从算法讲到硬件(分inference和training两部分),非常系统。虽然大多是overview,但是包含的内容很多,后续研究压缩领域也会从他主页中列举的资料来入门和学习。
韩松教授2017年的phd thesis: [EFFICIENT METHODS AND HARDWARE FOR DEEP LEARNING]([https://stacks.stanford.edu/file/druid:qf934gh3708/EFFICIENT METHODS AND HARDWARE FOR DEEP LEARNING-augmented.pdf](https://stacks.stanford.edu/file/druid:qf934gh3708/EFFICIENT METHODS AND HARDWARE FOR DEEP LEARNING-augmented.pdf))
DSD (Dense-Sparse-Dense Training) Model Zoo
2017 Invited Talk-Adversarial Examples and Adversarial Training, Ian Goodfellow
Ian Goodfellow的语速很慢,然而我整节课却没怎么听懂他在讲什么。
Lecture 17. Human-Centered AI
李飞飞最后的总结性课程,描绘AI对社会和人类的影响和蓝图,提出HAI的概念。
Lecture 18. Scene Graphs
2020版新增了Scene Graphs and Graph Convolutions,slides.
这一部分应该是让计算机去更好的理解图片。分类,检测都是认识图片的一种手段,不是目的。