CS231n的全称是CS231n: Convolutional Neural Networks for Visual Recognition,即面向视觉识别的卷积神经网络。该课程是斯坦福大学计算机视觉实验室推出的课程。需要注意的是,目前大家说CS231n,大都指的是2016年冬季学期(一月到三月)的最新版本。
课程描述 Information 计算机视觉在社会中已经逐渐普及,并广泛运用于搜索检索、图像理解、手机应用、地图导航、医疗制药、无人机和无人驾驶汽车等领域。而这些应用的核心技术就是图像分类、图像定位和图像探测等视觉识别任务。近期神经网络(也就是“深度学习”)方法上的进展极大地提升了这些代表当前发展水平的视觉识别系统的性能。 本课程将深入讲解深度学习框架的细节问题,聚焦面向视觉识别任务(尤其是图像分类任务)的端到端学习模型。在10周的课程中,学生们将会学习如何实现、训练和调试他们自己的神经网络,并建立起对计算机视觉领域的前沿研究方向的细节理解。最终的作业将包括训练一个有几百万参数的卷积神经网络,并将其应用到最大的图像分类数据库(ImageNet)上。我们将会聚焦于教授如何确定图像识别问题,学习算法(比如反向传播算法),对网络的训练和精细调整(fine-tuning)中的工程实践技巧,指导学生动手完成课程作业和最终的课程项目。
视频入口
Assignment(1)
01
假设我们有一个图像训练集 X,是一个大小为[N,D]的矩阵;其中,N表示样本的数量,D表示样本的维数。xi是X中的第i行,即第i个样本。
y表示一个向量,大小为[1,N];yi表示第i个样本的真实类别,yi=1,2,3, ...,C。
假设我们有一个线性映射为:
----------------------> f(xi, W, b) = xiW + b <--------------------
其中,W是权重(weight)矩阵,大小为[D,C],W的第j列表示xi在第j(1≤ j ≤C)个类别上的线性映射;b是偏置向量,大小为[1,C];f的大小为[N,C]。(ps: 这里的公式为了和代码里的保持一致,做了调整,下面的公式都为编程服务)
函数f(xi, W, b) 的值就是C在每个类别上的得分,而我们的最终目标就是学习到W和b,使得f的大小在全局范围内接近真实值,即真实的类别得到更高的分数。
为了便于直观理解,下面贴出一个栗子(和上面的公式有点区别,但不影响理解):
CS231n Convolutional Neural Networks for Visual Recognition.png
图片中的结果认为这很可能是一只狗,说明W和b的值没有训练好。
关于线性分类器的几何解释和模板解释,可以直接看cs231n的笔记,这里不再赘述。
为了便于计算,我们可以将b和W进行合并,将b加到W的最后一行,W的大小将变为[D+1,C]。此时,xi需要增加一维常数1,即xi的大小为[1,D+1](编程的时候别忘了);同时,上面的f需要修改为:f(xi, W) 。
SVM loss : 对于每一张图像样本,正确分类的得分应该比错误分类的得分至少高Δ(Δ的取值在实际中一般为1,不将Δ作为参数是因为它的变化可以转换为W的变化,所以只要训练W就行了)。这里贴上一张图便于理解:
CS231n Convolutional Neural Networks for Visual Recognition.png
上面我们提到的线性映射将第i个样本的像素值作为输入,输出该样本在C个类别上的得分,形成一个分值向量,大小为[1,C]。所以,我们记sj = f(xi, W)j,表示第i个样本在第j类上的得分。那么,multiclass SVM loss的表达式如下:
--------------------> Li = ∑j≠yi max(0, sj−syi+Δ) <---------------
从表达式中可以看出,当syi >= sj + Δ 时,Li = 0,这时候表示判断准确;反之,Li>0,这时候表示判断有误。
我们可以将Li重新表示如下:
--------------> Li = ∑j≠yi max(0, (xiW)j−(xyiW)j+Δ) <------------
上面的max(0, -)函数称为Hinge loss,有时候也可以用max(0, -)2,称为squared hinge loss SVM (or L2-SVM),它对错误的惩罚更加严厉。我们可以通过交叉验证来选择具体的形式(多数情况下我们会使用前者)。(ps: 这里有一篇介绍Hinge loss的博文)
上面的损失函数存在缺陷:W不唯一。假设一组W使得损失函数的值为0,那么 λW (λ>1) 也能做到。为了得到唯一的W进行分类工作,我们可以添加一个正则化惩罚项(regularization penalty)R(W)来实现,通常是2范数:
---------------------------> R(W) = ∑k∑s (Wk,s)2 <-----------------------
添加惩罚项后,完整的损失函数表达式为:
---------------------------> L = (1/N)∑iLi + λR(W) <---------------------
其中,λ可以通过交叉验证来选择。
对参数进行惩罚最主要的作用其实是防止过拟合(overfitting),提高模型的泛化能力。此外,偏置b不会对输入特征的影响强度产生作用,所以我们不需要对b进行惩罚(但是b被合并到了W里,所以实际上我们在assignment1里对b也进行了惩罚,不过影响不大)。
后面求解参数W会用到L关于W的偏导数,这里我们先给出(推导比较简单,这里Δ我直接换成1了):
------------> ∇Wyi Li = - xiT(∑j≠yi1(xiWj - xiWyi +1>0)) + 2λWyi <------
------------> ∇Wj Li = xiT 1(xiWj - xiWyi +1>0) + 2λWj , (j≠yi) <--------
其中,1(·)是示性函数,其取值规则为:1(表达式为真) =1;1(表达式为假) =0。
Softmax是二值Logistic回归在多分类问题上的推广。
这里函数f保持不变,将Hinge loss替换成交叉熵损失函数(cross-entropy loss),其损失函数表达式如下(log(e) =1):
-----------------------> Li = -log(exp(fyi)/∑j exp(fj)) <-------------------
其中,函数fj(z) = exp(zj)/∑k exp(zk)称为softmax函数。可以看出softmax函数的输出实际上是输入样本xi在K个类别上的概率分布,而上式是概率分布的交叉熵(不是相对熵,虽然看上去好像是相对熵,下面我会稍微修改一下Li,还原它的本来面目;交叉熵可以看做熵与相对熵之和)。
先引入一下信息论里的交叉熵公式:H(p,q) = -∑x p(x)logq(x);其中p表示真实分布,q表示拟合分布。下面我们来修改下Li:
-----------------------> Li = -∑k pi,klog(exp(fk)/∑j exp(fj)) <-------------
其中,pi = [0,0, ...,0,1,0, ...,0,0],pi,k=pi[k],pi 的大小为[1,C],pi 中只有pi[yi]=1,其余元素均为0。现在感觉如何?
在实际编程计算softmax函数时,可能会遇到数值稳定性(Numeric stability)问题(因为在计算过程中,exp(fyi) 和 ∑j exp(fj) 的值可能会变得非常大,大值数相除容易导致数值不稳定),为了避免出现这样的问题,我们可以进行如下处理:
CS231n Convolutional Neural Networks for Visual Recognition.png
其中,C的取值通常为:logC = -maxj fj,即-logC取f每一行中的最大值。
现在,结合惩罚项,给出总的损失函数:
---------> L = -(1/N)∑i∑j1(k=yi)log(exp(fk)/∑j exp(fj)) + λR(W) <-------
后面求解参数W会用到L关于W的偏导数,这里我们先给出结果,然后推导一遍:
--> ∇Wk L = -(1/N)∑i xiT(pi,m-Pm) + 2λWk, where Pk = exp(fk)/∑j exp(fj) <--------
推导过程如下:
Derivative of softmax loss function.png
下面贴出一张图,大家可以直观感受下SVM和Softmax关于损失函数的计算区别:
CS231n Convolutional Neural Networks for Visual Recognition.png
优化就是通过在训练集上训练参数(权重和偏置),最小化损失函数的过程。然后,通过验证集来微调超参数(学习率、惩罚因子λ等等),最终得到最优的模型;并用测试集来测试模型的泛化能力。
通常我们用梯度下降法(Gradient Descent)并结合反向传播(Backpropagation)来训练参数。具体的参数更新策略,这里我们使用vanilla update方法(我们会在Part3神经网络部分,具体介绍不同的参数更新策略),即x += - learning_rate * dx,其中x表示需要更新的参数。
梯度下降的版本很多,通常我们使用Mini-batch梯度下降法(Mini-batch Gradient Descent),具体参见该课程的笔记。
ps: 在编程任务中你会发现上面提示用随机梯度下降(Stochastic Gradient Descent, SGD),但实际上用了Mini-batches,所以当你听到有人用SGD来优化参数,不要惊讶,他们实际是用了Mini-batches的。
至于反向传播,实际就是链式法则(chain rule),这里不展开讲,具体参见课程笔记。实际上我已经给出了,就是上面的偏导。等到后面的神经网络,再具体展开讲一下。