CS231n assignment1 关键问题记录

pre

最近项目里需要用到DL相关的知识,所以我把原来下载好的cs231n的视频重新翻出来看了一遍,观看不练并没有什么效果,所以我在网上找到了课程之前发布的作业,我准备按照课程的进度逐步完成作业。由于最近时间比较紧张,我可能没有什么时间更新博客,不过这个课程的作业系列,我最终是会补完的。

这里采用的assignment1作业版本是cs231n 16年的1(一开始找错了),里面用到了一些python2的特性(如 xrange,print不需要括号),如果在python3的环境下使用,我们需要对源文件做一些修改。

Q&A by tasks

knn

关键问题
怎么理解knn
基于度量函数(这里一般默认采用欧式距离,也可看做L2距离)来评判两个特征向量的相似度,基于与输入向量最相近
的k个训练集上的特征向量的标签纸,采用投票法来决定输入向量的标签
如何采用矩阵的方法计算距离
1)首先回忆欧式距离的计算公式 np.sqrt( np.sum ( np.square(x1 - x2 )) )
2)np.square(x1 - x2 ) 可以被展开成 np.square(x1) - 2x1*x2 + np.square(x2)
注意这上面都是讨论的基于两个输入向量的计算公式
3)将2)中的公式推广到矩阵上就能得到我们需要的结果
dists = np.sqrt(np.sum(np.square(self.X_train),axis=1).T - 2* np.dot(X,self.X_train.T) + np.reshape(np.sum(np.square(X),axis=1),[X.shape[0],1]));

svm

关键问题
怎么理解svm
这里讨论多分类器下的SVM。针对每一个输出类别建立一个线性方程,最后可以写成 y = X.dot(W) + b, (y是一个 n*c的 矩阵,n表示输入个数,c表示类别个数)在训练的时候,我们要求针对每一个输入向量xi计算出来的结果yi (这是一个1*c的向量)满足其中yij要大于或者远大于其他分量(j是输入向量xi的正确标签,大于或者远大于这个标准是自由定义的,具体会在损失函数中体现),在这个标准下我们引入损失函数的概念,如果我们的分类器没有满足我们的要求(yij 远大于yi的其他分量),我们的模型就有了损失(不精确),我们定义一个损失函数来度量这种不精确,最后我们基于这样一个损失函数来调整模型,期望训练出来一个训练和验证集合上拥有最小损失的模型。
怎么理解前向传播和后向传播
我们这里可以理解为数据的流动方向。这两个概念是一个很广泛使用的概念,我们这里仅以SVM为例,说明这两个概念的含义。在我们计算 y = X.dot(W) + b的时候,我们将输入矩阵X映射成每条输入在每一个分类下的打分制y,这就是一个前向传播的概念,输入数据X沿着正向数据流将数据特征传递到输出数据中。然后在我们训练模型的过程中,我们根据输出数据y可以计算模型的损失函数Loss,根据偏导数,我们可以每一个参数的分析梯度,根据分析梯度我们可以对应的调整参数W和b,这就是一个反向传播的概念,训练损失Loss沿着反向数据流的方式将模型误差传递回模型参数中去。
怎么理解损失函数
损失函数是度量模型的不精确性的。基本公式为 Loss = (∑ Lossi) / n + λ R(W) . 前半部分是针对每一个输入用例的损失进行求和,然后通过平均操作移除训练集大小的影响。公式的后半部分是针对参数W的调整,λ是认为定义的正则化参数,在实践中需要手动调整,R(W)是针对模型参数W的正则化函数,常用的有L1正则化、L2正则化等,不同的正则化参数会使得模型参数W符合一定的要求,正则化参数R(W)从某种角度上约减的模型的解空间。
:怎么根据损失函数训练模型
最直接的方式采用计算梯度,我们通过将参数左右挪一点( e.g Wij + θ, Wij - θ,θ = 0.0001),然后计算模型的新的损失,然后用损失差值处于移动的范围就可以得到该参数的计算梯度。这个方法直截了当,但是计算成本很大。参考这样一个过程,我们可以联想到导数的计算过程,我们可以通过导数的计算方式来推导每一个参数的梯度,我们称之为分析梯度,这个方法速度相对这钱提升了好几个数量级,(但是我们这边需要注意,通常计算梯度和分析梯度近似,但是如果我们的损失函数在某个参数上的某些取值区间不可导,那么就会带来问题,这个由导数的定义引发,我们需要保证警惕)。得到梯度之后,我们可以 Wnew = Wold - learning_rat*gradient 来更新参数。最后还有一个值得注意的问题,由于我们的训练样本一般会很大,直接在训练样本上训练模型会消耗大量的资源问题,我们可以在每一次训练的时候随机选取batch_size个样本来训练模型,在训练充分之后,这样训练得到的模型收敛于基于整个训练原本训练得到的最佳模型。这样训练方法也被称之为随机梯度下降(SGD)

softmax

关键问题

怎么理解softmax

这是一个归一的公式, softmaxi = np.exp( score(yi)) / np.sum(np.exp(score)),基于之前的SVM模型我们来讨论softmax函数,我们采用svm可以xi在每个类别下的评分,在之前的过程中我们期望正确类别的评分大于其他的评分就可以了,softmax函数将问题转化成我们要求模式要是的xi得到的softmaxi值最大(也就是分类正确的概率最大)。从这样的一个设计初衷,我们知道,采用softmax的svm相对于普通的svm对训练数据更加敏感。

怎么根据softmax的损失函数来训练模型
这里的思路和普通的svm一致,只是损失函数定义不一致,引用[1] 中给出来的关键性的公式,引用[2]中给出了详细的推导过程,不过我相信各位也能自己直接推导出来
处理计算softmax值时np.exp()函数上溢的问题
在进行大量数值计算的时候,部分参数或者中间值会出现上溢或者下溢的问题。在根据 y = X.dot(W) + b,计算出score之后,我们需要针对矩阵中每一个值计算exp,这里非常容易出现上溢问题,这里我们通常采用在score矩阵的每一行减去该行的最大值,然后再进行之后的操作,这样一个行为相当于在计算Loss函数的时候针对log中表达式上下都乘以一个常数,并不影响最终的计算结果。在引用[2]中的代码就是在实现这样的功能
scores -= np.max(scores, axis = 1)[:, np.newaxis]
然后下溢的问题,这个可以通过检测异常值然后设定标准值取代的方式来规避,在实践中可以尝试一下。

Two-Layer Neural Network

关键问题

怎么理解两层神经网络

两层神经网络包含了一个输入层,一个隐藏层,一个输出层。三层以顺序的方式组织,层与层之间以全连接的形式联系,hiddenIn = X*W1 + b1 ,这是隐藏层的输入,hiddenOut = active(hiddenIn),通过激发函数,隐藏层产生输出, y = hiddenOut*W2+b2. 我们期望得到yij是yi所有分量下的最大值。yij是输入向量xi的正确分类的得分。(我们可以在这之后增加softmax,作业中也是这么要求的)

怎么计算反向传播
这里利用导数的传递性将模型误差逐层反向传播到各个参数中,我们可以沿着这个过程一次计算每公式的参数的偏导数矩阵。如果公式的导数过于复杂,可以参考cs231n的第4课时中给出来的图的方法来推导。这里不赘述细节
调整超参数的时候误差不断上升,或者很快nan了
这个问题很可能是训练速度learning_rate过大导致的,我们可以通过调小训练速度来解决。超参数都是不断尝试出来的,但是我们可以基于一定的经验加速这样的过程

Higher Level Representations: Image Features

我对图像处理不是很感兴趣,这部分没有写

代码地址

https://github.com/yueguangxuanyuan/cs231_assignment1

reference

[1] https://blog.csdn.net/zhangxb35/article/details/55223825
[2] https://blog.csdn.net/yc461515457/article/details/51924604

猜你喜欢

转载自blog.csdn.net/u010953266/article/details/80816971