趁着在学校的时间,跟着 cs231n 的课程做了一下作业,感觉收获特别大,现在汇总在博客里。下面是一些官方的课程资料:
网页 | 备注 |
---|---|
课程主页 | 主页课程介绍,浏览器也可以跑深度学习 |
课程官方笔记 | 貌似要 fq 软件支持 |
Syllabus | 课件、视频、课程安排表 |
还有一些其他有用的非官方资料:
网页 | 备注 |
---|---|
课程中文翻译 | 智能单元公众号提供的翻译 |
课程视频 | 网易云课堂提供 |
作业参考 | 来自 github@lightaime 的代码 |
我的作业代码请参考 github@Halfish/cs231n
完成 这里 的课程笔记中 Module 1: Neural Networks 的阅读。作业要求见 Assignment #1: Image Classification, kNN, SVM, Softmax, Neural Network,主要需要完成 kNN,SVM,Softmax分类器,还有一个两层的神经网络分类器的实现。
kNN 应该算法最简单的分类器了,读完课程文档 Image Classification: Data-driven Approach, k-Nearest Neighbor, train/val/test splits
和完成 knn.ipynb 的代码即可。
课程设置的很合理,需要依次完成两层循环、一层循环,最后完全用 numpy 的矩阵操作来实现逻辑。有点麻烦,但是都是因为对 numpy 不太熟悉,逻辑上其实没有什么难点。函数 compute_distances_no_loops 的三行代码 有点一时难以想到,不过看了别人代码也就很好理解了。
支持向量机和后面的 Softmax 分类器都是线性模型,这里只是损失函数不同罢了。阅读文档 Linear classification: Support Vector Machine, Softmax 大概就知道什么线性模型了。
对于 SVM 而言,分类器输入样本 xi 后,对第 j 个 类别的评分是:
反向传播就比较麻烦一点,因为要用随机梯度下降的迭代方法,所以要计算梯度。读完文档 Optimization: Stochastic Gradient Descent,可以找到 SVM 的梯度是:
具体需要完成 svm.ipynb 中的代码,具体的理论推导得出的梯度计算是否正确,会有 gradient check 的数值计算方式来检查。
Softmax 是和 SVM 一起对比介绍的,只是把 hinge Loss 换成 cross-entropy Loss,即交叉熵损失而已,如下:
而要算梯度就麻烦一点,课程文档里也没有给公式,我推了一下写在下边,如果有错误请读者批评指正,
在 Putting it together: Minimal Neural Network Case Study 里,构造了一个二维的数据集,用 Softmax 和 2-layer Neural Network 来做实验。完成 softmax.ipynb 的时候,计算 loss 和梯度都可以参考这篇笔记。
补充解释一下,前面的 loss function 是怎么来的呢?其实就是交叉熵。回忆一下交叉熵的公式, H(p,q)=−∑jpjlogqj ,其中向量 p 是原始的分布,这里指的是 ground-truth label,具体是 One-hot 编码结果。 q 则是模型预测的输出,可以看做是对 qj=efj∑jefj ,由于 p 里面一堆的零,那么显然只有 label 那项会保留下来。所以最后的结果就是 Li 。
再考虑交叉熵,因为 H(p,q)=H(p)+DKL(p∥q) ,而 H(p)=0 ,所以最小化交叉熵,其实就是最小化 KL 散度。也就是想让两个分布尽量相同。
上面是信息论的角度来看 Softmax,其实也可以用概率的角度来解释,即把结果看做是对每个类别预测分类的概率值, p(yi|xi;W)=efyi∑jefj ,因为有归一化的步骤,所以可以看做合法的概率值。
这部分内容较多一点,要完成三个文档,
对于这部分内容的理解,有很多重要的内容值得参考,可以参考我上一篇博文。
前向传播和计算 loss 的逻辑和 Softmax 分类器差不多,难点在于梯度的计算。因为要涉及 矩阵对矩阵 的梯度计算。可以参考课程笔记中 Gradients for vectorized operations 的内容。总结起来就是,通过矩阵的维度匹配来记忆梯度的计算规则。后向传播的梯度也是一层层计算下去的。注意 ReLU 的导数,我写作了:dhidden[hidden_layer <= 1e-5] = 0
,里面的 1e-5
而不是 0
,是为了避免精度损失带来的计算误差。
完成 two_layer_net.ipynb 中的代码。
这里讲的是提取特征,要补全的代码也是用来找最优参数的,模型的代码要跑很久而且感觉用处不大,所以就懒得写了。
后面的两次作业的博文见: