网上有作业参考:
1、知乎的
2、CSDN的CS231n课程学习笔记(一)——KNN的实现
目前是按照知乎上的来做的,做的过程中遇到一些问题和解决办法,现总结如下:
在终端输入
ipython notebook
或者
jupyter notebook
打开Jupyter。
Jupyter Notebook(此前被称为 IPython notebook)是一个交互式笔记本,支持运行 40 多种编程语言。Jupyter Notebook 的本质是一个 Web 应用程序,便于创建和共享文学化程序文档,支持实时代码,数学方程,可视化和 markdown。 用途包括:数据清理和转换,数值模拟,统计建模,机器学习等等。(Jupyter官方网站)
Jupyter简要操作方式:方式1、在单元格中写好代码后,点上面的“运行”进行运行程序,这仅仅运行一个单元格,好处是可以运行单个代码块,有bug可以及时更改;方式2、在每个单元格中写好代码后,点击“单元格”,会出现
继续点“运行所有单元格”,即可运行所有的单元格。
在写好整个程序后,想改为其他格式,选择“文件”–“下载”,点击相应格式的文件下载即可。
一些快捷键:
Jupyter Notebook 有两种键盘输入模式。编辑模式,允许你往单元中键入代码或文本;这时的单元框线是绿色的。命令模式,键盘输入运行程序命令;这时的单元框线是灰色。
Shift+Enter : 运行本单元,选中下个单元
Ctrl+Enter : 运行本单元
Alt+Enter : 运行本单元,在其下插入新单元
Y:单元转入代码状态
M:单元转入markdown状态
A :在上方插入新单元
B:在下方插入新单元
X:剪切选中的单元
Shift +V:在上方粘贴单元
将“ import cPickle as pickle ”改为“ import pickle as pickle”。
将“datadict = pickle.load(f)” 改为 “datadict = pickle.load(f,encoding=‘bytes’)”
load_cifar_batch(filename)函数其他修改如下:
def load_cifar_batch(filename):
""" load single batch of cifar """
with open(filename, 'rb') as f:
datadict = pickle.load(f,encoding='bytes')
X = datadict[b'data']
Y = datadict[b'labels']
X = X.reshape(10000, 3, 32, 32).transpose(0,2,3,1).astype("float")
Y = np.array(Y)
return X, Y
二、knn.py的修改
把“xrange()”改成range()
三、修改路径import numpy as np
from data_utils import load_cifar10
import matplotlib.pyplot as plt
from knn import KNearestNeighbor
x_train,y_train,x_test,y_test=load_cifar10('cifar-10-batches-py')
其中’cifar-10-batches-py’需要修改为自己的路径,我的路径名为’/home/djz/cs231n_assignment/assignment1/cs231n/datasets/cifar-10-batches-py’。
四、有一处错误,指正classifier=KNearestNeighbor()
classifier.train(x_train,y_train)
dists=classifier.cumpute_distances_two_loops(x_test)
print(dists)
第三行‘dists=classifier.cumpute_distances_two_loops(x_test)’里的cumpute修改为compute,不然会报错,估计这里是作者笔误。
五、交叉验证后用最好的K来完成预测任务出错“ValueError: object too deep for desired array”best_k=10
classifier=KNearestNeighbor()
classifier.train(x_train,y_train)
y_test_pred=classifier.predict(x_test,k=best_k)
num_correct=np.sum(y_test_pred==y_test)
accuracy=float(num_correct)/num_test
print('got %d / %d correct => accuracy: %f' % (num_correct,num_test,accuracy))
运行后会报错“ValueError: object too deep for desired array”,是因为bincount()函数的使用不对,解决办法有两种:
1、在knn.py中用numpy.squeeze()函数修改“closest_y”在“ y_pred[i]=np.argmax(np.bincount(closest_y)) ”上面添加里两行代码
if np.shape(np.shape(closest_y))[0] !=1: ############增加程序
closest_y=np.squeeze(closest_y) ############增加程序
呈现效果为:
def predict_labels(self,dists,k=1):
num_test=dists.shape[0]
y_pred=np.zeros(num_test)
for i in range(num_test):
closest_y=[]
y_indicies=np.argsort(dists[i,:],axis=0) #排序
closest_y=self.y_train[y_indicies[: k]]
if np.shape(np.shape(closest_y))[0] !=1: #增加的代码
closest_y=np.squeeze(closest_y) #增加的代码
y_pred[i]=np.argmax(np.bincount(closest_y))
return y_pred
2、把“closest_y”转化为一维向量
即把“ y_pred[i]=np.argmax(np.bincount(closest_y)) ”修改为
y_pred[i]=np.argmax(np.bincount(closest_y.reshape(len(closest_y))))
六、numpy里的arange()和reshape()的用法
arange()返回一个列表,reshape()将数组重新组成新维度的数组,shape()返回行数或列数。
arange():一个参数是终点;两个参数,第一个是起点,第二个是终点;三个参数,依次为起点、终点、步长。(默认步长为1)
reshape():
shape():(继续上面的运行)
感想:
1、knn算法的分类正确率很低,而且“训练快,测试慢”,不适合实际的需要,这是了解深度学习的工具,毕竟是传统的机器学习算法;
2、L1,L2 范数来进行像素比较是不够的,图像更多的是按背景和颜色被分类,而不是语义主体分身;
3、如果想要使K-NN算法实用,可以对数据特征进行normalize,让其均值为0,和单位方差。或者用PCA降维
附上交叉验证的结果: