原文鏈接:http://cs231n.github.io/classification/
Example示例
例如骗露,在下面的圖像中寿冕,圖像分類模型采用一張圖像,并將概率分配給4個標簽{ cat椒袍,dog驼唱,hat,mug }驹暑。 如圖所示玫恳,對于計算機來說,圖像是由一個大型的三維數(shù)組表示的优俘。 在本例中京办,貓圖像寬248像素,高400像素帆焕,有三個顏色通道 Red惭婿、 Green、 Blue (簡稱 RGB)叶雹。 因此财饥,圖像由248 x 400 x 3個數(shù)字組成,即總共297,600個數(shù)字折晦。 每個數(shù)字都是一個從0(黑色)到255(白色)的整數(shù)钥星。 我們的任務(wù)是把這25萬個數(shù)字變成一個單一的標簽,比如“貓”满着。
圖像分類的任務(wù)是為給定的圖像預(yù)測單個標簽(或標簽上的分布谦炒,如圖所示)贯莺。 圖像是由0到255的整數(shù)組成的三維數(shù)組,大小為寬度 x 高度 x 3宁改。 3代表紅缕探、綠、藍三色通道
Challenges. 挑戰(zhàn)
由于識別一個視覺概念(比如貓)對于人類來說相對一些挑戰(zhàn)時还蹲,請記住圖像的原始表示為亮度值的3d 數(shù)組):
Viewpoint variation.視點變化
對于攝像機來說撕蔼,一個對象的單個實例可以通過多種方式進行導(dǎo)向。
Scale variation.尺度變化
視覺類經(jīng)常顯示其大小的變化(在現(xiàn)實世界中的大小秽誊,而不僅僅是其在圖像中的范圍)
Deformation.變形
許多感興趣的物體不是剛體鲸沮,可以在極端的方式下變形。
Occlusion.
感興趣物體可以被遮擋锅论。有時只能看到對象的一小部分(只有很少的像素)
Illumination conditions.光照條件
光照對像素級別的影響是劇烈的讼溺。
Background clutter.背景雜亂
感興趣物體可能會融入他們的環(huán)境,使得他們難以識別最易。
Intra-class variation.類內(nèi)變異
興趣類別通常比較廣泛怒坯,比如“椅子”。有許多不同類型的對象藻懒,每個都有自己的外觀剔猿。
一個好的圖像分類模型必須對所有這些變化的叉積保持不變,同時保持類間變化的敏感性嬉荆。
##########################################################
Data-driven approach 數(shù)據(jù)驅(qū)動方法
向計算機提供每個類別的許多例子归敬,然后開發(fā)學(xué)習算法,觀察這些例子并了解每個類別的視覺外觀鄙早。 這種方法被稱為數(shù)據(jù)驅(qū)動的方法汪茧,因為它依賴于首先累積一個標記圖像的訓(xùn)練數(shù)據(jù)集。 下面是一個數(shù)據(jù)集的一個例子:
四個視覺類別的示例訓(xùn)練集限番。在實際中舱污,可能有成千上萬的類別,每個類別有成千上萬的圖像弥虐。
The Image classification pipeline 圖像分類管道
圖像分類的任務(wù)是用一個像素數(shù)組表示單個圖像扩灯,并為其分配標簽。整個通道定義如下:
Input:輸入有一組n個圖像組成霜瘪,每個圖像都由K個不同的類別中的一個做為標簽珠插。將這些數(shù)據(jù)稱為訓(xùn)練集(training set)
Learning:任務(wù)是利用訓(xùn)練集學(xué)習每個類別的樣子。將這一步稱為訓(xùn)練分類器或者學(xué)習模型粥庄。
Evaluation:最后丧失,評估分類器的質(zhì)量豺妓,要求它預(yù)測一組之前沒有見過的新的圖像惜互。將這些圖像的真實標簽和分類器預(yù)測的標簽進行比較布讹。直觀地說,希望大量的預(yù)測和真實答案是相吻合的(稱之為基本事實ground truth)训堆。
##########################################################
Nearest Neighbor Classifier 最近鄰分類器
這種分類器與卷積神經(jīng)網(wǎng)絡(luò)沒有任何關(guān)系描验,在實際應(yīng)用中也很少使用,但它可以讓我們對圖像分類問題的基本方法有所了解坑鱼。
圖像分類示例數(shù)據(jù)集:CIFAR-10
這個數(shù)據(jù)集由60,000張高和寬都是32像素的小圖片組成膘流。 每個圖像都被標記為10個類中的一個(例如“ airplane,automobile鲁沥,bird呼股,etc”)。 這60,000張圖像被分割成一個包含50,000張圖像的訓(xùn)練集和一個包含10,000張圖像的測試集画恰。 在下面的圖片中彭谁,是來自10個類的10幅隨機圖片:
CIFAR-10:http://www.cs.toronto.edu/~kriz/cifar.html
假設(shè)現(xiàn)在得到了包含50,000張圖像的 CIFAR-10訓(xùn)練集(每張標簽有5,000張圖像) 考润,希望標記其余的10,000張圖像狭园。 最近鄰分類器將獲取一個測試圖像,將其與每一個訓(xùn)練圖像進行比較糊治,并預(yù)測最近訓(xùn)練圖像的標簽唱矛。 在上面的圖片的右邊的圖像中,可以看到這個過程用于10個示例測試圖像的示例結(jié)果井辜。 注意揖赴,在10個示例中,只有3個檢索到同一類的圖像抑胎,而在其他7個示例中燥滑,情況并非如此。 例如阿逃,在第8行距離馬頭最近的訓(xùn)練圖像是一輛紅色的汽車铭拧,大概是由于強烈的黑色背景。 因此恃锉,在這種情況下搀菩,馬的圖像會被錯誤地貼上汽車的標簽。
你可能已經(jīng)注意到破托,我們沒有具體說明如何比較兩個圖像肪跋,在本例中,這兩個圖像只是32 x 32 x 3的兩個塊土砂。 最簡單的方法之一就是逐個像素地比較圖像州既,然后把所有的差異加起來谜洽。 換句話說,給定兩幅圖像并將它們表示為矢量 I1吴叶,I2阐虚,比較它們的合理選擇可能是 L1距離(L1 distance):
這里的求和是用所有像素來表示的,下面是可視化的過程:
如何在代碼中實現(xiàn)分類器析显。 首先,將 CIFAR-10數(shù)據(jù)用4個數(shù)組加載到內(nèi)存中: the training data/labels 和 the test data/labels签赃。 在下面的代碼中谷异,Xtr (大小為50,000 x 32 x 32 x 3)保存訓(xùn)練集中的所有圖像,相應(yīng)的一維數(shù)組 Ytr (長度為50,000)保存訓(xùn)練標簽(從0到9) :
Xtr, Ytr, Xte, Yte = load_CIFAR10('data/cifar10/') # a magic function we provide
# flatten out all images to be one-dimensional
Xtr_rows = Xtr.reshape(Xtr.shape[0], 32 * 32 * 3) # Xtr_rows becomes 50000 x 3072
Xte_rows = Xte.reshape(Xte.shape[0], 32 * 32 * 3) # Xte_rows becomes 10000 x 3072
現(xiàn)在已經(jīng)將所有的圖像延伸成行锦聊,下面是如何訓(xùn)練和評估分類器的方法:
nn = NearestNeighbor() # create a Nearest Neighbor classifier class
nn.train(Xtr_rows, Ytr) # train the classifier on the training images and labels
Yte_predict = nn.predict(Xte_rows) # predict labels on the test images
# and now print the classification accuracy, which is the average number
# of examples that are correctly predicted (i.e. label matches)
print 'accuracy: %f' % ( np.mean(Yte_predict == Yte) )
作為一個評估標準歹嘹,使用精確度(accuracy)是很常見的,它度量了預(yù)測正確的比例孔庭。 請注意尺上,我們將構(gòu)建的所有分類器都滿足這一個通用 API: 它們有一個 train (x,y)函數(shù)圆到,該函數(shù)接受數(shù)據(jù)和標簽以供學(xué)習怎抛。 在內(nèi)部,類應(yīng)該構(gòu)建標簽的某種模型芽淡,以及如何從數(shù)據(jù)中預(yù)測它們马绝。 然后還有一個預(yù)測(x)函數(shù),它接受新的數(shù)據(jù)并預(yù)測標簽下面是一個簡單的L1距離最近鄰分類器的實現(xiàn)挣菲,它滿足這個模板:
import numpy as np
class NearestNeighbor(object):
def __init__(self):
pass
def train(self, X, y):
""" X is N x D where each row is an example. Y is 1-dimension of size N """
# the nearest neighbor classifier simply remembers all the training data
self.Xtr = X
self.ytr = y
def predict(self, X):
""" X is N x D where each row is an example we wish to predict label for """
num_test = X.shape[0]
# lets make sure that the output type matches the input type
Ypred = np.zeros(num_test, dtype = self.ytr.dtype)
# loop over all test rows
for i in xrange(num_test):
# find the nearest training image to the i'th test image
# using the L1 distance (sum of absolute value differences)
distances = np.sum(np.abs(self.Xtr - 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
如果運行這段代碼富稻,您將看到這個分類器只能在 CIFAR-10上達到38.6% 。 這比隨機猜測準確(由于有10個類別白胀,猜測的準確率為10%) 椭赋,但是遠遠不及人類的表現(xiàn)(估計約為94%)也沒有接近最先進的卷積神經(jīng)網(wǎng)絡(luò)(達到95% 的準確率,與人類的準確率相當(參見最近在 CIFAR-10上舉辦的 Kaggle 競賽的排行榜))或杠。
距離選擇
計算向量之間的距離還有許多其他方法哪怔。 另一個常見的選擇可能是使用L2距離,它具有計算兩個向量之間的歐幾里得度量的幾何解釋。 距離的形式是:
換句話說认境,我們將像以前一樣計算像素差胚委,但是這次我們將它們平方,加起來元暴,最后得到平方根篷扩。 在 numpy 中兄猩,使用上面的代碼只需要替換一行代碼茉盏。 計算距離的那行:
distances = np.sqrt(np.sum(np.square(self.Xtr - X[i,:]), axis = 1))
請注意,在上面包含了 np.sqrt 調(diào)用枢冤,但在實際的最近鄰應(yīng)用程序中鸠姨,可以省略平方根操作,因為平方根是單調(diào)函數(shù)淹真。 也就是說讶迁,它縮放了距離的絕對大小,但保留了排序核蘸,因此有或沒有排序的最近鄰是相同的巍糯。 如果在 CIFAR-10上用這個距離運行最近鄰分類器,將獲得35.4% 的準確率(略低于 L1距離結(jié)果)客扎。
L1 vs. L2. 考慮這兩個指標之間的差異是很有趣的祟峦。 特別是,當涉及到兩個矢量之間的差異時徙鱼,L2距離比 L1距離更加無情宅楞。 也就是說,相對于一個大的分歧袱吆,L2距離更傾向于多個中等程度的分歧厌衙。 L1和 L2距離(或相當于一對圖像之間差異的 L1 / L2范數(shù))是 p 范數(shù)最常用的特殊情況。
Nearest Neighbor Classifier for CIFAR-10 完整代碼
import pickle as p
import matplotlib.pyplot as plt
import numpy as np
# NearestNeighbor class
class NearestNeighbor(object):
def __init__(self):
pass
def train(self, X, y):
""" X is N x D where each row is an example. Y is 1-dimension of size N """
# the nearest neighbor classifier simply remembers all the training data
self.Xtr = X
self.ytr = y
def predict(self, X):
""" X is N x D where each row is an example we wish to predict label for """
num_test = X.shape[0]
# lets make sure that the output type matches the input type
Ypred = np.zeros(num_test, dtype=self.ytr.dtype)
# loop over all test rows
for i in range(num_test):
# find the nearest training image to the i'th test image
# using the L1 distance (sum of absolute value differences)
distances = np.sum(np.abs(self.Xtr - 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
def load_CIFAR_batch(filename):
""" load single batch of cifar """
with open(filename, 'rb')as f:
datadict = p.load(f, encoding='latin1')
X = datadict['data']
Y = datadict['labels']
Y = np.array(Y) # 字典里載入的Y是list類型绞绒,把它變成array類型
return X, Y
def load_CIFAR_Labels(filename):
with open(filename, 'rb') as f:
label_names = p.load(f, encoding='latin1')
names = label_names['label_names']
return names
# load data
label_names = load_CIFAR_Labels("cifar-10-batches-py/batches.meta")
imgX1, imgY1 = load_CIFAR_batch("cifar-10-batches-py/data_batch_1")
imgX2, imgY2 = load_CIFAR_batch("cifar-10-batches-py/data_batch_2")
imgX3, imgY3 = load_CIFAR_batch("cifar-10-batches-py/data_batch_3")
imgX4, imgY4 = load_CIFAR_batch("cifar-10-batches-py/data_batch_4")
imgX5, imgY5 = load_CIFAR_batch("cifar-10-batches-py/data_batch_5")
Xte_rows, Yte = load_CIFAR_batch("cifar-10-batches-py/test_batch")
Xtr_rows = np.concatenate((imgX1, imgX2, imgX3, imgX4, imgX5))
Ytr_rows = np.concatenate((imgY1, imgY2, imgY3, imgY4, imgY5))
nn = NearestNeighbor() # create a Nearest Neighbor classifier class
nn.train(Xtr_rows[:5000,:], Ytr_rows[:5000]) # train the classifier on the training images and labels
Yte_predict = nn.predict(Xte_rows[:1000,:]) # predict labels on the test images
# and now print the classification accuracy, which is the average number
# of examples that are correctly predicted (i.e. label matches)
# print(Yte_predict)
print('accuracy: %f' % (np.mean(Yte_predict == Yte[:1000]))) # Yte_predict==Yte時分類正確婶希,求正確的概率
# show a picture
image=imgX1[9,0:1024].reshape(32,32)
print(image.shape)
plt.imshow(image)
plt.imshow(image,cmap=plt.cm.gray)
plt.axis('off') #去除圖片邊上的坐標軸
plt.show()
##########################################################
K-Nearest Neighbor Classifier K-最近鄰分類器
當進行預(yù)測時,只使用最近圖像的標簽是很奇怪的蓬衡。 事實上饲趋,通過使用 k- 最近鄰分類器,幾乎總是可以做得更好撤蟆。 這個想法非常簡單: 不需要在訓(xùn)練集中找到最接近的圖像奕塑,而是找到最接近的 k 個圖像,然后讓他們對測試圖像的標簽進行投票家肯。 特別是龄砰,當 k=1時,恢復(fù)最近鄰分類器。 直觀上换棚,k 值越高式镐,分類器對異常值的抵抗能力就越強:
k的值如何選擇呢兔仰? 接下來我們談?wù)勥@個問題茫负。
Validation sets for Hyperparameter tuning 用于超參數(shù)調(diào)優(yōu)的驗證集
K-最近鄰分類器需要 k 的設(shè)置。 但是什么數(shù)字最有效呢斋陪? 此外朽褪,有許多不同的距離函數(shù),可以使用: L1標準无虚,L2標準缔赠,還有許多其他的選擇,甚至還沒有考慮(如點積)友题。 這些選擇被稱為超參數(shù)(hyperparameters)嗤堰,它們經(jīng)常出現(xiàn)在許多從數(shù)據(jù)中學(xué)習的機器學(xué)習算法的設(shè)計中。 應(yīng)該選擇什么樣的值 / 設(shè)置通常并不明顯度宦。
你可能會建議嘗試許多不同的值踢匣,看看哪個最有效。這是一個好主意戈抄,這確實是我們將要做的离唬,但這必須非常小心。特別是划鸽,不能使用測試集來調(diào)整超參數(shù)输莺。每當設(shè)計機器學(xué)習算法時戚哎,應(yīng)該把測試集看作是一個非常寶貴的資源,理想情況下嫂用,直到最后一次才接觸到它型凳。否則,真正的危險是嘱函。調(diào)整后的超參數(shù)能過很好的在測試集上工作甘畅,但是當要部署模型時,可能會看到性能顯著降低往弓。在實踐中疏唾,稱作過擬合測試集。另一種看法是亮航,如果在測試集上調(diào)整超參數(shù)荸实,那么相當于把測試集當作訓(xùn)練集匀们,因此缴淋,在部署模型時,其上實現(xiàn)的性能對于實際觀察到的內(nèi)容會過于樂觀泄朴。但是如果只在最后使用一次測試集重抖,它仍然是衡量分類器泛化(generalization)的一個很好的代理。
??Evaluate on the test set only a single time, at the very end.
在測試集上只評估一次祖灰,在最后一次钟沛。
K-Nearest Neighbor Classifier for CIFAR-10 完整代碼
import pickle as p
import matplotlib.pyplot as plt
import numpy as np
# NearestNeighbor class
class NearestNeighbor(object):
def __init__(self):
pass
def train(self, X, y):
""" X is N x D where each row is an example. Y is 1-dimension of size N """
# the nearest neighbor classifier simply remembers all the training data
self.Xtr = X
self.ytr = y
def predict(self, X):
""" X is N x D where each row is an example we wish to predict label for """
num_test = X.shape[0]
# lets make sure that the output type matches the input type
Ypred = np.zeros(num_test, dtype=self.ytr.dtype)
# loop over all test rows
for i in range(num_test):
# find the nearest training image to the i'th test image
# using the L1 distance (sum of absolute value differences)
distances = np.sum(np.abs(self.Xtr - X[i, :]), axis=1)
sort_id = distances.argsort()
# min_index = np.argmin(distances) # get the index with smallest distance
# print(min_index)
dic = {}
for j in range(20):
vlable = self.ytr[sort_id[j]] # 為對應(yīng)的標簽記數(shù)
dic[vlable] = dic.get(vlable, 0) + 1
# 尋找vlable代表的標簽,如果沒有返回0并加一局扶,如果已經(jīng)存在返回改鍵值對應(yīng)的值并加一
max = 0
# print(dic.items())
for index, v in dic.items(): # .items 返回所有的鍵值對
if v > max:
max = v
maxIndex = index
Ypred[i] = maxIndex # predict the label
print(Ypred)
return Ypred
def load_CIFAR_batch(filename):
""" load single batch of cifar """
with open(filename, 'rb')as f:
datadict = p.load(f, encoding='latin1')
X = datadict['data']
Y = datadict['labels']
Y = np.array(Y) # 字典里載入的Y是list類型恨统,把它變成array類型
return X, Y
def load_CIFAR_Labels(filename):
with open(filename, 'rb') as f:
label_names = p.load(f, encoding='latin1')
names = label_names['label_names']
return names
# load data
label_names = load_CIFAR_Labels("cifar-10-batches-py/batches.meta")
imgX1, imgY1 = load_CIFAR_batch("cifar-10-batches-py/data_batch_1")
imgX2, imgY2 = load_CIFAR_batch("cifar-10-batches-py/data_batch_2")
imgX3, imgY3 = load_CIFAR_batch("cifar-10-batches-py/data_batch_3")
imgX4, imgY4 = load_CIFAR_batch("cifar-10-batches-py/data_batch_4")
imgX5, imgY5 = load_CIFAR_batch("cifar-10-batches-py/data_batch_5")
Xte_rows, Yte = load_CIFAR_batch("cifar-10-batches-py/test_batch")
Xtr_rows = np.concatenate((imgX1, imgX2, imgX3, imgX4, imgX5))
Ytr_rows = np.concatenate((imgY1, imgY2, imgY3, imgY4, imgY5))
nn = NearestNeighbor() # create a Nearest Neighbor classifier class
nn.train(Xtr_rows[:5000,:], Ytr_rows[:5000]) # train the classifier on the training images and labels
Yte_predict = nn.predict(Xte_rows[:1000,:]) # predict labels on the test images
# and now print the classification accuracy, which is the average number
# of examples that are correctly predicted (i.e. label matches)
# print(Yte_predict)
print('accuracy: %f' % (np.mean(Yte_predict == Yte[:1000]))) # Yte_predict==Yte時分類正確,求正確的概率
# show a picture
image=imgX1[9,0:1024].reshape(32,32)
print(image.shape)
plt.imshow(image)
plt.imshow(image,cmap=plt.cm.gray)
plt.axis('off') #去除圖片邊上的坐標軸
plt.show()
幸運的是三妈,有一種調(diào)優(yōu)超參數(shù)的正確方法畜埋,不涉及測試集。想法是:把訓(xùn)練集分成兩部分:一部分比較小的訓(xùn)練集稱為“驗證集(validation set)”畴蒲。以 CIFAR-10為例悠鞍,我們可以使用49,000個訓(xùn)練圖像進行訓(xùn)練,并留下1,000個圖像進行驗證模燥。 這個驗證集實質(zhì)上是一個偽測試集咖祭,用來調(diào)整超參數(shù)。
以下是 CIFAR-10的情況:
在這個過程結(jié)束時蔫骂,可以繪制一個圖表么翰,顯示哪個 k 值工作得最好。 然后辽旋,使用這個值浩嫌,在實際測試集上進行一次計算。
??把訓(xùn)練集分成訓(xùn)練集和驗證集。 使用驗證集優(yōu)化所有超參數(shù)固该。 最后在測試集上運行一次并報告性能锅减。
Cross-validation交叉驗證
如果訓(xùn)練數(shù)據(jù)的大小(以及驗證數(shù)據(jù))可能很小伐坏,人們有時會使用更復(fù)雜的技術(shù)進行超參數(shù)調(diào)整怔匣,稱為交叉驗證。 使用我們之前的示例桦沉,我們的想法是每瞒,不是任意選擇前1000個數(shù)據(jù)點作為驗證集和靜態(tài)訓(xùn)練集,而是通過迭代來獲得更好且噪聲更小的估計k的某個值的工作效果纯露。 驗證集并平衡這些性能剿骨。 例如,在5倍交叉驗證中埠褪,我們將訓(xùn)練數(shù)據(jù)分成5個相等的folds浓利,其中4個用于訓(xùn)練,1個用于驗證钞速。 然后我們將迭代哪個fold是驗證折疊贷掖,評估性能,最后平均不同fold的性能渴语。
例如參數(shù)k為5-fold的交叉驗證苹威。 對于k的每個值,我們在4folds上訓(xùn)練并在第5個上進行評估驾凶。 因此牙甫,對于每個k,我們在驗證fold上獲得5個精度(精度是y軸调违,每個結(jié)果是一個點)窟哺。 趨勢線通過每個k的結(jié)果的平均值繪制,誤差條表示標準偏差。 請注意,在此特定情況下暖夭,交叉驗證表明約k = 7的值最適合此特定數(shù)據(jù)集(對應(yīng)于圖中的峰值)泉蝌。 如果我們使用超過5folds,我們可能會看到更平滑(即噪聲較小)的曲線。
實際上實際上,更傾向于避免使用交叉驗證黄绩,而是使用單一的驗證分割(a single validation split),因為使用交叉驗證驗證可能會耗費大量計算時間玷过。 人們傾向于使用50%-90% 的訓(xùn)練數(shù)據(jù)用于訓(xùn)練爽丹,剩余的用于驗證筑煮。 但是,這取決于多個因素: 例如粤蝎,如果超參數(shù)的數(shù)量很大真仲,可能傾向于使用更大的驗證分割。 如果驗證集中的示例數(shù)量很少(可能只有幾百個左右) 初澎,那么使用交叉驗證更安全秸应。 在實踐中,通潮纾可以看到3-fold软啼、5-fold甚至10-fold的交叉驗證。
K-Nearest Neighbor Classifier for CIFAR-10 交叉驗證完整代碼
import pickle as p
import matplotlib.pyplot as plt
import numpy as np
# NearestNeighbor class
class NearestNeighbor(object):
def __init__(self):
pass
def train(self, X, y):
""" X is N x D where each row is an example. Y is 1-dimension of size N """
# the nearest neighbor classifier simply remembers all the training data
self.Xtr = X
self.ytr = y
def predict(self, X,k):
""" X is N x D where each row is an example we wish to predict label for """
num_test = X.shape[0]
# lets make sure that the output type matches the input type
Ypred = np.zeros(num_test, dtype=self.ytr.dtype)
# loop over all test rows
for i in range(num_test):
# find the nearest training image to the i'th test image
# using the L1 distance (sum of absolute value differences)
distances = np.sum(np.abs(self.Xtr - X[i, :]), axis=1)
sort_id = distances.argsort()
# min_index = np.argmin(distances) # get the index with smallest distance
# print(min_index)
dic = {}
for j in range(k):
vlable = self.ytr[sort_id[j]] # 為對應(yīng)的標簽記數(shù)
dic[vlable] = dic.get(vlable, 0) + 1
# 尋找vlable代表的標簽票顾,如果沒有返回0并加一础浮,如果已經(jīng)存在返回改鍵值對應(yīng)的值并加一
max = 0
print(dic.items())
for index, v in dic.items(): # .items 返回所有的鍵值對
if v > max:
max = v
maxIndex = index
Ypred[i] = maxIndex # predict the label
print(Ypred)
return Ypred
def load_CIFAR_batch(filename):
""" load single batch of cifar """
with open(filename, 'rb')as f:
datadict = p.load(f, encoding='latin1')
X = datadict['data']
Y = datadict['labels']
Y = np.array(Y) # 字典里載入的Y是list類型,把它變成array類型
return X, Y
def load_CIFAR_Labels(filename):
with open(filename, 'rb') as f:
label_names = p.load(f, encoding='latin1')
names = label_names['label_names']
return names
# load data
label_names = load_CIFAR_Labels("cifar-10-batches-py/batches.meta")
imgX1, imgY1 = load_CIFAR_batch("cifar-10-batches-py/data_batch_1")
imgX2, imgY2 = load_CIFAR_batch("cifar-10-batches-py/data_batch_2")
imgX3, imgY3 = load_CIFAR_batch("cifar-10-batches-py/data_batch_3")
imgX4, imgY4 = load_CIFAR_batch("cifar-10-batches-py/data_batch_4")
imgX5, imgY5 = load_CIFAR_batch("cifar-10-batches-py/data_batch_5")
Xte_rows, Yte = load_CIFAR_batch("cifar-10-batches-py/test_batch")
Xtr_rows = np.concatenate((imgX1, imgX2, imgX3, imgX4, imgX5))
Ytr_rows = np.concatenate((imgY1, imgY2, imgY3, imgY4, imgY5))
nn = NearestNeighbor() # create a Nearest Neighbor classifier class
nn.train(Xtr_rows[:5000,:], Ytr_rows[:5000]) # train the classifier on the training images and labels
Xval_rows = Xtr_rows[:1000, :] # take first 1000 for validation
Yval = Ytr_rows[:1000]
Xtr_rows = Xtr_rows[1000:, :] # keep last 49,000 for train
Ytr_rows = Ytr_rows[1000:]
# find hyperparameters that work best on the validation set
validation_accuracies = []
for k in [1, 3, 5, 10, 20, 50, 100]:
# use a particular value of k and evaluation on validation data
nn = NearestNeighbor()
nn.train(Xtr_rows, Ytr_rows)
# here we assume a modified NearestNeighbor class that can take a k as input
Yval_predict = nn.predict(Xval_rows, k=k)
acc = np.mean(Yval_predict == Yval)
print('accuracy: %f' % (acc,))
# keep track of what works on the validation set
validation_accuracies.append((k, acc))
##########################################################
最近鄰分類器優(yōu)缺點
Pros:
1.實現(xiàn)和理解非常簡單奠骄。
2.分類器不需要時間訓(xùn)練豆同,只需要存儲并索引訓(xùn)練數(shù)據(jù)。
Cons:
1.測試時需要支付計算成本含鳞。因為測試示例分類需要與每個單獨的訓(xùn)練數(shù)據(jù)進行比較影锈。(實踐中,更關(guān)心測試時間的效率而不是訓(xùn)練時間的效率)
最近鄰分類器的計算復(fù)雜度是一個非巢醣粒活躍的研究領(lǐng)域鸭廷,現(xiàn)有的一些近似最近鄰算法(Approximate Nearest Neighbor ,ANN)和庫可以加速數(shù)據(jù)集中的最近鄰查找(例如 FLANN)熔吗。 這些算法允許在檢索過程中權(quán)衡最近鄰檢索的正確性與其空間 / 時間復(fù)雜度辆床,通常依賴于預(yù)處理 / 索引階段,該階段包括構(gòu)建 kdtree 或運行 k-means 算法桅狠。
最近鄰分類器在某些設(shè)置(特別是低維數(shù)據(jù))中可能是一個不錯的選擇讼载,但它很少適用于實際的圖像分類設(shè)置轿秧。 一個問題是,圖像是高維對象(即它們通常包含許多像素) 咨堤,在高維空間中的距離可能是非常違反直覺的菇篡。 下面的圖片說明了我們上面提到的基于像素的L2相似性與視覺上的相似性是非常不同的:
這里還有一個可視化的例子津滞,使用像素差異來比較圖像是不夠的铝侵。 使用一種稱為 t-SNE 的可視化技術(shù)來獲取 CIFAR-10圖像,并將它們嵌入到二維空間中触徐,以便最好地保存它們的(局部)成對距離咪鲜。 在這個可視化中,根據(jù)我們上面展示的 L2像素距離撞鹉,附近顯示的圖像被認為是非常接近的:
更大的可視化版本:http://cs231n.github.io/assets/pixels_embed_cifar10_big.jpg0
特別要注意的是,相互鄰近的圖像更多的是圖像的一般色彩分布的函數(shù)孝鹊,或背景的類型炊琉,而不是它們的語義特征。 例如又活,一只狗可以看到非常接近青蛙苔咪,因為兩者碰巧都在白色的背景上。 理想情況下柳骄,希望所有10個類的圖像形成它們自己的集群团赏,以便同一類的圖像彼此鄰近,而不考慮不相關(guān)的特征和變化(例如背景)耐薯。 但是舔清,要獲得這個屬性,必須超越原始像素曲初。