CS231n KNN Assignment 1算法总结

CS231n KNN Assignment 1算法总结

1.数据驱动方法:train—precdict 模式

编写k_nearest_neighbor.py这个utils文件:

import numpy as np

class KNearestNeighbor(object):

  def __init__(self):
    pass

  def train(self, X, y):
    Train the classifier. 
    
  def predict(self, X, k=1, num_loops=0):
    Predict labels for test data using this classifier.
    return ...

2.检测代码运行速度

def time_function(f, *args):
    """
    Call a function f with args and return the time (in seconds) that it took to execute.
    """
    import time
    tic = time.time()
    f(*args)
    toc = time.time()
    return toc - tic
  • f 是需要检测的函数,args是传递给函数f 的参数。

3.matplotlib

  • plt.imshow(X)
import Matplotlib.pyplot as plt
plt.imshow(X)
plt.show()

其中,X的shape如下:
CS231n KNN Assignment 1算法总结
第二种情况下,可以是float(在0.0和1.0之间,其实就是int/255)或者int(0到255之间)。

  • plt.subplot(n,m,j):一共分为n*m个区域,现在画第j个

4.Numpy.flatnonzero()

  • Numpy.flatnonzero() : 该函数输入一个矩阵,返回扁平化后矩阵中非零元素的位置,直接返回array形式,np.nonzero()和np.where()则是返回tuple。
>>> x = np.arange(-2, 3)
>>> x
array([-2, -1,  0,  1,  2])
>>> np.flatnonzero(x)
array([0, 1, 3, 4])
>>>d = np.array([1,2,3,4,4,3,5,3,6])
>>>haa = np.flatnonzero(d == 3)
>>>print(haa)
array([2 5 7])

5.np.nonzero()

返回数组a中非零元素的索引值数组。

  • 只有a中非零元素才会有索引值,那些零值元素没有索引值;
  • 返回的索引值数组是一个2维tuple数组,该tuple数组中包含一维的array数组。其中,一维array向量的个数与a的维数是一致的。
  • 索引值数组的每一个array均是从一个维度上来描述其索引值。比如,如果a是一个二维数组,则索引值数组有两个array,第一个array从行维度来描述索引值;第二个array从列维度来描述索引值。
>>>a = np.array([[0,0,3],[0,0,0],[0,0,9]])
>>>b = np.nonzero(a)
>>>print(b)
(array([0, 2]), array([2, 2]))
>>>print(np.transpose(b))
array([[0, 2],
       [2, 2]])

说明:

  • a中有2个非零元素,因此,索引值tuple中array的长度为2。因为,只有非零元素才有索引值。
  • 索引值数组是2 维的。实际上,无论a的维度是多少,索引值数组一定是2维的tuple,但是tuple中的一维array个数和a的维数一致。
  • 第1个array([0, 2])是从row值上对3和9进行的描述。第2个array([2, 2])是从col值上对3和9的描述。这样,从行和列上两个维度上各用一个数组来描述非零索引值。
  • 通过调用np.transpose()函数,得出3的索引值是[0 2],即第0行,第2列。

6.numpy.where()

numpy.where() 有两种用法:

  • np.where(condition, x, y), 满足条件(condition),输出x,不满足输出y。如果是一维数组,相当于 [xv if c else yv for (c,xv,yv) in zip(condition,x,y)]
>>> aa = np.arange(10)
>>> np.where(aa,1,-1)
array([-1,  1,  1,  1,  1,  1,  1,  1,  1,  1])  # 0为False,所以第一个输出-1
>>> np.where(aa > 5,1,-1)
array([-1, -1, -1, -1, -1, -1,  1,  1,  1,  1])

>>> np.where([[True,False], [True,True]],    # 官网上的例子
             [[1,2], [3,4]],
             [[9,8], [7,6]])
array([[1, 8],
       [3, 4]])
  • np.where(condition): 只有条件 (condition),没有x和y,则输出满足条件 (即非0) 元素的坐标 (等价于 numpy.nonzero )。这里的坐标以tuple的形式给出,通常原数组有多少维,输出的tuple中就包含几个数组,分别对应符合条件元素的各维坐标。
>>> a = np.array([2,4,6,8,10])
>>> np.where(a > 5)             # 返回索引
(array([2, 3, 4]),)   
>>> a[np.where(a > 5)]              # 等价于 a[a>5]
array([ 6,  8, 10])

>>> np.where([[0, 1], [1, 0]])
(array([0, 1]), array([1, 0]))

上面这个例子条件中[[0,1],[1,0]]### 的真值为两个1,各自的第一维坐标为[0,1]### ,第二维坐标为[1,0]### 。

7.tuple和np.array相互转化

>>> b = (1,2)
>>> np.array(b)
array([1, 2])
>>> b = (np.array([1,2]),np.array([3,4]))
>>> np.array(b) #把最外层的tuple换成array
array([[1, 2],
       [3, 4]])
>>> np.transpose(b)
array([[1, 3],
       [2, 4]])
>>> b2 = np.array([1,2])
>>> tuple(b2)
(1, 2)
>>> b2 = np.array([[1,2],[3,4],[5,6]])
>>> tuple(b2) #把最外层的array去掉,换成tuple表达形式
(array([1, 2]), array([3, 4]), array([5, 6]))

8.List和np.array相互转化

>>> b = [1,2]
>>> np.array(b)
array([1, 2])
>>> b2 = np.array([[1,2],[3,4],[5,6]])
>>> [b2] #直接添加为新的list一部分,没有转换的意思
[array([[1, 2],
       [3, 4],
       [5, 6]])]
>>> list(b2) #将最外层的array去掉,换成list表达形式	
[array([1, 2]), array([3, 4]), array([5, 6])]
>>> 

9.List和tuple相互转化

>>> b
[1, 2]
>>> tuple(b)
(1, 2)
>>> list(tuple(b))
[1, 2]
>>> 

10.迭代器:iterable(名词),iterator 和 generator

  • 可以直接作用于for循环的对象统称为可迭代对象:Iterable。
    一类是集合数据类型,如list、tuple、dict、set、str、zip(返回tuple集合),等;一类是iterator。generator是一种特殊的iterator,包括生成器和带yield的generator function。iterator 可以用next(iterator)或者iterator.next()。
  • 列表生成器 [i for i in Iterable] 生成list, (i for i in Iterable) 生成generator.
  • set是类似dict的:{‘1’,‘2’,‘3’},但是没有索引,不能引用,可以去重复,所以用for可以依次取出不重复的元素.
  • Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的.

11.np.random.choice(a,b,replace=False)

  • 从a中选择b个数
  • replace为false意思数据取出后不再放入,之后取出的数据中肯定没有之前的数

#Mlliu/CS231n/Assignment1