cs231n-assignment1-knn
2018-03-18 21:19
267 查看
之前准备把所有的问题都写在一个博客里面,我发现实在太长了,所以就把作业一的问题都分开了!
part0:环境的安装和配置
part1:KNN,
part2:SVM
part3:softmax
part4:two_layer_net
part5:feature
part1:KNN
现在就part1进行解释与说明:
一、建议写之前先阅读下面的材料:http://cs231n.github.io/classification/
二、KNN的解释说明
KNN是一个简单的分类器,它包含下面的三个步骤:
step1:读取我们的训练数据,也就是简单的存储;
step2:测试,对于每一张测试的图片,我们将他和所有的训练集的每一个样本计算L2距离,找出离得最近的k张,然后我们将这k张里面出现次数最多的作为这个测试样本的标签;
step3:我们会通过交叉验证集来选择最佳的k值。
三、对于代码的解释和说明
knn.ipynb:
In[1]:
In[2]:
输出:
In[3]:
np.flatnonzero(a):返回的是flatten version of a中非零元素的下标;选出y与y_train里面元素相同的下标
np.randomchoice(a,size,replace=True,p=None):随机的选择属于y类别的七个图片进行显示
a:可以是int,那么就是在np.arange(a)里面选择出size个元素,要么是一个数组,从数组中选择出size个元素
size:选择出元素的个数
replace:如果为True,那么每次选出的元素再放回去,可以选出重复的元素;但是如果为False,不重复
p:以概率p选出元素
结果显示:
In[4]:选出前5000个训练集样本和前500个测试集样本
In[5]:
结果:
这里的5000,500就是之前说的训练集和测试集的大小
In[6]:
In[7]:K_nearest_neighbor.py文档里面的补全代码在之后会介绍!!!
结果:输出的是dist的大小,很显然是这样的
In[8]:
结果显示:
问题一:上图的某些行和列很明显颜色变浅,深色代表距离小,浅色代表距离大。请问为什么某些行或者列的颜色明显变浅?
回答一:某些行颜色变浅,表示测试样本与所有训练样本差异较大,该测试样本可能明显过亮或过暗或者有色差。
某些列颜色变浅,所有测试样本与该列表示的训练样本差异都较大,该训练样本可能明显过亮或过暗或者有色差。
In[9]:classifier.predict_labels
结果:我们希望得到的是27%的准确率
下面我们尝试的K=5的KNN,结果希望得到的稍微比27%多一点的准确率
In[10]:
结果:
In[11]:
np.linalg.norm()详见我的博客:http://blog.csdn.net/m0_37393514/article/details/79529168
结果:表示你的两个计算dists的函数得到的结果都是一样的!
In[12]:
结果:
In[13]:
结果:
下面我们需要通过交叉验证集来选择最佳的K:
In[14]:
np.vstack和np.hstack详见我的博客:http://blog.csdn.net/m0_37393514/article/details/79538748
np.array_split()详见我的博客:http://blog.csdn.net/m0_37393514/article/details/79537639
结果:
绘制关于k和交叉验证集的准确率的图表:
In[15]:
结果:
可以得到最佳的k=10
In[16]:
结果:
下面我们来仔细的介绍之前前面没有介绍的计算距离的三个函数:
k_nearest_neighbor.py:
两层循环很简单,我们不展开介绍了;就是使用np.linalg.norm()这个函数,
我的博客里面有介绍:http://blog.csdn.net/m0_37393514/article/details/79529168
一层循环是对于每一个测试样本与全部的训练样本整体进行计算,还是使用np.linalg,norm()函数,但是这里使用的是广播机制。
我的每一个测试样本X[i,:]大小是(1,D),而我们的训练样本的大小X_train->(num_train,D)的大小。我们是在D的方向上求得norm。
dist[i,:]->(1,num_train)
无循环的操作:其实不会写是抄的,看的网上大佬的解释,网页链接:http://blog.csdn.net/geekmanong/article/details/51524402
我整理了一下大神的说法,见下图:(记得补图)
所以对于我们的测试集X->(num_test,D),训练集self.X_train->(num_train,D),我们使用按位乘multiply,将数组对应的位置相乘,输出的
数组的大小与原数组相同。但是np.multiply(X,X)得到的大小是(num_test,D),np.multiply(self.X_train,self.X_train)的大小是
(num_train,D),而我们的-2×np.dot(X,self.X_train.T)是矩阵乘,对应的大小是(num_test,num_train)。根据我们上面的那个图可以
知道,我们一个测试样本对应一个训练样本的情况来说,X按位乘X我们需要沿着axis=1的方向上求和,这样得到的是一个(num_test,)的向量,
需要reshape为(num_test,1)这样的向量,同时那对于self.X_train按位乘self.X_train也是沿着axis方向上求和,得到的也是(num_train,)
的向量,需要reshape成(1,num_train)。在这样进行相加进行广播得到一个维度为(num_test,num_train)大小的dists。
广播机制详见某个大神博客:http://blog.csdn.net/weixin_39449570/article/details/78696991
part0:环境的安装和配置
part1:KNN,
part2:SVM
part3:softmax
part4:two_layer_net
part5:feature
part1:KNN
现在就part1进行解释与说明:
一、建议写之前先阅读下面的材料:http://cs231n.github.io/classification/
二、KNN的解释说明
KNN是一个简单的分类器,它包含下面的三个步骤:
step1:读取我们的训练数据,也就是简单的存储;
step2:测试,对于每一张测试的图片,我们将他和所有的训练集的每一个样本计算L2距离,找出离得最近的k张,然后我们将这k张里面出现次数最多的作为这个测试样本的标签;
step3:我们会通过交叉验证集来选择最佳的k值。
三、对于代码的解释和说明
knn.ipynb:
In[1]:
#预备代码 import random import numpy as np from cs231n.data_utils import load_CIFAR10 import matplotlib.pyplot as plt from __future__ import print_function # This is a bit of magic to make matplotlib figures appear inline in the notebook # rather than in a new window. %matplotlib inline#这句话会让matplotlib的画出现在notebook的页面上,而不是新建一个窗口 plt.rcParams['figure.figsize'] = (10.0, 8.0) # 设置默认的绘图窗口的大小 plt.rcParams['image.interpolation'] = 'nearest' plt.rcParams['image.cmap'] = 'gray' # 自动的重载Python的外部的模块 # see http://stackoverflow.com/questions/1907993/autoreload-of-modules-in-ipython %load_ext autoreload %autoreload 2
In[2]:
# 加载数据集 cifar10_dir = 'cs231n/datasets/cifar-10-batches-py' X_train, y_train, X_test, y_test = load_CIFAR10(cifar10_dir) # 打印出数据集的大小 print('Training data shape: ', X_train.shape) print('Training labels shape: ', y_train.shape) print('Test data shape: ', X_test.shape) print('Test labels shape: ', y_test.shape)
输出:
Training data shape: (50000, 32, 32, 3) Training labels shape: (50000,) Test data shape: (10000, 32, 32, 3) Test labels shape: (10000,)
In[3]:
np.flatnonzero(a):返回的是flatten version of a中非零元素的下标;选出y与y_train里面元素相同的下标
np.randomchoice(a,size,replace=True,p=None):随机的选择属于y类别的七个图片进行显示
a:可以是int,那么就是在np.arange(a)里面选择出size个元素,要么是一个数组,从数组中选择出size个元素
size:选择出元素的个数
replace:如果为True,那么每次选出的元素再放回去,可以选出重复的元素;但是如果为False,不重复
p:以概率p选出元素
#可视化数据集,我们对每一个类别选择出其中的七个进行数据的展示 classes = ['plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck'] num_classes = len(classes) samples_per_class = 7 for y, cls in enumerate(classes): idxs = np.flatnonzero(y_train == y) idxs = np.random.choice(idxs, samples_per_class, replace=False) for i, idx in enumerate(idxs): plt_idx = i * num_classes + y + 1 plt.subplot(samples_per_class, num_classes, plt_idx) plt.imshow(X_train[idx].astype('uint8')) plt.axis('off') if i == 0: plt.title(cls) plt.show()
结果显示:
In[4]:选出前5000个训练集样本和前500个测试集样本
# 为了跟高效的执行相应的代码,我们选择数据集的子集来进行训练和测试,这里选择的训练数是5000,测试数是500 num_training = 5000 mask = list(range(num_training)) X_train = X_train[mask] y_train = y_train[mask] num_test = 500 mask = list(range(num_test)) X_test = X_test[mask] y_test = y_test[mask]
In[5]:
# 将数据集的每一个样本原本是32*32*3的图片,拉成一个1*3072维度的向量 X_train = np.reshape(X_train, (X_train.shape[0], -1)) X_test = np.reshape(X_test, (X_test.shape[0], -1)) print(X_train.shape, X_test.shape)
结果:
(5000, 3072) (500, 3072)
这里的5000,500就是之前说的训练集和测试集的大小
In[6]:
from cs231n.classifiers import KNearestNeighbor #创建一个KNN的实例,但是我们的训练过程仅仅单独的进行数据的存储,而不会进行计算 classifier = KNearestNeighbor() classifier.train(X_train, y_train)
In[7]:K_nearest_neighbor.py文档里面的补全代码在之后会介绍!!!
# 在 cs231n/classifiers/k_nearest_neighbor.py 这个文件里,需要我们补全代码 # 实现L2距离的计算,这里我们使用两层循环 # 我们传入的参数是我们的测试集,但是需要注意的是,我们的测试集大小是Nte,训练集大小是Ntr,那我们输出的距离矩阵应该大小是Nte×Ntr。 dists = classifier.compute_distances_two_loops(X_test) print(dists.shape)
结果:输出的是dist的大小,很显然是这样的
(500, 5000)
In[8]:
# 我们显示距离矩阵,注意我们这里的每一行都是测试样本和距离训练样本的距离 plt.imshow(dists, interpolation='none') plt.show()
结果显示:
问题一:上图的某些行和列很明显颜色变浅,深色代表距离小,浅色代表距离大。请问为什么某些行或者列的颜色明显变浅?
回答一:某些行颜色变浅,表示测试样本与所有训练样本差异较大,该测试样本可能明显过亮或过暗或者有色差。
某些列颜色变浅,所有测试样本与该列表示的训练样本差异都较大,该训练样本可能明显过亮或过暗或者有色差。
In[9]:classifier.predict_labels
传入的参数是我们之前用两层循环计算出来的距离dists,下面进行验证自己的代码是否正确:
# 使用K=1的KNN,可以看作是NN y_test_pred = classifier.predict_labels(dists, k=1) # 输出准确预测的样本数和准确率 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))
结果:我们希望得到的是27%的准确率
Got 137 / 500 correct => accuracy: 0.274000
下面我们尝试的K=5的KNN,结果希望得到的稍微比27%多一点的准确率
In[10]:
y_test_pred = classifier.predict_labels(dists, k=5) 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))
结果:
Got 139 / 500 correct => accuracy: 0.278000
In[11]:
np.linalg.norm()详见我的博客:http://blog.csdn.net/m0_37393514/article/details/79529168
# 你需要补全compute_distances_one_loop.py的代码,这里面只有一层循环更加的高效! dists_one = classifier.compute_distances_one_loop(X_test) #为了保证向量化的代码运行正确,我们将运行结果与前面的方法的结果进行对比。对比两个矩阵是否相等的方法有很多, # 比较简单的一种是使用Frobenius范数。 # Frobenius范数表示的是两个矩阵所有元素的差值的均方根。或者说是将两个矩阵reshape成向量后,它们之间的欧氏距离. difference = np.linalg.norm(dists - dists_one, ord='fro') print('Difference was: %f' % (difference, )) if difference < 0.001: print('Good! The distance matrices are the same') else: print('Uh-oh! The distance matrices are different')
结果:表示你的两个计算dists的函数得到的结果都是一样的!
Difference was: 0.000000 Good! The distance matrices are the same
In[12]:
# 完成compute_distances_no_loops函数的代码,实现无循环的计算dists dists_two = classifier.compute_distances_no_loops(X_test) # 还是比较与之前计算的dists的差,看看结果正确否 difference = np.linalg.norm(dists - dists_two, ord='fro') print('Difference was: %f' % (difference, )) if difference < 0.001: print('Good! The distance matrices are the same') else: print('Uh-oh! The distance matrices are different')
结果:
Difference was: 0.000000 Good! The distance matrices are the same
In[13]:
# 查看对比几个计算dists的函数所花销的时间 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 two_loop_time = time_function(classifier.compute_distances_two_loops, X_test) print('Two loop version took %f seconds' % two_loop_time) one_loop_time = time_function(classifier.compute_distances_one_loop, X_test) print('One loop version took %f seconds' % one_loop_time) no_loop_time = time_function(classifier.compute_distances_no_loops, X_test) print('No loop version took %f seconds' % no_loop_time) # 毋庸置疑,肯定是完全的向量化的操作最快
结果:
Two loop version took 33.193914 seconds One loop version took 62.247426 seconds No loop version took 0.503530 seconds
下面我们需要通过交叉验证集来选择最佳的K:
In[14]:
np.vstack和np.hstack详见我的博客:http://blog.csdn.net/m0_37393514/article/details/79538748
np.array_split()详见我的博客:http://blog.csdn.net/m0_37393514/article/details/79537639
num_folds = 5 k_choices = [1, 3, 5, 8, 10, 12, 15, 20, 50, 100] X_train_folds = [] y_train_folds = [] ##################################################################################### # 将数据分成num_folds份,存入X_train_folds和y_train_folds,y_label_folds[i]是一个标签向量, # 表示对应于X_label_folds[i]中的那些点标签! 提示: 可以尝试使用numpy的array_split方法 ##################################################################################### X_train_folds = np.array_split(X_train, num_folds) y_train_folds = np.array_split(y_train, num_folds) ################################################################################ # END OF YOUR CODE # ################################################################################ # 一个字典k_to_accurracies表示我们在交叉验证集上运行k的knn的时候的准确率的大小 # k_to_accuracies[k]表示,当我们选择k时,我们对于每一个num_folds个交叉验证集的某个folds # 为测试样本的时算出来的准确率,也就是说是一个大小为num_folds的lists k_to_accuracies = {} ################################################################################ # 对于每一个可能的k值,运行num_folds次knn算法,每一次你使用其中的num_folds-1个作为训练集, # 剩下的那个作为验证集,将结果保存在K_to_accuracies中 # ################################################################################ for k in k_choices: k_to_accuracies[k] = [] for i in range(num_folds): X_train_cv = np.vstack(X_train_folds[:i] + X_train_folds[i + 1:]) X_test_cv = X_train_folds[i] y_train_cv = np.hstack(y_train_folds[:i] + y_train_folds[i + 1:]) y_test_cv = y_train_folds[i] classifier.train(X_train_cv, y_train_cv) dists_cv = classifier.compute_distances_no_loops(X_test_cv) y_pred = classifier.predict_labels(dists_cv, k) num_correct = np.sum(y_pred == y_test_cv) accuracy = float(num_correct) / y_test_cv.shape[0] k_to_accuracies[k].append(accuracy) ################################################################################ # END OF YOUR CODE # ################################################################################ # 打印计算出的准确率 for k in sorted(k_to_accuracies): for accuracy in k_to_accuracies[k]: print('k = %d, accuracy = %f' % (k, accuracy))
结果:
k = 1, accuracy = 0.263000 k = 1, accuracy = 0.257000 k = 1, accuracy = 0.264000 k = 1, accuracy = 0.278000 k = 1, accuracy = 0.266000 k = 3, accuracy = 0.239000 k = 3, accuracy = 0.249000 k = 3, accuracy = 0.240000 k = 3, accuracy = 0.266000 k = 3, accuracy = 0.254000 k = 5, accuracy = 0.248000 k = 5, accuracy = 0.266000 k = 5, accuracy = 0.280000 k = 5, accuracy = 0.292000 k = 5, accuracy = 0.280000 k = 8, accuracy = 0.262000 k = 8, accuracy = 0.282000 k = 8, accuracy = 0.273000 k = 8, accuracy = 0.290000 k = 8, accuracy = 0.273000 k = 10, accuracy = 0.265000 k = 10, accuracy = 0.296000 k = 10, accuracy = 0.276000 k = 10, accuracy = 0.284000 k = 10, accuracy = 0.280000 k = 12, accuracy = 0.260000 k = 12, accuracy = 0.295000 k = 12, accuracy = 0.279000 k = 12, accuracy = 0.283000 k = 12, accuracy = 0.280000 k = 15, accuracy = 0.252000 k = 15, accuracy = 0.289000 k = 15, accuracy = 0.278000 k = 15, accuracy = 0.282000 k = 15, accuracy = 0.274000 k = 20, accuracy = 0.270000 k = 20, accuracy = 0.279000 k = 20, accuracy = 0.279000 k = 20, accuracy = 0.282000 k = 20, accuracy = 0.285000 k = 50, accuracy = 0.271000 k = 50, accuracy = 0.288000 k = 50, accuracy = 0.278000 k = 50, accuracy = 0.269000 k = 50, accuracy = 0.266000 k = 100, accuracy = 0.256000 k = 100, accuracy = 0.270000 k = 100, accuracy = 0.263000 k = 100, accuracy = 0.256000 k = 100, accuracy = 0.263000
绘制关于k和交叉验证集的准确率的图表:
In[15]:
# plot the raw observations for k in k_choices: accuracies = k_to_accuracies[k] plt.scatter([k] * len(accuracies), accuracies) # plot the trend line with error bars that correspond to standard deviation accuracies_mean = np.array([np.mean(v) for k,v in sorted(k_to_accuracies.items())]) accuracies_std = np.array([np.std(v) for k,v in sorted(k_to_accuracies.items())]) plt.errorbar(k_choices, accuracies_mean, yerr=accuracies_std) plt.title('Cross-validation on k') plt.xlabel('k') plt.ylabel('Cross-validation accuracy') plt.show()
结果:
可以得到最佳的k=10
In[16]:
#基于你找的最佳的k,你会得到超过28%的准确率 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))
结果:
Got 141 / 500 correct => accuracy: 0.282000
下面我们来仔细的介绍之前前面没有介绍的计算距离的三个函数:
k_nearest_neighbor.py:
import numpy as np from past.builtins import xrange class KNearestNeighbor(object): """ 使用L2来进行KNN算法 """ def __init__(self): pass def train(self, X, y): """ 在训练数据的时候,knn仅仅完成记忆的功能,而不会实现进行其他的一些处理 输入: -X:一个大小为(num_train,D)的数组作为训练数据集,包含num_train个样本,每个样本都是D维度 -y:数组的大小是(N,)包含的训练样本的标签,y[i]是X[i]的标签 """ self.X_train = X self.y_train = y def predict(self, X, k=1, num_loops=0): """ 使用knn分类器进行对测试集的预测 输入: - X:是一个大小为(num_test,D)的数组,包含num_test个测试样本,每一个测试样本的维度是D - K:KNN选择的K - num_loops: 决定计算dists是采用几层的循环 返回: - y: 一个数组大小为(num_test,),是为了测试集输出的标签的大小,y[i]表示X[i]的预测的类别的结果 """ if num_loops == 0: dists = self.compute_distances_no_loops(X) elif num_loops == 1: dists = self.compute_distances_one_loop(X) elif num_loops == 2: dists = self.compute_distances_two_loops(X) else: raise ValueError('Invalid value %d for num_loops' % num_loops) return self.predict_labels(dists, k=k) def compute_distances_two_loops(self, X): """ 计算X(测试集)的每一个样本和self.X_train的每一个样本的之间的距离,使用两层循环 输入: - X: 一个大小为(num_test,D)的测试集 返回: - dists: 一个大小为(num_test,num_train)的距离矩阵,dists[i][j]表示第i个测试样本和第j个训练样本之间的欧氏距离 """ num_test = X.shape[0] num_train = self.X_train.shape[0] dists = np.zeros((num_test, num_train)) for i in xrange(num_test): for j in xrange(num_train): ##################################################################### # TODO: # # Compute the l2 distance between the ith test point and the jth # # training point, and store the result in dists[i, j]. You should # # not use a loop over dimension. # ##################################################################### dists[i][j] = np.linalg.norm(X[i] - self.X_train[j]) ##################################################################### # END OF YOUR CODE # ##################################################################### return dists def compute_distances_one_loop(self, X): """ Compute the distance between each test point in X and each training point in self.X_train using a single loop over the test data. Input / Output: Same as compute_distances_two_loops """ num_test = X.shape[0] num_train = self.X_train.shape[0] dists = np.zeros((num_test, num_train)) for i in xrange(num_test): ####################################################################### # 计算第i个测试样本和所有的训练样本的之间的欧氏距离存放在dists[i,:] ####################################################################### dists[i, :] = np.linalg.norm(X[i, :] - self.X_train[:], axis=1) ####################################################################### # END OF YOUR CODE # ####################################################################### return dists def compute_distances_no_loops(self, X): """ Compute the distance between each test point in X and each training point in self.X_train using no explicit loops. Input / Output: Same as compute_distances_two_loops """ num_test = X.shape[0] num_train = self.X_train.shape[0] dists = np.zeros((num_test, num_train)) ######################################################################### # 计算我们的欧氏距离不使用循环 # # 不允许使用scipy中的函数,只允许使用基础的数组操作. # # 提示:可以使用矩阵乘法和两次广播求和 ######################################################################### dists += np.sum(np.multiply(X, X), axis=1, keepdims=True).reshape(num_test, 1) dists += np.sum(np.multiply(self.X_train, self.X_train), axis=1, keepdims=True).reshape(1, num_train) dists += -2 * np.dot(X, self.X_train.T) dists = np.sqrt(dists) ######################################################################### # END OF YOUR CODE # ######################################################################### return dists def predict_labels(self, dists, k=1): """ 给定测试样本和训练样本之间的距离,求解每一个测试样本的标签 输入:dists,大小为(num_test,num_train) 返回: - y,大小为(num_test,),y[i]表示预测的X[i]的类别 """ num_test = dists.shape[0] y_pred = np.zeros(num_test) for i in range(num_test): # 用来存储距离当前第i个测试样本前k个最近的样本的标签 closest_y = [] ######################################################################### # 使用距离矩阵dists来找到距离第i个测试样本最近的k个样本,使用self.y_train来取出这些 # 标签存放到closest_y中 # # 暗示:使用numpy.argsort # ######################################################################### closest_y = self.y_train[np.argsort(dists[i])[:k]] ######################################################################### # 现在你肯定实现了得到距离最近的k个训练样本的标签,你需要找到那个出现次数最多的那个标签# # 存入y_pred[i]中 # ######################################################################### y_pred[i] = np.argmax(np.bincount(closest_y)) ######################################################################### # END OF YOUR CODE # ######################################################################### return y_pred
两层循环很简单,我们不展开介绍了;就是使用np.linalg.norm()这个函数,
我的博客里面有介绍:http://blog.csdn.net/m0_37393514/article/details/79529168
一层循环是对于每一个测试样本与全部的训练样本整体进行计算,还是使用np.linalg,norm()函数,但是这里使用的是广播机制。
我的每一个测试样本X[i,:]大小是(1,D),而我们的训练样本的大小X_train->(num_train,D)的大小。我们是在D的方向上求得norm。
dist[i,:]->(1,num_train)
无循环的操作:其实不会写是抄的,看的网上大佬的解释,网页链接:http://blog.csdn.net/geekmanong/article/details/51524402
我整理了一下大神的说法,见下图:(记得补图)
所以对于我们的测试集X->(num_test,D),训练集self.X_train->(num_train,D),我们使用按位乘multiply,将数组对应的位置相乘,输出的
数组的大小与原数组相同。但是np.multiply(X,X)得到的大小是(num_test,D),np.multiply(self.X_train,self.X_train)的大小是
(num_train,D),而我们的-2×np.dot(X,self.X_train.T)是矩阵乘,对应的大小是(num_test,num_train)。根据我们上面的那个图可以
知道,我们一个测试样本对应一个训练样本的情况来说,X按位乘X我们需要沿着axis=1的方向上求和,这样得到的是一个(num_test,)的向量,
需要reshape为(num_test,1)这样的向量,同时那对于self.X_train按位乘self.X_train也是沿着axis方向上求和,得到的也是(num_train,)
的向量,需要reshape成(1,num_train)。在这样进行相加进行广播得到一个维度为(num_test,num_train)大小的dists。
广播机制详见某个大神博客:http://blog.csdn.net/weixin_39449570/article/details/78696991
相关文章推荐
- cs231n_assignment1_配置作业环境+kNN
- 关于CS231N-Assignment1-KNN中no-loop矩阵乘法代码的讲解
- cs231n_assignment1_KNN(2016版)
- cs231n:assignment1:KNN解答
- CS231n——Assignment1-KNN
- CS231n - CNN for Visual Recognition Assignment1 ---- KNN
- CS231n-assignment1(作业1)-knn
- cs231n-assignment1-kNN部分
- 【深度学习】cs231n-assignment1 - KNN
- CS231n--assignment 1--KNN
- cs231n课程作业assignment1(KNN)
- cs231n - assignment1 - linear-svm 梯度推导
- cs231n课程作业assignment1(SVM)
- cs231n 课程作业 Assignment 2
- CS231n学习笔记--Assignment2/3
- cs231n_assignment1_SVM
- cs231n_assignment1_two_layer_net
- cs231n:assignment1——Q3: Implement a Softmax classifier
- CS231n-Assignment1(作业1)-softmax
- cs231n - assignment1 - softmax 梯度推导