深度學習的發展不僅突破了許多視覺難題,也加速了計算機視覺領域相關技術的進步。本文主要從CV數據處理、CV模型(CNN)、CV模型訓練流程以及CV模型集成對計算機視覺的基礎知識和基本環節進行了講解。
CV數據下載https://tianchi.aliyun.com/competition/entrance/531795/information(阿里天池-零基礎入門CV賽事)
CV數據處理1. matplotlib
matplotlib是Python的繪圖庫,在科學繪圖領域被廣泛使用。使用plt.imread()讀取圖片將其儲存為一個RGB像素值矩陣,再進行處理。故其可以與opencv或pillow結合使用,只需要傳入像素值矩陣,matplotlib便可以接手處理接下來想要完成的操作。PIL即Python Imaging Library,而pillow是PIL的一個分支。pillow提供了常見的圖像讀取和處理的操作,它比opencv更為輕巧,且可以與ipython notebook無縫集成。使用Image.open()讀取圖片儲存為一個對象,並非是numpy矩陣。
3. OpenCV
OpenCV是一個跨平臺的計算機視覺庫,是今天介紹的所有圖像庫中最全面也最強大的庫。使用cv2.imread()讀取圖片將其儲存為一個BGR像素值矩陣,故若要結合使用matplotlib則要先進行轉化。4. skimage
skimage包是scikit-image SciKit (toolkit for SciPy) 的簡稱,它對scipy.ndimage進行了擴展,提供了更多的圖片處理功能。skimage包由許多的子模塊組成,各個子模塊功能不同。使用io.imread()讀取圖片將其儲存為一個RGB像素值矩陣。5. imageioImageio是一個Python庫,提供了一個簡單的接口用於讀取和寫入各種圖像數據,包括動畫圖像,視頻,體積數據和科學格式。使用imageio.imread()讀取圖片將其儲存為一個RGB像素值矩陣。五種數據擴增技巧
在深度學習模型的訓練過程中,數據擴增是必不可少的環節。現有深度學習的參數非常多,一般的模型可訓練的參數量基本上都是萬到百萬級別,而訓練集樣本的數量很難有這麼多,數據擴增可以擴展樣本空間。
1. 裁剪
中心裁剪:transforms.CenterCrop;
隨機裁剪:transforms.RandomCrop;
隨機長寬比裁剪:transforms.RandomResizedCrop;
上下左右中心裁剪:transforms.FiveCrop;
上下左右中心裁剪後翻轉: transforms.TenCrop。
依概率p水平翻轉:transforms.RandomHorizontalFlip(p=0.5);
依概率p垂直翻轉:transforms.RandomVerticalFlip(p=0.5);
隨機旋轉:transforms.RandomRotation。
尺寸變換:transforms.Resize;
標準化:transforms.Normalize;
填充:transforms.Pad;
修改亮度、對比度和飽和度:transforms.ColorJitter;
轉灰度圖:transforms.Grayscale;
依概率p轉為灰度圖:transforms.RandomGrayscale;
線性變換:transforms.LinearTransformation();
仿射變換:transforms.RandomAffine;
將數據轉換為PILImage:transforms.ToPILImage;
轉為tensor,並歸一化至[0-1]:transforms.ToTensor;
用戶自定義方法:transforms.Lambda。
5. 對transforms操作,使數據增強更靈活transforms.RandomChoice(transforms): 從給定的一系列transforms中選一個進行操作;
transforms.RandomApply(transforms, p=0.5): 給一個transform加上概率,依概率進行操作;
transforms.RandomOrder: 將transforms中的操作隨機打亂。
常用的數據擴增庫1. torchvision
pytorch官方提供的數據擴增庫,提供了基本的數據擴增方法,可以無縫與torch進行集成;但數據擴增方法種類較少,且速度中等;
連結:https://github.com/pytorch/vision2. imgaug
imgaug是常用的第三方數據擴增庫,提供了多樣的數據擴增方法,且組合起來非常方便,速度較快;
連結:https://github.com/aleju/imgaug3. albumentations
是常用的第三方數據擴增庫,提供了多樣的數據擴增方法,對圖像分類、語義分割、物體檢測和關鍵點檢測都支持,速度較快。
連結:https://albumentations.readthedocs.io
CV模型(CNN)1. 具有三維體積的神經元(3D volumes of neurons)
卷積神經網絡利用輸入圖片的特點,把神經元設計成三個維度 :width, height, depth。比如輸入的圖片大小是 32 × 32 × 3 (rgb),那麼輸入神經元就也具有 32×32×3 的維度。下面是傳統神經網絡的示意圖:
一個卷積神經網絡由很多層組成,它們的輸入是三維的,輸出也是三維的,有的層有參數,有的層不需要參數。卷積神經網絡的示意圖如下:
2. 卷積神經網絡結構
2.1 卷積層(Convolutional layer)卷積神經網路中每層卷積層由若干卷積單元組成,每個卷積單元的參數都是通過反向傳播算法優化得到的。卷積運算的目的是提取輸入的不同特徵,第一層卷積層可能只能提取一些低級的特徵如邊緣、線條和角等層級,更多層的網絡能從低級特徵中迭代提取更複雜的特徵。
2.2 池化層(Pooling layer)
通常在卷積層之後會得到維度很大的特徵,將特徵切成幾個區域,取其最大值或平均值,得到新的、維度較小的特徵。池化即下採樣,目的是為了減少特徵圖。池化操作對每個深度切片獨立,規模一般為 2*2,相對於卷積層進行卷積運算,池化層進行的運算一般有以下幾種:
最常見的池化層是規模為2*2, 步幅為2,對輸入的每個深度切片進行下採樣。每個MAX操作對四個數進行,如下圖所示:2.3 非線性激活函數
神經的非線性激活化函數,用於增加網絡的非線性分割能力,一般用Relu函數。2.4 全連接層( Fully-Connected layer)
完全連接層是一個傳統的多層感知器,它在輸出層使用 softmax 激活函數。把所有局部特徵結合變成全局特徵,用來計算最後每一類的得分。一個卷積神經網絡各層應用實例:
如下圖所示為LeNet網絡結構,總共有7層網絡(不含輸入層),2個卷積層、2個池化層、3個全連接層。
隨著網絡結構的發展,研究人員最初發現網絡模型結構越深、網絡參數越多模型的精度更優。比較典型的是AlexNet、VGG、InceptionV3和ResNet的發展脈絡。
與相對較小的LeNet相比,AlexNet包含8層變換,其中有5層卷積和2層全連接隱藏層,以及1個全連接輸出層。AlexNet在LeNet的基礎上增加了3個卷積層。但AlexNet作者對它們的卷積窗口、輸出通道數和構造順序均做了大量的調整。雖然AlexNet指明了深度卷積神經網絡可以取得出色的結果,但並沒有提供簡單的規則以指導後來的研究者如何設計新的網絡。
VGG,它的名字來源於論文作者所在的實驗室Visual Geometry Group。VGG提出了可以通過重複使用簡單的基礎塊來構建深度模型的思路。VGG16相比AlexNet的一個改進是採用連續的幾個3x3的卷積核代替AlexNet中的較大卷積核(11x11,7x7,5x5) 。VGG16包含了16個隱藏層(13個卷積層和3個全連接層)。VGG的結構圖如下:
在2014年的ImageNet圖像識別挑戰賽中,一個名叫GoogLeNet的網絡結構大放異彩。它雖然在名字上向LeNet致敬,但在網絡結構上已經很難看到LeNet的影子。GoogLeNet吸收了NiN中網絡串聯網絡的思想,並在此基礎上做了很大改進。在隨後的幾年裡,研究人員對GoogLeNet進行了數次改進,本節將介紹這個模型系列的第一個版本。
Inception塊GoogLeNet中的基礎卷積塊叫作Inception塊,得名於同名電影《盜夢空間》(Inception)。與上一節的NiN塊相比,這個基礎塊在結構上更加複雜。2.5 殘差網絡(ResNet-50)深度學習的問題:深度CNN網絡達到一定深度後再一味地增加層數並不能帶來進一步地分類性能提高,反而會招致網絡收斂變得更慢,準確率也變得更差。- - -殘差塊(Residual Block)恆等映射:
ResNet的前兩層跟之前介紹的GoogLeNet中的一樣:在輸出通道數為64、步幅為2的7*7卷積層後接步幅為2的3*3的最大池化層。不同之處在於ResNet每個卷積層後增加的批量歸一化層。ResNet-50網絡結構如下:
在機器學習模型(特別是深度學習模型)的訓練過程中,模型是非常容易過擬合的。深度學習模型在不斷的訓練過程中訓練誤差會逐漸降低,但測試誤差的走勢則不一定。
在模型的訓練過程中,模型只能利用訓練數據來進行訓練,並不能接觸到測試集上的樣本,故需要構建驗證數據集對模型進行驗證。
擬合(Fitting):就是說這個曲線能不能很好的描述某些樣本,並且有比較好的泛化能力。
過擬合(Overfitting):模型把數據學習的太徹底,以至於把噪聲數據的特徵也學習到了,這樣就會導致在後期測試的時候不能夠很好地識別數據,即不能正確的分類,模型泛化能力太差。
欠擬合(UnderFitting):模型沒有很好地捕捉到數據特徵,不能夠很好地擬合數據,或者是模型過於簡單無法擬合或區分樣本。
防止欠擬合方法
添加其他特徵項,有時候我們模型出現欠擬合的時候是因為特徵項不夠導致的,可以添加其他特徵項來很好地解決。例如,「組合」、「泛化」、「相關性」三類特徵是特徵添加的重要手段,無論在什麼場景,都可以照葫蘆畫瓢,總會得到意想不到的效果。除上面的特徵之外,「上下文特徵」、「平臺特徵」等等,都可以作為特徵添加的首選項。添加多項式特徵,這個在機器學習算法裡面用的很普遍,例如將線性模型通過添加二次項或者三次項使模型泛化能力更強。例如上面的圖片的例子。減少正則化參數,正則化的目的是用來防止過擬合的,但是現在模型出現了欠擬合,則需要減少正則化參數。
數據集劃分
訓練集(Train Set):模型用於訓練和調整模型參數。驗證集(Validation Set):用來驗證模型精度和調整模型超參數。測試集(Test Set):驗證模型的泛化能力。
因為訓練集和驗證集是分開的,所以模型在驗證集上面的精度在一定程度上可以反映模型的泛化能力。在劃分驗證集的時候,需要注意驗證集的分布應該與測試集儘量保持一致,不然模型在驗證集上的精度就失去了指導意義。既然驗證集這麼重要,那麼如何劃分本地驗證集呢。在一些比賽中,賽題方會給定驗證集;如果賽題方沒有給定驗證集,那麼參賽選手就需要從訓練集中拆分一部分得到驗證集。驗證集的劃分有如下幾種方式:
留出法(Hold-Out) 直接將訓練集劃分成兩部分,新的訓練集和驗證集。這種劃分方式的優點是最為直接簡單;缺點是只得到了一份驗證集,有可能導致模型在驗證集上過擬合。留出法應用場景是數據量比較大的情況。
交叉驗證法(Cross Validation,CV) 將訓練集劃分成K份,將其中的K-1份作為訓練集,剩餘的1份作為驗證集,循環K訓練。這種劃分方式是所有的訓練集都是驗證集,最終模型驗證精度是K份平均得到。這種方式的優點是驗證集精度比較可靠,訓練K次可以得到K個有多樣性差異的模型;CV驗證的缺點是需要訓練K次,不適合數據量很大的情況。
自助採樣法(BootStrap) 通過有放回的採樣方式得到新的訓練集和驗證集,每次的訓練集和驗證集都是有區別的。這種劃分方式一般適用於數據量較小的情況。這些劃分方法是從數據劃分方式的角度來講的,在現有的數據比賽中一般採用留出法和交叉驗證法。如果數據量比較大,留出法還是比較合適的。
訓練神經網絡的流程
1. 好好檢查數據
訓練神經網絡的第一步是完全不接觸任何神經網絡代碼,而是從徹底檢查數據開始。此步驟至關重要。花時間去檢查數據是一件比較重要的工作。因為數據中往往可能存在異常值,而且了解它們的分布可以有利於我們找到一個更好的模型。
2. 評估框架並得到一個並不完美的baseline此階段的提示和技巧:
固定隨機種子:始終使用固定的隨機種子來確保兩次運行代碼時您將獲得相同的結果;
簡化:在此階段,請務必關閉任何數據擴充功能。數據擴充是我們稍後可能會採用的一種正則化策略,但是目前這只是引入一種錯誤的嘗試;
驗證損失:驗證您的損失是否從正確的損失值開始;
設定一個好的初始化;
人類基線:監控除損失之外的指標,這些指標是人類可以解釋和檢查的(例如準確性)。儘可能評估自己(人類)的準確性並與之進行比較;
可視化預測動態。在訓練過程中可視化固定測試批次上的模型預測。這些預測如何運動的「動力」將對訓練的進行方式有非常好的直覺。如果網絡以某種方式過度擺動,可能會感覺網絡「努力」以適應您的數據,這表明不穩定。抖動量也很容易注意到非常低或非常高的學習率。
找到一個好的模型的方法有兩個階段:首先獲得一個足夠大的模型以使其可以過度擬合(即專注於訓練損失),然後適當地對其進行正則化(放棄一些訓練損失以提高驗證損失)。
此階段的一些提示和技巧:
選擇模型:為了減少訓練損失,您需要為數據選擇合適的體系結構。
Adam是安全的。在設定基準的早期階段,我喜歡以3e-4的學習率使用Adam 。以我的經驗,亞當更寬容超參數,包括不良的學習速度。對於ConvNets,調整良好的SGD幾乎總是比Adam稍勝一籌,但是最佳學習率區域要狹窄得多且針對特定問題。
一次只使一個複雜化。如果您有多個信號要插入您的分類器,我建議您將它們一個接一個地插入,並每次確保獲得預期的性能提升。
不要相信學習率衰減的默認值。如果您要重新使用其他領域的代碼,請務必小心學習率。
此階段的一些提示和技巧:
獲取更多數據
數據擴充
創意增強:如果半假數據沒有做到這一點,偽造數據也可能會有所作為。人們正在尋找擴展數據集的創新方法。例如,領域隨機化,模擬的使用,巧妙的混合,例如將(潛在模擬的)數據插入場景,甚至GAN。
使用預訓練網絡
堅持監督學習
減小輸入維數
減小模型尺寸
減小批量大小
Dropout
提早停止訓練。根據您測得的驗證損失提前停止訓練,以在模型快要過擬合的時候捕獲模型。
嘗試更大的模型。大型模型大多數最終會過擬合,但是它們的「早期停止」性能通常會比小型模型好得多。
5. 微調
此階段的一些提示和技巧:
CV模型集成分類器是數據挖掘中對樣本進行分類的方法的統稱,包含決策樹、邏輯回歸、樸素貝葉斯、神經網絡等算法。
選定樣本(包含正樣本和負樣本),將所有樣本分成訓練樣本和測試樣本兩部分。根據預測結果,計算必要的評估指標,評估分類模型的性能。構造這個分類器不需要任何領域的知識,也不需要任何的參數設置。因此它特別適合於探測式的知識發現。此外,這個分類器還可以處理高維數據,而且採用的是類似於樹這種形式,也特別直觀和便於理解。因此,決策樹是許多商業規則歸納系統的基礎。
2. 樸素貝葉斯分類器
素貝葉斯分類器是假設數據樣本特徵完全獨立,以貝葉斯定理為基礎的簡單概率分類器。
3. AdaBoost算法
AdaBoost算法的自適應在於前一個分類器產生的錯誤分類樣本會被用來訓練下一個分類器,從而提升分類準確率,但是對於噪聲樣本和異常樣本比較敏感。
4. 支持向量機
支持向量機是用過構建一個或者多個高維的超平面來將樣本數據進行劃分,超平面即為樣本之間的分類邊界。
5. K近鄰算法
基於k近鄰的K個樣本作為分析從而簡化計算提升效率,K近鄰算法分類器是基於距離計算的分類器。
集成學習有許多集成模型,例如自助法、自助聚合(Bagging)、隨機森林、提升法(Boosting)、 堆疊法(stacking) 以及許多其它的基礎集成學習模型。
集成方法的思想是通過將這些個體學習器(個體學習器稱為「基學習器」,基學習器也被稱為弱學習器。)的偏置和/或方差結合起來,從而創建一個 強學習器(或 集成模型),從而獲得更好的性能。我們可以用三種主要的旨在組合弱學習器的元算法:
非常粗略地說,我們可以說Bagging的重點在於獲得一個方差比其組成部分更小的集成模型,而Boosting和Stacking則將主要生成偏置比其組成部分更低的強模型(即使方差也可以被減小)。
十折交叉驗證
由於深度學習模型一般需要較長的訓練周期,如果硬體設備不允許建議選取留出法,如果需要追求精度可以使用交叉驗證的方法。十折交叉驗證用來測試算法準確性。將數據集分成十份,輪流將其中九份作為訓練數據,一份作為測試數據,進行試驗。每次試驗都會得出相應的正確率(或差錯率)。十次的結果的正確率(或差錯率)的平均值作為對算法精度的估計,一般還需要進行多次十折交叉驗證(例如十次十折交叉驗證),再求其均值,作為對算法準確性的估計。下面假設構建了十折交叉驗證,訓練得到十個CNN模型。那麼在十個CNN模型可以使用如下方式進行集成:
對預測的結果的概率值進行平均,然後解碼為具體字符
對預測的字符進行投票,得到最終字符
深度學習中的集成學習在深度學習中本身還有一些集成學習思路的做法,值得借鑑學習:丟棄法Dropout
Snapshot
延伸閱讀【1】數據讀取:
https://mp.weixin.qq.com/s/IOlHIEIQhuIaubTeP4o39
【2】CNN模型:
https://mp.weixin.qq.com/s/JhFun5I_8Kjkbz6S4613Xw
【3】模型訓練:
https://mp.weixin.qq.com/s/ZwfrIkHQMsHl_16xvCSejQ
【4】模型集成:
https://mp.weixin.qq.com/s/I41c-i-6y-pPdZOeiMM_0Q
【5】理論實踐:
本文電子版教程 後臺回復 cv實踐指南 下載
「在看,為學習到這點讚↓