cs231n knn

# coding: utf-8

# In[19]:


import random
import numpy as np
from cs231n.data_utils import load_CIFAR10
import matplotlib.pyplot as plt

from __future__ import print_function

get_ipython().run_line_magic('matplotlib', 'inline')
plt.rcParams['figure.figsize'] = (10.0, 8.0) # set default size of plots
plt.rcParams['image.interpolation'] = 'nearest'
plt.rcParams['image.cmap'] = 'gray'

get_ipython().run_line_magic('load_ext', 'autoreload')
get_ipython().run_line_magic('autoreload', '2')


# In[20]:


cifar10_dir = 'cs231n/datasets/cifar-10-batches-py'
try:
   del X_train, y_train
   del X_test, y_test
   print('Clear previously loaded data.')
except:
   pass

X_train, y_train, X_test, y_test = load_CIFAR10(cifar10_dir)
print(X_train.shape,y_train.shape, X_test.shape, y_test.shape)


# In[21]:


num_training = 5000
mask = list(range(num_training))
X_train = X_train[mask]
y_train = y_train[mask]

num_test = 50 #500 #加快速度,取50测试
mask = list(range(num_test))
X_test = X_test[mask]
y_test = y_test[mask]
print('ok')


# In[22]:


# 三维转一维
print(X_train.shape, X_test.shape) # (5000, 32, 32, 3) (500, 32, 32, 3)
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)      32*32*3=3072


# In[109]:


class NearestNeighbor(object):

    def train(self, X, y):
        self.Xtrain = X
        self.ytr = y
########################################################################
# 直接预测
    def predict_l1(self, X): # 曼哈顿距离
        num_test = X.shape[0]
        Ypred = np.zeros(num_test, dtype = self.ytr.dtype)
        for i in range(num_test):
            distances = np.sum(np.abs(self.Xtrain - X[i,:]), axis = 1)  # L1
            min_index = np.argmin(distances) # get the index with smallest distance
            Ypred[i] = self.ytr[min_index] # predict the label of the nearest example
        return Ypred
        
    def predict_l2(self, X): # 欧氏距离
        num_test = X.shape[0]
        Ypred = np.zeros(num_test, dtype = self.ytr.dtype)
        for i in range(num_test):
            distances = np.sqrt(np.sum(np.square(self.Xtrain - X[i,:]), axis = 1))
            min_index = np.argmin(distances) # get the index with smallest distance
            Ypred[i] = self.ytr[min_index] # predict the label of the nearest example
        return Ypred
########################################################################
# 以下计算欧氏距离l2
    def compute_dist_2_loop(self,Xtest):
        train_len = self.Xtrain.shape[0]
        test_len = Xtest.shape[0]
        dists = np.zeros((test_len,train_len))
        for i in range(test_len):
            for j in range(train_len):
#                 dists[i][j] = np.sum(np.abs(self.Xtrain[j]-Xtest[i])) # l1
                dists[i][j] = np.sqrt( np.sum( np.square(self.Xtrain[j]-Xtest[i]) ) ) # l2
                # dists[i][j]    dists[i,j]
        return dists # 1203599820.3775597
    
    def compute_dist_1_loop(self,Xtest):
        train_len = self.Xtrain.shape[0] # 5000
        test_len = Xtest.shape[0]        # 50
        dists = np.zeros( (test_len, train_len) ) # 50*5000
        for i in range(test_len):
            dists[i] = np.sqrt(np.sum(np.square(self.Xtrain-Xtest[i]), axis=1))
            # dists[i,:]   dists[i]
#             dists[i,:] = np.linalg.norm(X[i,:]-self.X_train,axis=1) 
            #np.linalg.norm范式
#     https://blog.csdn.net/lanchunhui/article/details/51004387

        return dists # 1203599820.3775597
    
    def compute_dist_no_loop(self,Xtest):
#         大概可以理解为 sqrt((a-b)^2) => sqrt( a^2 + b^2 - 2ab ) 展开,矩阵注意维度
        a2 = np.sum(self.Xtrain**2, axis=1) # 5000*1  # **2 or np.square
        b2 = np.sum(Xtest**2, axis=1)        # 50*1
        dot_matrix = np.dot(Xtest, self.Xtrain.T) # 50*5000
#         print(dot_matrix.shape)
#         print(a2.shape) # (5000,)
#         print(b2.shape) # (50,)
#         print(b2.T.shape) #对向量直接用.T  向量不变  (50,)
#         此时,a2 b2都是向量,要与点积得到的矩阵50*5000想相a加减,先将reshape,后用到广播机制
#         向量貌似e可以隐式转换为一个1行n列的矩阵,但不可隐式转为n行1列的矩阵
        return np.sqrt(a2 + np.reshape(b2,(-1,1)) - 2*dot_matrix) # reshape -1 自适应
        
    
#         https://blog.csdn.net/qq_41671051/article/details/80096269
#         https://blog.csdn.net/hqh131360239/article/details/79061535

    def _compute_distances_no_loops(self, X):
        num_test = X.shape[0]  
        num_train = self.Xtrain.shape[0]  
        dists = np.zeros((num_test, num_train))   
        test_sum = np.sum(np.square(X), axis = 1) # 500*3072 - 500*1 以500,形式表示  
        train_sum = np.sum(np.square(self.Xtrain), axis = 1) # 5000*3072 - 5000*1 以5000,形式表示  
        dianji = np.dot(X, self.Xtrain.T)  #点积(转置)500*5000  
        dists = np.sqrt(-2 * dianji + test_sum.reshape(-1,1) + train_sum) #平方展开,广播  
        return dists
        


# In[ ]:


# 2 loop、1 loop、no loop三种方式,
# 2 loop、1 loop 耗时较长,时间差不多
# no loop 耗时短。并行运算,大大提高了速度。


# In[110]:


classifier = NearestNeighbor()
classifier.train(X_train, y_train)

# ans_l1 = classifier.predict_l1(X_test)
# print(np.mean(ans_l1==y_test)) # 0.22

# ans_l2 = classifier.predict_l2(X_test)
# print(np.mean(ans_l2==y_test)) # 0.18

ans = classifier.compute_dist_no_loop(X_test)
print(np.sum(ans)) # 1203599820.3775597

print('ok')


# In[85]:


#################################
# test area
import numpy as np
a = np.array([ [1,2,3], [4,5,6], [7,8,9] ])
# print(a)
# print(a[1][1],a[1,1])
# print(a[1])
# print(np.array((-2,4,2)))
print(np.square(a))
print(a**2)

猜你喜欢

转载自www.cnblogs.com/cbattle/p/9026622.html