这里只记录一些自己在看课时的感受和一些想法,具体内容的笔记请参考:
01. Introduction to CNN for visual recognition
这一块主要讲了关于Vision的重要性,从整个历史的角度分析“视觉”的重要性。cv就是想尽办法构建一种机器,可以模拟人利用视觉所能干的一切的事。 另外强调了数据的重要性,ImageNet的出现为整个视觉提供了一个benchmark数据集,可以更好评价视觉的进步程度。还有就是神经网路尤其是CNN在2012年取得重大成功,之后的发展基本围绕其通过层数的叠加来提高性能。最后强调了CNN早在1997年就出现了,之所以后面才如此流行是因为“计算能力”的发展和“大量数据”的出现。
CV的“圣杯”,通过短暂的观看一张图片,便能滔滔不绝的叙述这里面的故事。
02. Image Classification(图像分类)
- 我们如何处理的图像分类问题?无法用传统的人工去定义各种规则,采用数据驱动的方法。
- 图像分类的难点?视角、光线、各种姿势、物种不同的类别、背景和物种的相似性以及因为一些光线原因导致某个物种很像另一种物体等等,在各种情况下都能准确分类出来。
- 一些简单的图像分类器
- 最近邻算法(train阶段记住所有图片,predict阶段比较相似来输出标签)q:里面的各种颜色以及一个一个的点是什么?里面的具体过程是什么样的?
- 里面的各种颜色代表着决策区域,也就是这个区域的点会属于那种颜色的类别。一个一个的点代表着训练的数据,点的颜色代表着该点属于哪个类别。这个具体过程就是,随便在这个区域点一个点作为测试点,通过计算这个测试点与所有的训练点的L1距离或者L2距离,找出最短距离的点的类别,那这个测试点就属于该类别。
- K最近邻算法 q:这里的K代表什么含义?不同的计算距离的方式到底有什么区别?(L1/L2)如何确定超参数?
- K代表选几个最短距离的点,K越小那么分类时受局部点或者噪声的影响就越大,当然也可以说更加关注每个具体的数据;K越大那么分类时更加关注全局数据,一般来说泛化性会更好些。当然具体的选择还是通过实验来确定这个超参数如何选择。
- L1距离是曼哈顿距离,是各个坐标在对应坐标系的投影的距离之和,因此它的距离会受坐标系选取的影响,不同坐标系的单位长度、或者方向不同都会影响L1距离,因此当输入有某个很在意的特征时可以选用L1距离,由于该特征会投影到某个坐标系上,因此可能会更受关注一些。
- L2距离是欧式距离,是两个点的实际空间距离,简单来说就是两个点的连线距离。所以它的距离并不会受坐标系影响,而当输入有很在意的特征时也难以发现。当然最后实际选择哪个距离,还要看实验结果,这里只是给一个直觉上的参考。
- 最近邻算法(train阶段记住所有图片,predict阶段比较相似来输出标签)q:里面的各种颜色以及一个一个的点是什么?里面的具体过程是什么样的?
这个图反应到原点的L1、L2距离相等的点构成的形状。
- 训练集、验证集、测试集:在训练集中我们训练模型的参数,通过验证集进行评估进而调整超参数然后重复训练和验证直至找到一个最优或者较优的超参数,测试集只有在最后一步的时候才会使用;测试集代表着未见过的数据,或者说wild data,因此在测试集上的表现性能代表着模型的泛化能力,事实上我们并不关注训练结果怎么样,只关注模型在未见过的数据上的表现如何,因此万万不可在测试集上去改任何参数来拟合测试集。
- 设置超参数的一种策略:交叉验证。交叉验证在小数据集时较为常用,但在大数据集或者训练时间很长的模型时就很难应用了。因为交叉验证涉及多次划分训练集,多次训练,这样的计算成本太高了。
- 维度灾难:在knn中,随着维度的升高,在训练集中让点尽可能的覆盖这个空间所需要的点会呈指数爆炸性增长。由此维度越高,我们的数据可能难以做到完全覆盖这个空间的全部类型,因此识别未见过的数据的能力会变弱。
- 线性分类器。q:W究竟该如何理解? b又代表了什么?
-
W有三种理解
- 所有分类器的组合,W的每一行代表着一种分类器,刚好W的每一行都会和图片数据x相乘,然后计算一个分数,通过这个分数来确定该图像属于这个类别的可能性。
- 模板匹配,W的每一行代表着一个类别的模板,通过比较给定的图片与该模板的相似程度来确定是否属于该类别。当然由于这个模板会结合所有的训练数据,所以给定的模板会尽可能包含该类别的所有信息,比如双头马。
- 把图像看作高维空间的点,Wx+b则构成一个直线,W的每一行构成不同的直线。通过判断计算后的点落在某个直线的哪一端来进行分类。
-
b代表了一个偏移量,由于训练数据不会保证所有类别的数据是一个均等的水平,那么b的作用就是使得参数调整更加灵活。如果假设没有b的话,这意味着调整W的时候,始终在绕着原点转,但是数据并不一定会关于原点均匀分布,所以我们添加b使得这条直线能够更加灵活移动,从而分开数据。
-
03. Loss function and optimization
-
q: 什么是损失函数?
- 损失函数就是用来衡量在给定特定参数时的预测结果与真实结果对比情况,损失函数要实现的功能就是与真实情况越接近损失越小,越不符损失越大。计算损失时,将所有的数据集中的预测值与标签值(或者说真实值)比较,得到总的损失值,然后再取平均得到这一轮的损失值,以这个损失值作为更新参数时的指导。
-
多个损失函数
- SVM 作为损失函数, q: 什么是SVM?SVM哪个对应画出的图是什么意思?
- 这里讨论的是SVM损失函数,并不是一般意义上的支持向量机。这个损失函数的物理意义就是,确保在正确分类上的得分始终比不正确分类上的得分高出一个边界值 这个边界值实际上可以是任意的,因为我们在通过损失函数确定W时,只关注的是正确的与错误的相对差值,这个差值实际上可以进行缩放,变成2倍的或者其他多倍的,取决于W可以变成2W或者多倍的W,因此这里给定为1只是一个惯例值。
- 这个图的横坐标对应,纵坐标对应损失值,为真实值时的分数。具体来说:SVM的损失函数: 这个损失函数是以正确的类别为基准,即给正确类别打的分为基准,计算给其他类别打的分与正确类别打的分的差值,错误类别打的分只能比低,如果比高,则损失值就很大。由此可以得到下面的“铰链损失”
- SVM 作为损失函数, q: 什么是SVM?SVM哪个对应画出的图是什么意思?
-
正则化的概念q: 什么是正则化?为什么要引入正则化?为什么加入正则化就能将复杂度降下来呢?
- regular本意就是“规约、限制”的含义,regularization翻译为正则化,就是添加一些限制,使得模型能够朝简单方向发展,例如:本来我可以拟合成非线性的,但是我拟合成线性的。这里面有一个思想:简单往往是最好的,会更加具有泛化能力。这里要注意一个前提:正则化约束,约束的是w,即权重,它要让权重安排的尽可能简单。换句话说通过数据损失,我们可能找到多组w能够正确分类这组数据,但是我们想要最简单的一组w来完成这个任务,因为最简单的往往更具有泛化能力。
- 不加正则项,模型为了更加符合训练数据,可能导致过拟合。因此通过添加一个能够让复杂度降低的约束项,会使得最后结果更加具有泛化性,因此在测试集上表现会更好。
- 这个是我的理解:不论是L1还是L2,两者其实都希望W的各个值尽可能小,当出现多项式的时候比如: 此时会使尽可能小,至于为什么不会让小,感觉还是和数据相关,总是接触的一手的数据,它的参数往往重要一些。所以最终会降低复杂度。那么为什么L1会趋向于让更多W的值为0呢?因为L1本身是最简单的取绝对值直接加起来,那么最小就是让绝对值项为0。而L2会趋向于让各个W的值均匀的变成小值,因为它是平方和,均匀变小比让每个值为0容易一些。或者我们结合图像来看,L2范式的正则是多个二次项加起来,那要使得这项最小,最好的解决方案就是各个w在对称轴附近均匀分布;L1范式的正则是多个一次项加起来,那要使得这项最小,最好的解决方案就是每一项都最小,每一项都在这条线的最下边
-
softmax分类器, q:什么是softmax?softmax分类器与前面的SVM分类器有什么不同?损失的本质是什么?
- softmax就是在原来得到的score上进行一个softmax处理,使得所有的得分均为正值,且被归一化到0~1之间形成一个概率。我们的目标是让正确类别的概率尽可能的接近1其余错误的概率尽可能接近0,因此这里采用的损失函数为-logP,当-logP的值最小的时候也就是0的时候,此时该标签值对应的概率是1
- 前面的SVM分类器是一个直觉上的感觉,他给你一个目的,我就是为了让正确类别的得分尽可能高于错误类别的得分。而这里我们很明确就是让它落在一个0~1的区间内,并且让这个正确的类别的概率去接近1。更关键一点:SVM分类器只要能区别出这个正确的类别,它就不再努力了;softmax分类器,虽然已经区别出来了,但还是要尽量把这个区别出来的概率接近到1.
- 损失本质是为了让正确的类别尽可能凸显出来,或者是与错误类别之间分值差异大,或者是正确类别概率更高,所谓的损失函数就是,在使这个损失尽可能降低的同时,正确类别所能获得分数更高。同时损失衡量的是数据有多么不好。一般情况,通过仔细研究这个损失函数,就能看到我们是怎么利用的这个数据的。
似然函数相关介绍
似然函数()反映的是给定一组观察样本X,这组观察样本是从所有样本中取出来的,最大似然估计的思想就是:既然我本身有这么多样本,结果你偏偏能取出这组样本,我就认为这组样本在给定下的概率是最大的。于是我通过写出似然函数并让这个函数值最大,此时得到的就是最有可能的 。
- 优化(Optimization),如何通过损失函数找到最优的参数,或者说如何使这个损失最小。
- 梯度下降法,梯度指向函数上升最快的方向,因此我们通过 -gradient 来找到下降最快的方向。计算梯度的方法:数值梯度法和解析梯度法,一种是通过梯度的定义去用近似的方式计算,一种是直接通过推导给出精确的计算梯度的方式。
- 数值梯度法,,梯度的shape是和W的shape(或者说参数的shape)是一样的,而现代的参数量动辄就几千万,这会导致计算量非常大,计算起来非常慢。
- 解析梯度法,通过牛顿莱布尼兹的微积分,我们直接给出了梯度的具体计算公式,因此我们通过这种方式进行梯度下降。
梯度下降
梯度下降(利用全部数据来更新一次参数)、随机梯度下降(利用一个数据来更新一次参数)、小批量梯度下降(利用mini-batch数据来更新一次参数)。由于梯度下降利用了全部的数据,所以它的更新速度非常慢,但是由于它看到的是全局的数据,据此计算的梯度就是准确的参数更新方向,因此他就是奔着那个下坡去的;而随机梯度下降,只看到某个特例,虽然它的更新速度很快,但他容易反复横跳(一会觉得这个方向是下坡,一会觉得那个方向是下坡),因此它不容易收敛,但是它很容易跳出局部最小值;小批量梯度下降结合了两者,当小批量的批量接近全部数据,此时就是梯度下降,当小批量为1就是随机梯度下降,他兼顾更新速度和跳出局部最小值的优点。
- 图像特征,在原来机器学习时,图像的分类,分为两个步骤,一个是图像特征提取(可能是颜色上的特征提取、边缘化的方向提取,也可能是一种图片词袋的提取),然后训练这个线性分类器;但是到了深度学习过程,这个特征提取也不需要人工提取了,直接在网络中就提取完了。q:为什么深度学习不需要提前进行特征提取?
04. Introduction to Neural Network
-
反向传播、计算图。相较于原本的解析梯度法,这里通过先列出计算图,前向传播进行计算,然后反向通过链式求导法则,一步步计算出最终输出相对于初始输入的梯度。这里的每个节点代表一种运算(也可以代表多种运算的集合eg:sigmoid由+、-、exp、1/x等组成,但是整体sigmoid的求导可以计算为这样就极大简化了运算过程q: 是不是神经网络的层的概念就有考虑到这个原因呢?另外强调一点,如果变量在前向传播的表达式中出现多次(即一个变量有多个分叉),那么反向传播时它的梯度是这些分叉梯度的累加和。
-
对于向量形式的反向传播。整体流程和标量形式的反向传播一致,只不过把标量的梯度,换成了雅可比矩阵(Jacobian Matrix)。雅可比矩阵反映了每个y(m维)对每个x(n维)的求偏导,因此他应该是mxn维的,这只是一个数据的,实际上是batch-size的数据,比如batch-size为100则实际上的雅可比矩阵为100m*100n,非常大。因此实际上写出的雅可比矩阵的shape是和X的shape一致的,这反映了每个X在哪个方向上上升的最快。
-
神经网络。q:什么是神经网络?神经网络与之前计算图中的计算节点之间有什么关系?神经网络中的隐藏层代表着什么含义?
- 神经网络的组成基本单位是神经元,各个神经元组成了输入层、隐藏层、输出层;这些层之间通过权重(W,b)进行连接,W和b构成了神经网络的参数。在我看来,每个神经元其实就是个值,一层神经网络就是多个值叠在一起,玩神经网络就是玩数据,最初的神经网络就是最初的数据,通过中间的连接以及激活函数不断操作,配合损失函数赋予这个值意义,使得最终输出满足这个意义。
- 计算节点它是有具体计算功能的,从这一点来看很难严格匹配上神经网络中的具体实体,可能和神经元之间的连接有点类似吧。计算图只是说明了反向传播的原理,首先将原式分解成基本的一个个式子,计算所有的中间值,然后利用链式法则,倒推所有的梯度。
- 我认为,以线性分类为例,隐藏层干的事和最后输出层干的事没什么不同,只不过隐藏层的神经元更多了,原本输出层我只要10个神经元代表着10类,现在隐藏层弄了100个神经元,那就代表着100种分类嘛,因此隐藏层它分的就更加具体更加细致,但是我最终只要10类,那从隐藏层到输出层,就代表着根据现有分的100种分类再重新凝练一下形成10种分类。
05. Thoughts while working with the assignment 1
-
q:在计算梯度的时候,明明我好像是按照每个样本为一行计算的梯度,并没有像loss一样有显示的多个损失累加,那为什么最后计算的梯度要除以N呢?
- 首先要搞明白我们计算的梯度实际上是对整个损失来求的梯度,既然整个损失是累加的,那对整个梯度来说,肯定需要除以N。更新的时候是用梯度乘原本的x来进行更新,而梯度的意义代表着每个x在该梯度方向上增长最快,从总体来看,在更新的时候会利用到所有的x以及对应的梯度,而这些梯度是各个批次样本对应损失的梯度,因此在更新时,应该乘这个梯度的1/N。可能还有点抽象,不过只要你想明白为什么需要1/N,因为我们想要用多个批次来代表一个批次,因此会有一个取平均的过程,所以当涉及到从整体来看的时候,就会要乘1/N。
- 这里又重新思考了一下,我们回归梯度的本质,梯度就是损失对参数的导数,因为我求得的损失是多个batch的即有batch个损失,每个损失都对应一个梯度,而我只更新一次,因此最终的更新梯度就是所有损失梯度的均值。
-
正则化损失的目的:引入正则化损失是为了让参数尽可能的小,所以说损失应该加在参数上,而不是什么softmax后的分数之类的东西上。包括对正则化损失对应的梯度,都在参数上。另外,正则化损失的超参数一般情况用reg来表示,之所以平常有个0.5 * reg,是为了求导数的时候好算。
-
在进行反向传播的时候,我们经常提到的上游dout,其实指的是dx,当然这么说有点绝对。这里只是提供一种理解方式,根本的去找上游dout的方法还是画出计算图就看明白了,这里的x其实代指着中间结果,并不完全就是最初的x。