GitHub地址:https://github.com/ZJUFangzh/cs231n
使用KNN算法来完成图像识别,数据集用的是cifar10。
首先看一下数据集的维度
1 | # Load the raw CIFAR-10 data. |
可以看到,每一张图片是$32×32×3$,训练集有50000张,测试集有10000张
1 | Training data shape: (50000, 32, 32, 3) |
为了更够更快的计算,就选5000张做训练,500张做测试就好了
1 | # Subsample the data for more efficient code execution in this exercise |
而后把像素拉成3072的行向量
1 | # Reshape the image data into rows |
因为knn不需要训练,所以先存入数据:
1 | from cs231n.classifiers import KNearestNeighbor |
然后要修改k_nearest_neighbor.py
中的compute_distances_two_loops
这里套了两层循环,也就是比较训练集和测试集的每一张图片的间距:
1 | def compute_distances_two_loops(self, X): |
得到了一个$(500,5000)$的dists矩阵。
然后修改predict_labels
函数
1 | def predict_labels(self, dists, k=1): |
预测一下:
1 | # Now implement the function predict_labels and run the code below: |
结果是0.274
再试试k=5的结果,是0.278
然后再修改compute_distances_one_loop
函数,这次争取只用一个循环
1 | def compute_distances_one_loop(self, X): |
验证一下间距是
1 | Difference was: 0.000000 |
然后争取不用循环compute_distances_no_loops
,这一步比较难,想法是利用平方差公式$(x-y)^2 = x^2 + y^2 - 2xy$,使用矩阵乘法和二次广播,直接算出距离,注意矩阵的维度
1 | def compute_distances_no_loops(self, X): |
对比一下三种方法的时间,我这里不知道为什么two比one短,理论上是循环越少时间越短:
1 | Two loop version took 24.510484 seconds |
交叉验证
用交叉验证来找到最好的k
1 | num_folds = 5 |
画个图:
1 | # plot the raw observations |
1 | # Based on the cross-validation results above, choose the best value for k, |
得到最好的k=10,准确率是0.282
小结
- cs231n的作业比DeepLearning.ai的难多了,不是一个档次的,关键是提示比较少,所以自己做起来比较费劲
- 主要要学会向量化的运算,少用loop循环
- knn已经被淘汰了,这个作业只是让我们入门看看图像识别大概怎么做