第7章 你的第一個分類器


第7章 你的第一個分類器

       在過去幾章,我們花費時間討論了圖像基礎、學習類型、甚至是構建圖像分類器時的四個步驟,但是到目前為止我們還沒有構建一個真正的自己的分類器。

       我們先構建幾個輔助工具,以方便從磁盤上預處理和加載圖像。之后,我們討論k-Nearest Neighbors (KNN)分類器,你將首先使用機器學習來探索圖像分類器。事實上,這個算法非常簡單,它根本不做任何實際的“學習”——但它仍然是一個重要的算法,以至於我們可以在以后的章節中理解神經網絡是如何從數據中學習的。

       最后,我們應用KNN算法在數據集上識別不同動物的種類。

1          使用圖像數據集

當使用數據集的時候,我們必須首先考慮以字節為單位的數據集的大小。數據集是否足夠合適以滿足機器的RAM大小?我們是否可以像加載大矩陣或數組那樣加載數據集?或是數據集太大,超出了我們機器的內存,要求我們一次只能將數據集“分塊”成片段並一次只加載一部分?

一些數據集較小可以直接加載進內存,而在大的數據集上工作時,就需要開發一些靈活的工具來有效的加載圖像而不是造成內存崩潰。

因此,在構建圖像分類器之前,花些時間來組織、預處理和加載數據集是很重要的一方面。

1.1    “Animals”數據集的介紹

 

圖1 三個類別每個類別1000張圖像,共3000張的數據集例子

“Animals”數據集是一個簡單的示例數據集,用於展示使用簡單的機器學習技術和高級的深度學習算法時如何訓練圖像分類器。

Animals數據集中的圖像嚴格分成三個類別:dogs、cats、pandas,每個類別有1000張示例圖像。貓和狗的圖像是從kaggle的Dogs vs. Cats挑戰(http://pyimg.co/ogx37))中抽取來的,而pandas則是從ImageNet數據集中抽取來的。

僅包含3000張圖像,可以容易的加載進內存中,這將使訓練更快、也不需要額外的編寫分塊加載圖像的代碼。深度學習模型可以快速的以CPU或GPU模式在這個數據集上工作。無論你的硬件配置如何,你都可以使用這個數據集學習機器學習和深度學習的基礎。

本章的目標是使用KNN分類器僅利用原始像素強度(如不考慮特征提取)盡量對一張圖像進行分類。可以看到,原始像素強度不適合於KNN算法,盡管如此,這扔是一個重要的基准實驗,因為我們可以理解為什么CNNs能夠在原始像素強度上獲得如此高的精度,而傳統的機器學習算法卻不能做到這一點。

1.2    深度學習工具箱的開始

在貫穿全書中,我們將構建我們自定義的深度學習工具箱。我們將從基本的輔助函數和類開始,對圖像進行預處理並加載小數據集,最終構建當前最先進的CNNs應用。

實際上,這是作者在運行深度學習實驗時使用的相同的工具箱。這個工具包將逐章逐步建立起來,讓您可以看到組成軟件包的各個組件,最終成為一個完整的庫,可以用來快速構建和訓練您自己的自定義深度學習網絡。

讓我們開始定義我們工具箱的項目結構:

 

可看到,我們有一個單獨定義的模塊pyimagesearch,我們開發的所有代碼都在該模塊下。

為了本章的開發需要,我們定義兩個子模塊:

 

datasets子模塊使用命名為simpledatasetloader的類開始執行,我們將使用這個類從磁盤中加載小的數據集(可以加載進主內存中),可選的功能是依據一些函數對數據集中的每個圖像進行預處理,並返回:(1)圖像(例如,原始像素強度);(2)與每個圖像相關的類別標簽。

之后,執行preprocessing模塊,就像后面章節看到的,這里有一些預處理方法,我們可以應用到圖像的數據集上來提升分類精確度,例如均值減法、抽樣隨機補丁、或簡單的將圖像調整到固定大小。在這個例子中,我們的SimplePreprocessor類將從磁盤加載圖像、將它調整到固定大小並且忽略長寬因素(ratio aspect)。在下兩部分,我將手動實現SimplePreprocessor和SimpleDatasetLoader。

1.3    基本的圖像預處理器

機器學習算法如KNN、SVMs甚至是CNNs要求數據集中的所有圖像有固定的特征向量大小。對於圖像,這一要求意味着我們的圖像必須經過預處理和縮放,以具有相同的寬度和高度。

有許多方法可以完成這種大小調整和縮放,從尊重原始圖像的長寬比的更先進的方法,到忽略長寬比的簡單方法,這種方法簡單地壓縮寬度和高度到所需的尺寸。實際上,使用哪種方法取決於變化因素的復雜性,一些可以忽略長寬比,一些則不可以。

本章中,我們構建一個基本的解決:構建一個忽略長寬比的圖像預處理器。如simplepreprocessor.py中代碼所示,其中這里接受一個縮放大小寬、高參數,默認使用的差值算法為cv2.INTER_AREA。這里的預處理做的工作很基本,接收輸入圖像,調整到固定大小,然后返回。與下一節中的圖像加載器結合,可以快速的將磁盤中的原始圖像調整為我們需要的分類器所需要的圖像大小。

1.4    構建圖像加載器

圖像加載器見simpledatasetloader.py文件,初始化__init__(self, preprocessors=None)中可選的接收一個預處理器,可用於之后加載的原始圖像進行預處理。注意,這里將preprocessor設定為一個列表可用於接收多個預處理器,可對原始圖像進行一系列預處理操作,如調整大小、均值減法、轉換到合適Keras處理的格式等等。

在load(self, pathname, verbose=-1)中,我們接收原始圖像的路徑,這里的路徑格式為/dataset_name/class/image.jpg,即dataset_name為數據集的名字,class為數據集中類別名字,image.jpg為實際圖像的名字,具體框架格式見該章示例程序。verbose用於顯示加載的圖像個數的一種顯示控制參數,默認不打印圖像加載信息。

在本書中幾乎所有項目都是按照這種項目框架來組織的,數據集也是按照這種配置,強烈建議按照這種組織。

此數據集加載程序的唯一注意事項是,它假定數據集中的所有圖像都可以一次裝入主內存。對於不能一次加載的數據集,我們需要一種更復雜的加載方式,這將在Practioner Bundle中闡述。

現在我們理解了圖像如何加載進內存,也已經對圖像進行了預處理,現在就可以進入KNN分類器設計階段了。

2          K-NN簡單的分類器

KNN是目前為止最簡單的機器學習和圖像分類算法。實際上,它不需要學習,只是利用了特征向量之間的距離度量。簡單的說,它對未知數據點的分類,通過在K個最近鄰中通過投票選擇出票數最多的類別作為該未知數據點的類別。為了使KNN算法發揮作用,它提出了一個基本假設,即具有相似視覺內容的圖像緊密地位於一個N維空間中。

為了在KNN算法度量兩個數據點的距離,我們需要選擇一個距離度量或類似的函數。衡量距離的x距離如下:

 

 

最常見的歐拉距離時x=2,曼哈頓距離則x=1。實際上,在KNN中可以任意選擇距離度量公式,這里我們以歐拉距離為例。

2.1    KNN工作示例

例如當選擇k=3時,如圖2所示,在最近的三個距離中,為2個cats和1個panda,依據投票規則,這里未知的圖像分類為cats。

 

圖2 k=3時KNN示例

2.2    KNN超參數

這里有兩個最明顯的超參數,一個是k值,當k太小,則無法有效的分類未知圖像,當k太大時,則可能過於平滑結果不准確。另一個超參數則是距離度量公式,歐拉距離是最佳的嗎?其它距離度量如何?

2.3    實現KNN算法

KNN算法的目標是在Animals數據集上使用原始像素強度訓練一個分類器且用它對未知圖像進行分類。我們使用前幾章描述的4步機器學習步驟進行:

步驟一:收集數據。這里我們animals有三個類,每個類1000張圖像,通過預處理將圖像縮放到32*32大小,那么每張圖像的維度大小為32*32*3=3072整數維度。

步驟二:划分數據集。這里將數據集按照75%訓練集和25%測試集划分。

步驟三和步驟四:訓練、評估KNN算法。

通過示例程序框架,我們在knn.py中編寫主程序,這里首先通過argparse模塊對輸入參數進行格式化處理。

根據代碼,我們知道通過SimpleDatasetLoader().load()函數返回的data為(3000, 32, 32, 3)的維度大小,然后我們通過data.shape[0]將數據原封不動的調整為(3000, 3072)的維度格式,這樣我們根據LabelEncoder().fit_transform(labels)獲得的(3000, [0…0, 1…1, 2…2])其中012為類別整數化后的表示,就可以將(data, label)調整為維度參數都對應且便於參數化處理了。在許多機器學習算法中,都假定類別標簽編碼為整數,因此這一步轉換是很有必要的。

之后,我們使用python的train_test_split()函數對數據集data進行划分數據集,約定成俗的做法是X表示用於訓練和測試的數據集表示,Y表示類別標簽。因此,約定使用trainX和testX分別表示訓練和測試示例,trainY和testY分別表示訓練和測試標簽。最后,根據示例程序中的最后部分調用KNN算法進行訓練和測試。

2.4    KNN結果

在knn.py所在目錄下,執行:python knn.py --dataset ../datasets/animals,將顯示執行過程,且在運行結束后顯示出評估結果。

其中顯示數據緩存大小約為9M,是因為我們3000張圖像,每張圖像32*32*3大小。根據評估,我們的分類器正確率在50%左右,比我們隨機猜測1/3要高一些,說明還是不錯的。

但是KNN的一個主要缺陷是,它簡單但是不能從數據中學習。我們的下一章將討論參數化學習(parameterized learning)的概念,在這個概念中,我們可以從圖像本身學習模式(patterns),而不是假設具有相似內容的圖像將在一個N維空間中聚集在一起。

2.5    KNN的優缺點

KNN的一個主要優點是簡單實施和理解。但是,它在分類階段將花費大量時間,我們可以通過近似最近鄰算法(Approximate Nearest Neighbor)來克服,但是這實際上是准確率與時間/空間的權衡。KNN與大多數機器學習算法(所有深度學習算法)相比,后者是在訓練階段花費大量時間來獲得較高的准確率,而在測試分類階段進行快速分類。

考慮到這些,為什么還要學習KNN呢?一個原因是它簡單易於理解。另一個原因是它給我們一個測試基准,可以用於和神經網絡和CNNs進行性能比較。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM