第一课:李飞飞授课
cs231a —— 更宽泛、涵盖更全面的计算机视觉课程。cs231n专门讨论cnn。
CVPR, ICCV —— 重要的计算机视觉会议
Block world (Larry Roberts, 1963)
David Marr's book: VISION
Normalized Cut (Shi & Malik, 1997) 将图像分割为有意义的块
Face Detection (Viola & Jones, 2001)
SIFT & Object Recognition, David Lowe, 1999
Spatial Pyramid Matching, Lazebnik, Schmid & Ponce, 2006
总体梗概
课程描述
计算机视觉在我们的生活中随处可见,其应用包括搜索、图像解译、app、地理制图、医学、无人驾驶飞行器、以及自动驾驶汽车。许多这些应用的核心任务是图像识别,例如图像分类、定位和检测。神经网络技术的最近进展(即深度学习)极大的提升了这些最先进图像识别系统的性能。
重点关注:
如何建立图像识别问题,学习算法(例如反向传播法),训练并精细调整网络的工程应用技巧,通过上手操作的作业和最终的一个课程工程项目来指导训练学生。
课前具备的条件:
精通Python;高度熟悉C/C++
大学微积分;线性代数
基本概率统计
CS229的等效知识(机器学习)[将使用代价函数、求导数、使用梯度下降法求最优]
课程鼓励外部学习者:
作业、课程笔记、讲座视频、幻灯片可以在线获得。
完成作业需要掌握的工具:Python,and a few polular libraries(numpy, scipy, matplotlib)
knn分类器、线性分类器
knn分类器原理不复杂,笔记掠过。
线性分类器与CS229的部分内容一样。要点有:score function, loss function, gradient descend.
SVM loss,也是hinge loss;
softmax loss,可以从两个角度解读:1 信息论角度,真实分布与预测分布的交叉熵,或者KL散度;2 概率论角度,最大似然(叠加正则项时,是最大后验概率)
为什么正则项可以防止过拟合?因为正则项限制模型参数的大小,使模型保持简单。
为什么要用L1、L2正则项?从概率论的角度解释,使假定模型参数服从某种分布(L1对应拉普拉斯分布、L2对应高斯分布),这时再求最大后验概率,就推导出正则项。
实际编程时注意:
初始化W为接近与0的随机数时,应当检验Multi-SVM损失函数 / softMax损失函数是否符合预期。具体为Multi-SVM损失函数C -1,而softMax损失函数为log(C),C为分类数。
寻优过程与CS 229类似。同样,计算梯度时,需要注意:
用数值法求得的梯度来检验解析公式得出的梯度。(所谓的Gradient Check)
图像特征提取:神经网络兴起之前,往往不直接将图像作为分类器的输入,而是先提取特征,再输入分类器。
常用的特征有:Color Histgram,Hisgram of Oriented Gradient (HoG),Bag of Words
反向传播
Computational Graph: 可以近似任何函数
用于计算前向传播,得到函数值;或计算反向传播,计算梯度。
(由于神经网络很复杂时,很难得到梯度的解析式,因此用Computational Graph来计算)
课程反向传播的notes部分,某个函数分解成计算图后,正向传播计算如下:
x = 3 # example values
y = -4
# forward pass
sigy = 1.0 / (1 + math.exp(-y)) # sigmoid in numerator #(1)
num = x + sigy # numerator #(2)
sigx = 1.0 / (1 + math.exp(-x)) # sigmoid in denominator #(3)
xpy = x + y #(4)
xpysqr = xpy**2 #(5)
den = sigx + xpysqr # denominator #(6)
invden = 1.0 / den #(7)
f = num * invden # done!
反向传播如下:
# backprop f = num * invden
dnum = invden # gradient on numerator #(8)
dinvden = num #(8)
# backprop invden = 1.0 / den
dden = (-1.0 / (den**2)) * dinvden #(7)
# backprop den = sigx + xpysqr
dsigx = (1) * dden #(6)
dxpysqr = (1) * dden #(6)
# backprop xpysqr = xpy**2
dxpy = (2 * xpy) * dxpysqr #(5)
# backprop xpy = x + y
dx = (1) * dxpy #(4)
dy = (1) * dxpy #(4)
# backprop sigx = 1.0 / (1 + math.exp(-x))
dx += ((1 - sigx) * sigx) * dsigx # Notice += !! See notes below #(3)
# backprop num = x + sigy
dx += (1) * dnum #(2)
dsigy = (1) * dnum #(2)
# backprop sigy = 1.0 / (1 + math.exp(-y))
dy += ((1 - sigy) * sigy) * dsigy #(1)
# done! phew
其中,dnum的意思是 $$ \partial f / \partial num $$
同理 dx 意思是 $$\partial f / \partial x$$
其他的都类似。
卷积神经网络总体
Convolutional Neural Network 与 Fully Connected Neural Networks 相对。
设计CNN的结构、选择超参数是很费事费力的事情。90%的情况下,我们都从ImageNet中选择表现最好的网络结构,下载下来,再针对自己的具体数据精确调参。
对于Fully Connected Neural Networks,三层比两层表现更好,但是更深的网络则不然。而对于CNN,几乎越深的神经网络效果越好。
为了防止过拟合,一般不是通过降低层数,二是通过 L2 regularization, dropout, input noise等方法。小网络容易陷入较差的局部最优解,对初值依赖很强;而大网络则往往不会得到很差的解,对初值依赖性也不强。
一些实现细节
数据预处理:Zero Centering, Normalization。注意:这些操作在计算均值和方差时都是使用 training set,而不能用 validation set 和 test set。
权值初值:初始化为较小的随机数。初始化为标准的高斯分布,然后以1/sqrt(n)做校正(n是神经元的输入的维度),使得神经元的输出为标准高斯分布,这样可以提高收敛的概率。对于采用ReLU的神经网络,应当乘以sqrt(2/n)。
bias初值:一般都设置为0。
检验程序的正确性 Sanity Check
检查初始的损失函数,是否符合预期
检验梯度。在 gradient checking 时使用双精度,而不是单精度,否则会因溢出出现较大的相对误差。分开对 data loss和 regularization loss 进行梯度检验,防止一方的梯度过大吞噬掉另一方,从而检查不出另一方的错误。
再对大量数据进行学习前,把regularization调成0,学习少数几个随机样本(例如20个),使得网络对这几个数据过拟合。此时,理论上loss function应当为0。若不为零,说明学习过程中有错误。
照看学习的过程
第一个需要监督的量是损失函数。 先设定很小的regularization,然后观察loss function是否会快速下降。如果不下降,说明learning rate 太低了;如果loss function 急剧增大,则learning rate 太大了
第二是训练集的分类精度和检验集的训练精度 Train/Val accuracy
第三是每一步的权值的更新量与权值本身的比值,Ratio of weights:updates,大小应当为1e-3左右
第四,输出每一层的Activation / Gradient distributions,以排除不正确的initialization
最后,得到学习的结果时,将第一层神经网络可视化(对于处理图像的网络)
迭代寻优的方法
普通的梯度下降法
动量更新法
Nesterov动量法
超参数调优
learning rate 的调优: 使用cross validation,先选择部分数据、执行少量迭代,观察loss function是否下降,变化情况如何,以确定learning rate 的大致范围。(过大则loss fucntion可能出现NaN,过小则loss function 无变化)
对超参数的采样使用随机抽样,而不是等间隔抽样,这样更容易找到更好的组合
迁移学习
使用大型数据的学习结果,只对最后几层做进一步调优。
CPU or GPU
GPU编程:
类c语言代码,有很多技巧,很复杂
高阶API:cuBLAS, cuFFT, cuDNN(用于卷积神经网络、反向传播),等等
与CUDA类似,通常计算速度更慢一些
一般使用现有库即可。