在做cs231n作业一的knn时,遇到问题总结和解决办法

网上有作业参考:
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:在上方粘贴单元

一、data_utils.py 的修改

将“ 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降维
附上交叉验证的结果:
在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值