本文為你介紹圖像分類的5種技術(shù),總結(jié)并歸納算法、實現(xiàn)方式,并進行實驗驗證。
圖像分類問題就是從固定的一組分類中,給輸入圖像分配標簽的任務(wù)。這是計算機視覺的核心問題之一,盡管它看似簡單,卻在實際生活中有著各種各樣的應(yīng)用。
傳統(tǒng)方式:功能描述和檢測。
也許這種方法對于一些樣本任務(wù)來說是比較好用的,但實際情況卻要復(fù)雜得多。
因此,我們將使用機器學(xué)習(xí)來為每個類別提供許多示例,然后開發(fā)學(xué)習(xí)算法來查看這些示例,并了解每個類的視覺外觀,而不是試圖直接在代碼中指定每一個大家感興趣的類別是什么樣的。
然而,圖像分類問題就是一個非常復(fù)雜的工作,它總是借用諸如卷積神經(jīng)網(wǎng)絡(luò)(CNN)這樣的深度學(xué)習(xí)模型來完成。但我們也知道,通常我們在課堂中學(xué)習(xí)到的,諸如KNN(鄰近算法)和SVM(支持向量機)這樣的許多算法,在數(shù)據(jù)挖掘問題上做得非常好,但似乎它們有時也不是圖像分類問題的最佳選擇。
因此,我們想要比較一下我們在課堂中學(xué)到的算法與CNN和遷移學(xué)習(xí)算法的性能。
目標
我們的目標是:
將KNN、SVM和BP神經(jīng)網(wǎng)絡(luò),與通常用于工業(yè)中圖像分類問題的算法進行比較,例如CNN和遷移學(xué)習(xí)。
獲得深度學(xué)習(xí)的經(jīng)驗。
通過Google的TensorFlow來探索機器學(xué)習(xí)框架。
算法和工具
我們在這個項目中使用的5種方法分別是KNN、SVM、BP神經(jīng)網(wǎng)絡(luò)、CNN,以及遷移學(xué)習(xí)。
整個項目主要分為3種方法。
第一種方法:使用KNN、SVM和BP神經(jīng)網(wǎng)絡(luò),這是我們在課堂上學(xué)到的算法,功能強大而且易于實施。我們主要使用sklearn來實現(xiàn)這些算法。
第二種方法:雖然傳統(tǒng)的多層感知器(MLP)模型成功地應(yīng)用于圖像識別,但由于節(jié)點之間的完全連通性受到維度災(zāi)難的影響,因此不能很好地擴展到更高分辨率的圖像。所以在這一部分我們使用Google的TensorFlow深度學(xué)習(xí)框架來構(gòu)建一個CNN。
第三種方法:重新訓(xùn)練預(yù)先訓(xùn)練的深層神經(jīng)網(wǎng)絡(luò)的最后一層(稱為Inception V3),同樣也是由TensorFlow來實現(xiàn)。Inception V3是為ImageNet大型視覺識別挑戰(zhàn)而進行的訓(xùn)練,數(shù)據(jù)從2012年開始采集。這是計算機視覺中的標準任務(wù),其中模型嘗試將整個圖像分為1000個類別,如“斑馬”、“斑點狗”和“洗碗機”。為了重新訓(xùn)練這個預(yù)先訓(xùn)練網(wǎng)絡(luò),我們需要確保我們自己的數(shù)據(jù)集尚未被預(yù)先訓(xùn)練。
如何實現(xiàn)
第一種方法:
預(yù)處理數(shù)據(jù)集,并用sklearn來運行KNN、SVM和BP神經(jīng)網(wǎng)絡(luò)。
首先,我們使用openCV包定義了兩種不同的預(yù)處理函數(shù):第一個稱為圖像特征向量,調(diào)整圖像大小,然后將圖像平坦化為行像素列表。第二個稱為提取顏色直方圖,使用cv2.normalize從HSV顏色間距中提取3D顏色直方圖,然后平坦化結(jié)果。
然后,我們構(gòu)造需要解析的幾個參數(shù),因為我們要測試這個部分的準確性,不僅是針對整個數(shù)據(jù)集的,還要測試具有不同數(shù)量標簽的子數(shù)據(jù)集,我們將數(shù)據(jù)集構(gòu)造為解析到我們程序中的參數(shù)。與此同時,我們還構(gòu)造了用于k-NN方法的相鄰數(shù)作為解析參數(shù)。
做好這些之后,我們開始提取數(shù)據(jù)集中的每個圖像特征并將其放入數(shù)組中。我們使用cv2.imread來讀取每個圖像,通過從圖像名稱中提取字符串來拆分標簽。在我們的數(shù)據(jù)集中,我們使用相同的格式設(shè)置名稱:“類標簽”.“圖像號”.jpg,因此我們可以輕松地提取每個圖像的類標簽。然后我們使用之前定義的2個函數(shù)來提取2種特征,并附加到數(shù)組rawImages和特征中,而我們之前提取的標簽則附加到數(shù)組標簽。
下一步是使用從sklearn包導(dǎo)入的函數(shù)train_test_split拆分數(shù)據(jù)集。具有后綴RI、RL的集合是rawImages和標簽對的拆分結(jié)果,另一個是特征和標簽對的拆分結(jié)果。我們使用數(shù)據(jù)集的85%作為訓(xùn)練集,15%作為測試集。
最后,我們運用KNN、SVM和BP神經(jīng)網(wǎng)絡(luò)函數(shù)來評估數(shù)據(jù)。對于KNN,我們使用KNeighborsClassifier;對于SVM,我們使用SVC;對于BP神經(jīng)網(wǎng)絡(luò),我們使用MLPClassifier。
第二種方法:
使用TensorFlow構(gòu)建CNN。TensorFlow的目的是讓你構(gòu)建一個計算圖(使用任何類似Python的語言),然后用C ++來執(zhí)行圖形操作,這比直接用Python來執(zhí)行相同的計算要高效得多。
TensorFlow還可以自動計算優(yōu)化圖形變量所需的梯度,以便使模型更好地運行。這是因為圖形是簡單數(shù)學(xué)表達式的組合,因此可以使用導(dǎo)數(shù)的鏈式規(guī)則來計算整個圖形的梯度。
TensorFlow圖由以下部分組成:
用于將數(shù)據(jù)輸入圖表的占位符變量。
要進行優(yōu)化的變量,以便使卷積網(wǎng)絡(luò)更好地得以運行。
卷積網(wǎng)絡(luò)的數(shù)學(xué)公式。
可用于指導(dǎo)變量優(yōu)化的成本衡量標準。
一種更新變量的優(yōu)化方法。
CNN架構(gòu)由不同層的堆疊形成,其通過可微函數(shù)將輸入量轉(zhuǎn)換成輸出量(例如類別分數(shù))。
所以在我們的實現(xiàn)操作中,第一層是保存圖像,然后我們構(gòu)建了3個具有2×2最大池和修正線性單元(ReLU)的卷積層。
輸入是一個具有以下尺寸的四維張量:
圖像編號。
每個圖像的Y軸。
每個圖像的X軸。
每個圖像的通道。
輸出是另一個四維張量,具有以下尺寸:
圖像號,與輸入相同。
每個圖像的Y軸。如果使用的是2×2池,則輸入圖像的高度和寬度除以2。
每個圖像的X軸。同上。
由卷積濾波器產(chǎn)生的通道。
然后我們在網(wǎng)絡(luò)末端構(gòu)建了2個完全連接的層。輸入是形狀為[num_images,num_inputs]的2維張量。輸出是形狀為[num_images,num_outputs]的2維張量。
然而,為了連接卷積層和完全連接層,我們需要一個平坦層,將4維張量減小到2維,從而可以用作完全連接層的輸入。
CNN的最后端始終是一個softmax層,它將來自全連接層的輸出歸一化,使得每個元素被限制在0和1之間,而所有元素總和為1。
為了優(yōu)化訓(xùn)練結(jié)果,我們需要一個成本衡量標準,并盡量減少每次迭代。我們在這里使用的成本函數(shù)是交叉熵(從tf.nn.oftmax_cross_entropy_with_logits()調(diào)用),并對所有圖像分類采用交叉熵的平均值。優(yōu)化方法是tf.train.AdamOptimizer(),它是Gradient Descent的高級形式。這是一個調(diào)整的參數(shù)學(xué)習(xí)率。
第三種方法:
Retrain Inception V3物體識別模型有數(shù)百萬個參數(shù),可能需要幾周才能完全訓(xùn)練。遷移學(xué)習(xí)是一種技術(shù),可以通過為一組類別(如ImageNet)采用訓(xùn)練有素的模型來快速完成此項工作,并從新類別的現(xiàn)有權(quán)重中進行訓(xùn)練。雖然它不如全訓(xùn)練運行得那么好,但對于許多應(yīng)用來說,這是非常有效的,并且可以在筆記本電腦上運行,只要運行三十分鐘即可,無需GPU。對于這部分的實現(xiàn),我們可以按照下邊的說明進行操作:
https://www.tensorflow.org/tutorials/image_retraining
首先,我們需要獲得預(yù)先訓(xùn)練的模型,刪除舊的頂層,并在我們擁有的數(shù)據(jù)集上訓(xùn)練一個新的模型。在一個沒有貓品種的原始ImageNet類中,要對完整的網(wǎng)絡(luò)進行訓(xùn)練。遷移學(xué)習(xí)的神奇之處在于,經(jīng)過訓(xùn)練以區(qū)分某些對象的較低層可以重用于許多識別任務(wù),而無需任何更改。然后我們分析磁盤上的所有圖像,并計算其中每個圖像的瓶頸值(bottleneck values)。點擊這里查看bottleneck的詳細信息(https://www.tensorflow.org/tutorials/image_retraining)。每個圖像在訓(xùn)練過程中被重復(fù)使用多次,所以計算每個瓶頸值都需要花費大量的時間,因此可以加快緩存這些瓶頸值,從而不必重復(fù)計算。
該腳本將運行4000個訓(xùn)練步驟。每個步驟從訓(xùn)練集中隨機選擇十個圖像,從緩存中發(fā)現(xiàn)其瓶頸,并將它們饋送到最后一層以獲得預(yù)測。然后將這些預(yù)測與實際標簽進行比較,從而通過反向傳播過程更新最終層的權(quán)重。
開始實驗
數(shù)據(jù)集
牛津IIIT寵物數(shù)據(jù)集(http://www.robots.ox.ac.uk/~vgg/data/pets/)
有25個品種的狗和12個品種的貓。每個品種有200張圖像。
我們在項目中只使用了10個貓品種。
我們在這里使用的類型是['Sphynx'(加拿大無毛貓,也稱斯芬克斯貓),'Siamese'(暹羅貓),'Ragdoll'(布偶貓),'Persian'(波斯貓),'Maine-Coon'(緬因貓),'British-shorthair'(英國短毛貓),'Bombay'(孟買貓),'Birman'(緬甸貓),'Bengal'(孟加拉貓)]。
所以我們在數(shù)據(jù)集中共有2000張圖像,彼此的尺寸各不同。但是我可以將它們調(diào)整為固定大小,如64 x 64或128 x 128。
預(yù)處理
在這個項目中,我們主要使用OpenCV進行圖像數(shù)據(jù)的處理,比如將圖像讀入數(shù)組,并重新形成我們需要的尺寸。
改進圖像訓(xùn)練結(jié)果的一個常見方法是以隨機方式變形,裁剪或增亮訓(xùn)練輸入,這具有擴展訓(xùn)練數(shù)據(jù)的有效大小的優(yōu)點,而這歸功于相同圖像的所有可能的變化,并且傾向于幫助網(wǎng)絡(luò)學(xué)習(xí)應(yīng)對在分類器的現(xiàn)實使用中將發(fā)生的所有失真問題。
詳情請參閱鏈接:https://github.com/aleju/imgaug
評估
第一種方法:
第一部分:預(yù)處理數(shù)據(jù)集,并用sklearn應(yīng)用KNN、SVM和BP神經(jīng)網(wǎng)絡(luò)。
在程序中有很多參數(shù)可以調(diào)整:在image_to_feature_vector函數(shù)中,我們設(shè)置的尺寸是128x128,我們之前也嘗試過像8x8,64x64,256x256這樣的大小。從而我們發(fā)現(xiàn)圖像尺寸越大,精度越好。但是,大的圖像尺寸也會增加執(zhí)行時間和內(nèi)存消耗。所以我們終于決定圖像尺寸為128x128,因為它不是太大,但同時也可以保證精度。
在extract_color_histogram函數(shù)中,我們將每個通道的bin數(shù)設(shè)置為32,32,32。像上一個函數(shù)一樣,我們也嘗試了8,8,8和64,64,64,并且更高的數(shù)字可以產(chǎn)生更高的結(jié)果,但同時也伴隨著更高的執(zhí)行時間。所以我們認為32,32,32是最合適的。
而至于數(shù)據(jù)集,我們嘗試了3種數(shù)據(jù)集。第一個是具有400個圖像,2個標簽的子數(shù)據(jù)集。第二個是具有1000個圖像,5個標簽的子數(shù)據(jù)集。最后一個是具有1997個圖像,10個標簽的整個數(shù)據(jù)集。并且我們將不同的數(shù)據(jù)集解析為程序中的參數(shù)。
在KNeighborsClassifier中,我們只更改了鄰居數(shù),并將結(jié)果存儲為每個數(shù)據(jù)集的最佳K。然后將我們設(shè)置的所有其他參數(shù)初始為默認值。
在MLPClassifier中,我們設(shè)置了一個含有50個神經(jīng)元的隱藏層。我們測試了多個隱藏層,但最終結(jié)果似乎沒有什么明顯的變化。最大迭代時間為1000,容差為1e-4,以確保其收斂。并將L2懲罰參數(shù)α設(shè)置為默認值,隨機狀態(tài)為1,求解器為“sgd”,學(xué)習(xí)速率為0.1。
在SVC中,最大迭代時間為1000,類的權(quán)重值為“平衡”。
我們的程序的運行時間不是很長,從2個標簽數(shù)據(jù)集到10個標簽數(shù)據(jù)集需要大約3到5分鐘。
第二種方法:
用TensorFlow構(gòu)建CNN。
計算模型的梯度是需要很長時間的,因為這個模型使用的是大型數(shù)據(jù)集的整體。因此,我們在優(yōu)化器的每次迭代中僅僅使用少量的圖像。批量大小通常為32或64。數(shù)據(jù)集分為包含1600張圖像的訓(xùn)練集,包含400張圖像的驗證集和包含300張圖像的測試集。
有很多參數(shù)是可以進行調(diào)整的。
首先是學(xué)習(xí)率。只要它足夠小,可以收斂和足夠大得不會使程序太慢,一個好的學(xué)習(xí)率還是很容易找到的。我們選擇了1×10 ^ -4。
第二個是我們向網(wǎng)絡(luò)提供的圖像的大小。我們嘗試了64 * 64和128 * 128。事實證明,圖像越大,我們得到的準確性越高,但代價是運行時間也相應(yīng)地增加。
然后是層和它們的形狀。但實際上有太多的參數(shù)可以調(diào)整,所以想要找到這些參數(shù)的最佳值是一件非常困難的工作。
根據(jù)網(wǎng)上的許多資源,我們了解到,建立網(wǎng)絡(luò)的參數(shù)的選擇幾乎都取決于經(jīng)驗。
起初我們試圖建立一個相對復(fù)雜的網(wǎng)絡(luò),其參數(shù)如下所示:
我們使用3個卷積層和2個完全連接的層,而這些都是相對復(fù)雜的。
但是,結(jié)果是——過度擬合。只有經(jīng)過一千次迭代,我們的程序才能獲得100%的訓(xùn)練精度,而只有30%的測試精度。起初我很困惑為什么我們會得到一個過度擬合的結(jié)果,并且我試圖隨機調(diào)整參數(shù),但是結(jié)果卻始終沒有變好。幾天后,我碰巧看到一篇文章,談到中國研究人員進行的一個深入學(xué)習(xí)項目(https://medium.com/@blaisea/physiognomys-new-clothes-f2d4b59fdd6a)。他們指出,他們進行的研究是有問題的。“一個技術(shù)性的問題是,想要訓(xùn)練和測試像AlexNet這樣的CNN,而結(jié)果不會過度擬合,僅僅使用不到2000個例子是不足以做到的。”所以,這個時候我才意識到,首先我們的數(shù)據(jù)集實際上是很小的,其次就是我們的網(wǎng)絡(luò)太復(fù)雜了。
要記得我們的數(shù)據(jù)集是剛好包含2000張圖像。
然后我嘗試減少內(nèi)核的數(shù)量層和大小。我嘗試了很多參數(shù),下圖就是我們使用的最終結(jié)構(gòu)。
我們只使用2個小形狀的卷積層和2個完全連接的層??山Y(jié)果并不是很理想,4000次迭代后得到的結(jié)果仍然是過度擬合,但是測試結(jié)果比以前好了10%。
我們?nèi)匀辉趯ふ乙环N處理方法,但是顯而易見的原因是我們的數(shù)據(jù)集不足,而我們沒有足夠的時間進行更好的改進。
最終結(jié)果就是,經(jīng)過5000次迭代之后,我們大概達到了43%的精度,而運行時間卻超過半個小時。
PS:實際上,由于這個結(jié)果,我們感到有些不安。 所以我們發(fā)現(xiàn)了另一個標準的數(shù)據(jù)集—CIFAR-10(https://www.cs.toronto.edu/~kriz/cifar.html)。
CIFAR-10數(shù)據(jù)集由10個類別的60000個32x32彩色圖像組成,每個類別有6000張圖像。里面含有50000個訓(xùn)練圖像和10000個測試圖像。
我們使用上面構(gòu)造的相同網(wǎng)絡(luò),經(jīng)過10小時的訓(xùn)練,我們在測試集上得到了78%的準確度。
第三種方法:
重新訓(xùn)練Inception V3,與此相同,我們隨機選擇幾個圖像進行訓(xùn)練,并選擇另一批圖像進行驗證。
有很多參數(shù)是可以進行調(diào)整的。
首先是訓(xùn)練步驟,默認值是4000,如果我們可以早些得到一個合理的結(jié)果,我們嘗試更多或嘗試一個較小的。
學(xué)習(xí)率是控制訓(xùn)練過程中最后一層更新的大小的。直觀地說,如果越小,那么學(xué)習(xí)將需要更長的時間,但最終可以幫助提高整體精度。**train batch**size會在一個訓(xùn)練步驟中控制檢查了的圖像的數(shù)量,并且由于學(xué)習(xí)率是應(yīng)用到每個批次中的,所以如果你想要讓更大的批次來獲得相同的整體效果的話,我們將需要減少它們的數(shù)量。
因為深入學(xué)習(xí)任務(wù)繁重,運行時間通常相對較長,所以我們不希望經(jīng)過數(shù)小時的訓(xùn)練之后得知,我們的模式實際上是很糟糕的。因此我們經(jīng)常檢驗驗證的準確性。這樣我們也可以避免過度擬合。通過分割可以將80%的圖像放入主要訓(xùn)練集中,保持10%作為訓(xùn)練期間的驗證,頻繁運行,然后將最終10%的圖像用作測試集,以預(yù)測分類器在現(xiàn)實世界的表現(xiàn)。
結(jié)果
第一種方法:預(yù)處理數(shù)據(jù)集,并用sklearn來運行KNN、SVM和BP神經(jīng)網(wǎng)絡(luò)。
結(jié)果如下圖所示。因為SVM的結(jié)果非常差,甚至低于隨機猜測,所以我們沒有提供其運行結(jié)果。
從結(jié)果我們可以看出:
在k-NN中,原始像素精度和直方圖精度相對相同。在含有5個標簽的子數(shù)據(jù)集中,直方圖精度比原始像素高出那么一點,但是在所有原始像素中,原始像素顯示出更好的結(jié)果。
在神經(jīng)網(wǎng)絡(luò)MLP分類器中,原始像素精度遠低于直方圖精度。而對于整個數(shù)據(jù)集(含有10個標簽)來說,原始像素精度甚至低于隨機猜測。
所有這兩種sklearn方法都沒有給出非常好的性能,在整個數(shù)據(jù)集(含有10個標簽的數(shù)據(jù)集)中識別正確類別的準確度只有約24%。這些結(jié)果表明,使用sklearn方法進行圖像識別的效果不夠好。他們在具有多種類別的復(fù)雜圖像的分類中并不具備良好的性能。但是,與隨機猜測相比,他們確實做了一些改進,但這還遠遠不夠。
基于此結(jié)果,我們發(fā)現(xiàn)為了提高準確性,必須采用一些深度學(xué)習(xí)的方法。
第二種方法:使用TensorFlow構(gòu)建如上所述的CNN,由于過度擬合,我們無法獲得良好的效果。
訓(xùn)練通常需要半小時的時間來進行,但是由于結(jié)果過度擬合,我們認為這個運行時間并不重要。與方法1進行比較,我們可以看到:雖然CNN的結(jié)果過度擬合,但我們?nèi)匀粫玫揭粋€比方法1更好的結(jié)果。
第三種方法:重新訓(xùn)練 Inception V3。
整個訓(xùn)練進度不超過10分鐘。而我們可以取得非常好的成績?;诖耍覀儗嶋H上可以看到深度學(xué)習(xí)和遷移學(xué)習(xí)的巨大能量。
演示:
目標
基于上述的比較,我們可以得出這樣的結(jié)論:
KNN、SVM和BP神經(jīng)網(wǎng)絡(luò)是不能夠很好地完成諸如圖像分類這樣的特定任務(wù)的。
雖然我們在CNN部分得到的結(jié)果過度擬合,但仍然比在課堂中學(xué)到的處理圖像分類問題的其他方法要好得多。
遷移學(xué)習(xí)在圖像分類問題上具有非常高的效率。無需GPU即可在短時間內(nèi)準確快捷地完成訓(xùn)練。即使你有一個小的數(shù)據(jù)集,它也可以很好地防止過度擬合。
我們學(xué)到了一些非常重要的圖像分類任務(wù)經(jīng)驗。這樣的任務(wù)與我們上課時所做的其他任務(wù)完全不同。數(shù)據(jù)集相對較大而不稀疏,網(wǎng)絡(luò)復(fù)雜,因此如果不使用GPU,運行時間會相當長。
裁剪或調(diào)整圖像大小使其更小。
隨機選擇一個小批量進行每次迭代訓(xùn)練。
在驗證集中隨機選擇一個小批量進行驗證,在訓(xùn)練過程中經(jīng)常報告驗證的得分情況。
嘗試使用圖像增強將一組輸入圖像轉(zhuǎn)換為一組新的,更大的,略有更改的圖像。
對于圖像分類任務(wù),我們需要一個比200 x 10的更大的數(shù)據(jù)集,CIFAR10數(shù)據(jù)集包含6萬張圖像。
更復(fù)雜的網(wǎng)絡(luò)需要更多的數(shù)據(jù)集來進行訓(xùn)練。
注意過度擬合。
-
神經(jīng)網(wǎng)絡(luò)
+關(guān)注
關(guān)注
42文章
4779瀏覽量
101166 -
圖像分類
+關(guān)注
關(guān)注
0文章
93瀏覽量
11956 -
深度學(xué)習(xí)
+關(guān)注
關(guān)注
73文章
5513瀏覽量
121545
原文標題:計算機視覺怎么給圖像分類?KNN、SVM、BP神經(jīng)網(wǎng)絡(luò)、CNN、遷移學(xué)習(xí)供你選(附開源代碼)
文章出處:【微信號:vision263com,微信公眾號:新機器視覺】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論