cs231n_assignment1_配置作业环境+kNN

作业1:http://cs231n.github.io/assignments2017/assignment1/

我是在win7电脑上做的。

准备工作:

下载anaconda:https://www.anaconda.com/download/

打开前修改jupyter notebook启动目录:https://www.zhihu.com/question/31600197/answer/90214029


jupyter notebook --generate-config


修改完成后,打开anaconda prompt

cs231n_assignment1_配置作业环境+kNN

打开:jupyter notebook

cs231n_assignment1_配置作业环境+kNN


开始做作业

下载CIFAR-10数据库:http://www.cs.toronto.edu/~kriz/cifar.html,下载CIFAR-10 python version

解压到cs231n/datasets目录下,对每一个cell,shift+enter运行。

首先是加载数据:

cs231n_assignment1_配置作业环境+kNN

cs231n_assignment1_配置作业环境+kNN

由运行结果可以看出:

训练集50000张图片,每张图片是32*32*3的;测试集10000张图片,图片格式同上。

可视化数据集,每一个类随机选取7张图片:

cs231n_assignment1_配置作业环境+kNN

numpy.flatnonzero(a):返回非0元素的索引,a可以是一个表达式

>>> x = np.arange(-2, 3)
>>> x
array([-2, -1, 
0,  1,  2])
>>> np.flatnonzero(x)
array([0, 1, 3, 4])

可以使用它来提取非0元素:

>>> x.ravel()[np.flatnonzero(x)]

array([-2, -1,  1,  2])


numpy.random.choice(asize=Nonereplace=Truep=None):对一维数组a产生一个随机采样。size指的是输出形状,replace表示放回还是不放回。

均匀分布:

>>> np.random.choice(5, 3)
array([0, 3, 4])
>>> #This is equivalent tonp.random.randint(0,5,3)

自定义取样概率:

>>> np.random.choice(5, 3, p=[0.1, 0, 0.3, 0.6, 0])
array([3, 3, 0])

>>> aa_milne_arr = ['pooh','rabbit', 'piglet', 'Christopher', 'dog', 'cat']

>>>np.random.choice(aa_milne_arr, 5, replace=False, p=[0.2, 0.1, 0.1, 0.3, 0.1,0.2])

array(['dog', 'piglet', 'pooh','cat', 'rabbit'], dtype='<U11')



为了后面减少计算量,随机采样数据集,训练集采样5000张,测试集采样500张:

cs231n_assignment1_配置作业环境+kNN

将32*32*3的图片reshape成一行:

cs231n_assignment1_配置作业环境+kNN

numpy.reshape(anewshapeorder='C')

np.reshape(a, (a.shape[1], a.shape[0])):转置等同于np.transpose(a)

当数据的形状不确定时,如果想转换为1行,列数不确定的话,newshape可以传入(1, -1); 

如果想转换为1列,行数不确定的话,newshape可以传入(-1, 1); 

同理如果是2列或者2行的话,就是(-1, 2)或者(2-1) -1代表不确定


导入k近邻分类器模块:

cs231n_assignment1_配置作业环境+kNN

利用两层循环计算L2距离:

cs231n_assignment1_配置作业环境+kNN

-->

cs231n_assignment1_配置作业环境+kNN

xrange() 函数用法与 range 完全相同,所不同的是生成的不是一个数组,而是一个生成器。Python3取消了xrange,只保留range

NoModuleErrorNo module named 'past',需要安装future包,在anacondaenvironment里安装

cs231n_assignment1_配置作业环境+kNN

可视化距离矩阵:

cs231n_assignment1_配置作业环境+kNN


knn不需要训练,直接进行预测,k=1:

cs231n_assignment1_配置作业环境+kNN

-->

cs231n_assignment1_配置作业环境+kNN

numpy.argsort(aaxis=-1kind='quicksort'order=None)

排序,得到前k个近邻的标签,然后得到投票结果

numpy.bincount(xweights=Noneminlength=0)

对一维数组x统计各值出现的次数,x里必须是非负整数

numpy.argmax(aaxis=Noneout=None)返回最大值

ValueError: object toodeep for desired array,关闭重启

再令k=5预测:

cs231n_assignment1_配置作业环境+kNN

精度比k=1时稍高。


在一个loop中完成L2距离计算,并用F范数与两个loop时的结果比较验证正确性:

cs231n_assignment1_配置作业环境+kNN

-->

cs231n_assignment1_配置作业环境+kNN

利用numpy数组运算的特性(broadcast),自动进行维数扩展

cs231n_assignment1_配置作业环境+kNN


不使用loop计算L2距离:

cs231n_assignment1_配置作业环境+kNN

-->

cs231n_assignment1_配置作业环境+kNN

就是将距离函数拆开,完成各个单项后再合并

x - y^2 = x^2 - 2*x*y + y^2


a.dot(b) 与 np.dot(a,b)效果相同

numpy.sum():

keepdims :bool, optional

If this is set to True, the axes which are reduced are left in theresult as dimensions with size one. With this option, the result will broadcastcorrectly against the input array.

例如:

>>> b

array([[1, 2],

       [3, 4],

       [5, 6]])

 

>>> np.sum(b,axis=1,keepdims = True)

array([[ 3],

       [ 7],

       [11]])

>>> np.sum(b,axis=1)

array([ 3,  7, 11])

比较三种方法的优劣,高下立现

cs231n_assignment1_配置作业环境+kNN


交叉验证:

将训练集分成5等分,同时观察不同的k下的分类精度:

cs231n_assignment1_配置作业环境+kNN

numpy.split(aryindices_or_sectionsaxis=0)

Split an array into multiple sub-arrays.

>>> x = np.arange(9.0)
>>> np.split(x,3)
[array([ 0., 
1.,  2.]), array([ 3.,  4., 5.]), array([ 6.,  7.,  8.])]

 

>>> x = np.arange(8.0)
>>> np.split(x,[3, 5, 6, 10])
[array([ 0., 
1.,  2.]),
 array([ 3.,  4.]),
 array([ 5.]),
 array([ 6.,  7.]),
 array([], dtype=float64)]


执行5次kNN算法,将其中一份数据作为验证集,其他作为测试集,取测试集的精度:

cs231n_assignment1_配置作业环境+kNN

cs231n_assignment1_配置作业环境+kNN

取平均精度,画出k-精度图:

cs231n_assignment1_配置作业环境+kNN

可以看出,kNN的分类精度高也就30%,不实用。

最佳k咱们取10:

cs231n_assignment1_配置作业环境+kNN

精度28.2%.