zoukankan      html  css  js  c++  java
  • CS231n 2016 通关 第二章-KNN 作业分析

    KNN作业要求:

    1、掌握KNN算法原理

    2、实现具体K值的KNN算法

    3、实现对K值的交叉验证

    1、KNN原理见上一小节

    2、实现KNN

      过程分两步:

        1、计算测试集与训练集的距离

        2、通过比较label出现比例的方式,确定选取的最终label

      代码分析:

      cell1 - cell5 对数据的预处理

      cell6创建KNN类,初始化类的变量,此处是传递测试数据和训练数据

      cell7实现包含两个循环的KNN算法:

        通过计算单一的向量与矩阵之间的距离(在之前的cell中,已经将图像转换成列:32*32 的图像转换为 1*3072,,

        测试集是500张:500*3072,训练集是5000张:5000*3072)

      代码基础:使用python 2.7.9 + numpy 1.11.0

      技巧:使用help 查看相关函数的用法,或者google

        举例:np.square 

              

          q 键退出help      

          

          可知,np.square() 为了加快运算速度,是用c写的,在这里查不到具体用法。google查看:

          

            例子为计算数组[-1j,1]里边各元素的平方,得到的结果为[-1,1]

      代码:实现compute_distances_two_loops(self, X)

     1   def compute_distances_two_loops(self, X):
     2     """
     3     Compute the distance between each test point in X and each training point
     4     in self.X_train using a nested loop over both the training data and the 
     5     test data.
     6 
     7     Inputs:
     8     - X: A numpy array of shape (num_test, D) containing test data.
     9 
    10     Returns:
    11     - dists: A numpy array of shape (num_test, num_train) where dists[i, j]
    12       is the Euclidean distance between the ith test point and the jth training
    13       point.
    14     """
    15     num_test = X.shape[0]
    16     num_train = self.X_train.shape[0]
    17     dists = np.zeros((num_test, num_train))
    18     for i in xrange(num_test):
    19       for j in xrange(num_train):
    20         #####################################################################
    21         # TODO:                                                             #
    22         # Compute the l2 distance between the ith test point and the jth    #
    23         # training point, and store the result in dists[i, j]. You should   #
    24         # not use a loop over dimension.                                    #
    25         #####################################################################
    26         dists[i,j] = np.sqrt(np.sum(np.square(X[i,:]-self.X_train[j,:])))
    27         #####################################################################
    28         #                       END OF YOUR CODE                            #
    29         #####################################################################
    30     return dists

        实现对一张测试图像对应的矩阵与一张训练集图像的矩阵做L2距离。

        也可以用numpy.linalg.norm函数实现:

          此函数执行的公式:

          所以核心代码可以写作:

            dists[i,j] = np.linalg.norm(self.X_train[j,:]-X[i,:])

      cell8 得到的距离可视化,白色表示较大的距离值,黑色是较小距离值

      cell9 实现K=1的label预测

      代码:实现 classifier.predict_labels()

     1   def predict_labels(self, dists, k=1):
     2     """
     3     Given a matrix of distances between test points and training points,
     4     predict a label for each test point.
     5 
     6     Inputs:
     7     - dists: A numpy array of shape (num_test, num_train) where dists[i, j]
     8       gives the distance betwen the ith test point and the jth training point.
     9 
    10     Returns:
    11     - y: A numpy array of shape (num_test,) containing predicted labels for the
    12       test data, where y[i] is the predicted label for the test point X[i].  
    13     """
    14     num_test = dists.shape[0]
    15     y_pred = np.zeros(num_test)
    16     for i in xrange(num_test):
    17       # A list of length k storing the labels of the k nearest neighbors to
    18       # the ith test point.
    19       closest_y = []
    20       count = []
    21       #########################################################################
    22       # TODO:                                                                 #
    23       # Use the distance matrix to find the k nearest neighbors of the ith    #
    24       # testing point, and use self.y_train to find the labels of these       #
    25       # neighbors. Store these labels in closest_y.                           #
    26       # Hint: Look up the function numpy.argsort.                             #
    27       #########################################################################
    28       buf_labels = self.y_train[np.argsort(dists[i,:])]
    29       closest_y = buf_labels[0:k]
    30       #########################################################################
    31       # TODO:                                                                 #
    32       # Now that you have found the labels of the k nearest neighbors, you    #
    33       # need to find the most common label in the list closest_y of labels.   #
    34       # Store this label in y_pred[i]. Break ties by choosing the smaller     #
    35       # label.                                                                #
    36       #########################################################################
    37       #for j in closest_y :
    38       #  count.append(closest_y.count(j))
    39       #m = max(count)      
    40       #n = count.index(m)
    41       #y_pred[i] = closest_y[n]
    42       c = Counter(closest_y)
    43       y_pred[i] = c.most_common(1)[0][0]
    44       #########################################################################
    45       #                           END OF YOUR CODE                            # 
    46       #########################################################################
    47 
    48     return y_pred

            步骤:

              1.使用numpy.argsort对所以距离进行排序,得到排序后的索引。

              2.通过索引找到对应的label

              3.通过collection包的Counter,对label进行统计表示

              4.通过counter的Most common方法得到出现最多的label

      cell9 在计算完成后,同时实现了准确率的计算

      cell10 实现K =5的KNN

      cell11 实现compute_distances_one_loop(X_test)

      代码:

     1   def compute_distances_one_loop(self, X):
     2     """
     3     Compute the distance between each test point in X and each training point
     4     in self.X_train using a single loop over the test data.
     5 
     6     Input / Output: Same as compute_distances_two_loops
     7     """
     8     num_test = X.shape[0]
     9     num_train = self.X_train.shape[0]
    10     dists = np.zeros((num_test, num_train))
    11     for i in xrange(num_test):
    12       #######################################################################
    13       # TODO:                                                               #
    14       # Compute the l2 distance between the ith test point and all training #
    15       # points, and store the result in dists[i, :].                        #
    16       #######################################################################
    17       buf = np.square(self.X_train-X[i,:])
    18       dists[i,:] = np.sqrt(np.sum(buf,axis=1))      
    19       #######################################################################
    20       #                         END OF YOUR CODE                            #
    21       #######################################################################
    22     return dists

      并通过计算一个循环与两个循环分别得到的结果的差值平方,来衡量准确性。

      cell12 实现完全的数组操作,不使用循环

     1   def compute_distances_no_loops(self, X):
     2     """
     3     Compute the distance between each test point in X and each training point
     4     in self.X_train using no explicit loops.
     5 
     6     Input / Output: Same as compute_distances_two_loops
     7     """
     8     num_test = X.shape[0]
     9     num_train = self.X_train.shape[0]
    10     dists = np.zeros((num_test, num_train)) 
    11     #########################################################################
    12     # TODO:                                                                 #
    13     # Compute the l2 distance between all test points and all training      #
    14     # points without using any explicit loops, and store the result in      #
    15     # dists.                                                                #
    16     #                                                                       #
    17     # You should implement this function using only basic array operations; #
    18     # in particular you should not use functions from scipy.                #
    19     #                                                                       #
    20     # HINT: Try to formulate the l2 distance using matrix multiplication    #
    21     #       and two broadcast sums.                                         #
    22     #########################################################################
    23     #buf = np.tile(X,(1,num_train))
    24     buf = np.dot(X, self.X_train.T)
    25     buf_test = np.square(X).sum(axis = 1)
    26     buf_train = np.square(self.X_train).sum(axis = 1)
    27     dists = np.sqrt(-2*buf+buf_train+np.matrix(buf_test).T)
    28     #########################################################################
    29     #                         END OF YOUR CODE                              #
    30     #########################################################################
    31     return dists

      使用(a-b)2=a2+b2-2ab 的公式

      27行: 此时buf_test 为500*1数组  buf_train为5000*1的数组  需要得到500*5000的数组  此处通过构造矩阵的方式进行broadcast

      cell13 比较3种方案的执行效率

      cell14 交叉验证

      交叉验证的思想在上一节有解释过了

      代码:(其中带有注释)

     1 num_folds = 5
     2 k_choices = [1, 3, 5, 8, 10, 12, 15, 20, 50, 100]
     3 
     4 X_train_folds = []
     5 y_train_folds = []
     6 ################################################################################
     7 # TODO:                                                                        #
     8 # Split up the training data into folds. After splitting, X_train_folds and    #
     9 # y_train_folds should each be lists of length num_folds, where                #
    10 # y_train_folds[i] is the label vector for the points in X_train_folds[i].     #
    11 # Hint: Look up the numpy array_split function.                                #
    12 ################################################################################
    13 X_train_folds = np.array_split(X_train, num_folds)
    14 y_train_folds = np.array_split(y_train, num_folds)
    15 ################################################################################
    16 #                                 END OF YOUR CODE                             #
    17 ################################################################################
    18 
    19 # A dictionary holding the accuracies for different values of k that we find
    20 # when running cross-validation. After running cross-validation,
    21 # k_to_accuracies[k] should be a list of length num_folds giving the different
    22 # accuracy values that we found when using that value of k.
    23 k_to_accuracies = {}
    24 
    25 
    26 ################################################################################
    27 # TODO:                                                                        #
    28 # Perform k-fold cross validation to find the best value of k. For each        #
    29 # possible value of k, run the k-nearest-neighbor algorithm num_folds times,   #
    30 # where in each case you use all but one of the folds as training data and the #
    31 # last fold as a validation set. Store the accuracies for all fold and all     #
    32 # values of k in the k_to_accuracies dictionary.                               #
    33 ################################################################################
    34 for k in k_choices:
    35     k_to_accuracies[k] = []
    36 
    37 for k in k_choices:
    38     print 'evaluating k=%d' % k
    39     for j in range(num_folds):
    40         #get validation 
    41         X_train_cv = np.vstack(X_train_folds[0:j]+X_train_folds[j+1:])
    42         X_test_cv = X_train_folds[j]              
    43         y_train_cv = np.hstack(y_train_folds[0:j]+y_train_folds[j+1:])
    44         y_test_cv = y_train_folds[j]
    45         #train 
    46         classifier.train(X_train_cv, y_train_cv)
    47         dists_cv = classifier.compute_distances_no_loops(X_test_cv)
    48         #get accuracy
    49         y_test_pred = classifier.predict_labels(dists_cv, k)
    50         num_correct = np.sum(y_test_pred == y_test_cv)
    51         accuracy = float(num_correct) / num_test
    52         #add j th accuracy of k to array
    53         k_to_accuracies[k].append(accuracy)
    54 ################################################################################
    55 #                                 END OF YOUR CODE                             #
    56 ################################################################################
    57 
    58 # Print out the computed accuracies
    59 for k in sorted(k_to_accuracies):
    60     for accuracy in k_to_accuracies[k]:
    61         print 'k = %d, accuracy = %f' % (k, accuracy)

      cell15 显示k值对应的准确率

      上述包含了均值和标准差

      cell16 使用最优值,得到较好的准确率

    总结:

      整体来说,第一个作业难度较大,主要难度不是在算法部分,而是在熟悉python相关函数与相应的用法方面。对于python大神而言,难度低。

      但是经过扎实的第一次作业后,后边的作业相对简单了。之后的作业细节方面讲解的少些。

    附:通关CS231n企鹅群:578975100 validation:DL-CS231n 

  • 相关阅读:
    cocos2dx中的定时器及其分类
    cocos中BatchNode精灵集合的使用
    cocos2dx中的坐标体系
    cocos2dx中的背景图层CCLayerColor和渐变图层CCLayerGradient
    精灵的属性Zorder的设置
    cocos2.2.3中创建精灵对象的三大类方法
    什么是差值查找?
    vs2013中头文件中大小写的切换的快捷键
    ARM基础:为何C语言(的函数调用)需要堆栈,而汇编语言却不需要堆栈
    ARM基础:MMU 异常向量表 重映射
  • 原文地址:https://www.cnblogs.com/wangxiu/p/5655622.html
Copyright © 2011-2022 走看看