深度學習的發展不只突破了許多視覺難題,也加速了計算機視覺領域相關技術的進步。本文主要從CV數據處理、CV模型(CNN)、CV模型訓練流程以及CV模型集成對計算機視覺的基礎知識和基本環節進行了講解。python
https://tianchi.aliyun.com/competition/entrance/531795/information(阿里天池-零基礎入門CV賽事)git
五種數據讀取方法
目前較爲主流的Python圖像庫的基本使用方法:github
1. matplotlib算法
matplotlib是Python的繪圖庫,在科學繪圖領域被普遍使用。使用plt.imread()讀取圖片將其儲存爲一個RGB像素值矩陣,再進行處理。故其能夠與opencv或pillow結合使用,只須要傳入像素值矩陣,matplotlib即可以接手處理接下來想要完成的操做。2. PIL(pillow)安全
PIL即Python Imaging Library,而pillow是PIL的一個分支。pillow提供了常見的圖像讀取和處理的操做,它比opencv更爲輕巧,且能夠與ipython notebook無縫集成。使用Image.open()讀取圖片儲存爲一個對象,並不是是numpy矩陣。網絡
3. OpenCV架構
OpenCV是一個跨平臺的計算機視覺庫,是今天介紹的全部圖像庫中最全面也最強大的庫。使用cv2.imread()讀取圖片將其儲存爲一個BGR像素值矩陣,故若要結合使用matplotlib則要先進行轉化。app
4. skimage框架
skimage包是scikit-image SciKit (toolkit for SciPy) 的簡稱,它對scipy.ndimage進行了擴展,提供了更多的圖片處理功能。skimage包由許多的子模塊組成,各個子模塊功能不一樣。使用io.imread()讀取圖片將其儲存爲一個RGB像素值矩陣。dom
Imageio是一個Python庫,提供了一個簡單的接口用於讀取和寫入各類圖像數據,包括動畫圖像,視頻,體積數據和科學格式。使用imageio.imread()讀取圖片將其儲存爲一個RGB像素值矩陣。
五種數據擴增技巧
在深度學習模型的訓練過程當中,數據擴增是必不可少的環節。現有深度學習的參數很是多,通常的模型可訓練的參數量基本上都是萬到百萬級別,而訓練集樣本的數量很難有這麼多,數據擴增能夠擴展樣本空間。
擴增通常不會改變標籤;對於物體檢測,數據擴增會改變物體座標位置;對於圖像分割,數數據擴增方法有不少:從顏色空間、尺度空間到樣本空間,同時根據不一樣任務數據擴增都有相應的區別。對於圖像分類,數據據擴增會改變像素標籤。以torchvision.transforms爲例,首先總體瞭解數據擴增的方法,包括:
1. 裁剪
中心裁剪:transforms.CenterCrop;
隨機裁剪:transforms.RandomCrop;
隨機長寬比裁剪:transforms.RandomResizedCrop;
上下左右中心裁剪:transforms.FiveCrop;
上下左右中心裁剪後翻轉: transforms.TenCrop。
2. 翻轉和旋轉
依機率p水平翻轉:transforms.RandomHorizontalFlip(p=0.5);
依機率p垂直翻轉:transforms.RandomVerticalFlip(p=0.5);
隨機旋轉:transforms.RandomRotation。
3. 隨機遮擋
對圖像進行隨機遮擋: transforms.RandomErasing。
4. 圖像變換
尺寸變換: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/vision
2. imgaug
imgaug是經常使用的第三方數據擴增庫,提供了多樣的數據擴增方法,且組合起來很是方便,速度較快;
連接:https://github.com/aleju/imgaug
3. albumentations
是經常使用的第三方數據擴增庫,提供了多樣的數據擴增方法,對圖像分類、語義分割、物體檢測和關鍵點檢測都支持,速度較快。
連接:https://albumentations.readthedocs.io
CNN原理卷積神經網絡(Convolutional Neural Network, CNN)是一類特殊的人工神經網絡,是深度學習中重要的一個分支。CNN在不少領域都表現優異,精度和速度比傳統計算學習算法高不少。特別是在計算機視覺領域,CNN是解決圖像分類、圖像檢索、物體檢測和語義分割的主流模型。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,相對於卷積層進行卷積運算,池化層進行的運算通常有如下幾種:
最大池化(Max Pooling)。取4個點的最大值。這是最經常使用的池化方法。
均值池化(Mean Pooling)。取4個點的均值。
高斯池化。借鑑高斯模糊的方法。不經常使用。
最多見的池化層是規模爲2*2, 步幅爲2,對輸入的每一個深度切片進行下采樣。每一個MAX操做對四個數進行,以下圖所示:
池化操做將保存深度大小不變。若是池化層的輸入單元大小不是二的整數倍,通常採起邊緣補零(zero-padding)的方式補成2的倍數,而後再池化。
2.3 非線性激活函數
神經的非線性激活化函數,用於增長網絡的非線性分割能力,通常用Relu函數。
2.4 全鏈接層( Fully-Connected layer)
徹底鏈接層是一個傳統的多層感知器,它在輸出層使用 softmax 激活函數。把全部局部特徵結合變成全局特徵,用來計算最後每一類的得分。一個卷積神經網絡各層應用實例:
CNN常見模型1. 卷積神經網絡基礎:LeNet5手寫字體識別模型LeNet5誕生於1994年,是最先的卷積神經網絡之一。LeNet5經過巧妙的設計,利用卷積、參數共享、池化等操做提取特徵,避免了大量的計算成本,最後再使用全鏈接神經網絡進行分類識別,這個網絡也是最近大量神經網絡架構的起點。
以下圖所示爲LeNet網絡結構,總共有7層網絡(不含輸入層),2個卷積層、2個池化層、3個全鏈接層。
2. 卷積神經網絡進階
隨着網絡結構的發展,研究人員最初發現網絡模型結構越深、網絡參數越多模型的精度更優。比較典型的是AlexNet、VGG、InceptionV3和ResNet的發展脈絡。
2012年,AlexNet橫空出世。這個模型的名字來源於論文第一做者的姓名Alex Krizhevsky。AlexNet使用了8層卷積神經網絡,並以很大的優點贏得了ImageNet 2012圖像識別挑戰賽。它首次證實了學習到的特徵能夠超越手工設計的特徵,從而一舉打破計算機視覺研究的現狀。
與相對較小的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基礎塊組成。
Inception塊至關於⼀個有4條線路的⼦⽹絡。它經過不一樣窗口形狀的卷積層和最⼤池化層來並⾏抽取信息,並使⽤1×1卷積層減小通道數從而下降模型複雜度。
Inception塊GoogLeNet中的基礎卷積塊叫做Inception塊,得名於同名電影《盜夢空間》(Inception)。與上一節的NiN塊相比,這個基礎塊在結構上更加複雜。
深度學習的問題:深度CNN網絡達到必定深度後再一味地增長層數並不能帶來進一步地分類性能提升,反而會招致網絡收斂變得更慢,準確率也變得更差。- - -殘差塊(Residual Block)恆等映射:
左邊:f(x)=x;
右邊:f(x)-x=0 (易於捕捉恆等映射的細微波動)。
ResNet的前兩層跟以前介紹的GoogLeNet中的同樣:在輸出通道數爲6四、步幅爲2的7*7卷積層後接步幅爲2的3*3的最大池化層。不一樣之處在於ResNet每一個卷積層後增長的批量歸一化層。ResNet-50網絡結構以下:
在機器學習模型(特別是深度學習模型)的訓練過程當中,模型是很是容易過擬合的。深度學習模型在不斷的訓練過程當中訓練偏差會逐漸下降,但測試偏差的走勢則不必定。
在模型的訓練過程當中,模型只能利用訓練數據來進行訓練,並不能接觸到測試集上的樣本,故須要構建驗證數據集對模型進行驗證。
過擬合與欠擬合
擬合(Fitting):就是說這個曲線能不能很好的描述某些樣本,而且有比較好的泛化能力。
過擬合(Overfitting):模型把數據學習的太完全,以致於把噪聲數據的特徵也學習到了,這樣就會致使在後期測試的時候不可以很好地識別數據,即不能正確的分類,模型泛化能力太差。
欠擬合(UnderFitting):模型沒有很好地捕捉到數據特徵,不可以很好地擬合數據,或者是模型過於簡單沒法擬合或區分樣本。
防止過擬合方法
防止欠擬合方法
減小正則化參數,正則化的目的是用來防止過擬合的,可是如今模型出現了欠擬合,則須要減小正則化參數。
數據集劃分
測試集(Test Set):驗證模型的泛化能力。
由於訓練集和驗證集是分開的,因此模型在驗證集上面的精度在必定程度上能夠反映模型的泛化能力。在劃分驗證集的時候,須要注意驗證集的分佈應該與測試集儘可能保持一致,否則模型在驗證集上的精度就失去了指導意義。
既然驗證集這麼重要,那麼如何劃分本地驗證集呢。在一些比賽中,賽題方會給定驗證集;若是賽題方沒有給定驗證集,那麼參賽選手就須要從訓練集中拆分一部分獲得驗證集。驗證集的劃分有以下幾種方式:
留出法(Hold-Out) 直接將訓練集劃分紅兩部分,新的訓練集和驗證集。這種劃分方式的優勢是最爲直接簡單;缺點是隻獲得了一份驗證集,有可能致使模型在驗證集上過擬合。留出法應用場景是數據量比較大的狀況。
交叉驗證法(Cross Validation,CV) 將訓練集劃分紅K份,將其中的K-1份做爲訓練集,剩餘的1份做爲驗證集,循環K訓練。這種劃分方式是全部的訓練集都是驗證集,最終模型驗證精度是K份平均獲得。這種方式的優勢是驗證集精度比較可靠,訓練K次能夠獲得K個有多樣性差別的模型;CV驗證的缺點是須要訓練K次,不適合數據量很大的狀況。
這些劃分方法是從數據劃分方式的角度來說的,在現有的數據比賽中通常採用留出法和交叉驗證法。若是數據量比較大,留出法仍是比較合適的。
訓練神經網絡的流程
1. 好好檢查數據
訓練神經網絡的第一步是徹底不接觸任何神經網絡代碼,而是從完全檢查數據開始。此步驟相當重要。花時間去檢查數據是一件比較重要的工做。由於數據中每每可能存在異常值,並且瞭解它們的分佈能夠有利於咱們找到一個更好的模型。
2. 評估框架並獲得一個並不完美的baseline
此階段的提示和技巧:
固定隨機種子:始終使用固定的隨機種子來確保兩次運行代碼時您將得到相同的結果;
簡化:在此階段,請務必關閉任何數據擴充功能。數據擴充是咱們稍後可能會採用的一種正則化策略,可是目前這只是引入一種錯誤的嘗試;
驗證損失:驗證您的損失是否從正確的損失值開始;
設定一個好的初始化;
人類基線:監控除損失以外的指標,這些指標是人類能夠解釋和檢查的(例如準確性)。儘量評估本身(人類)的準確性並與之進行比較;
可視化預測動態。在訓練過程當中可視化固定測試批次上的模型預測。這些預測如何運動的「動力」將對訓練的進行方式有很是好的直覺。若是網絡以某種方式過分擺動,可能會感受網絡「努力」以適應您的數據,這代表不穩定。抖動量也很容易注意到很是低或很是高的學習率。
3. 過分擬合
找到一個好的模型的方法有兩個階段:首先得到一個足夠大的模型以使其能夠過分擬合(即專一於訓練損失),而後適當地對其進行正則化(放棄一些訓練損失以提升驗證損失)。
此階段的一些提示和技巧:
選擇模型:爲了減小訓練損失,您須要爲數據選擇合適的體系結構。
Adam是安全的。在設定基準的早期階段,我喜歡以3e-4的學習率使用Adam 。以個人經驗,亞當更寬容超參數,包括不良的學習速度。對於ConvNets,調整良好的SGD幾乎老是比Adam稍勝一籌,可是最佳學習率區域要狹窄得多且針對特定問題。
一次只使一個複雜化。若是您有多個信號要插入您的分類器,我建議您將它們一個接一個地插入,並每次確保得到預期的性能提高。
不要相信學習率衰減的默認值。若是您要從新使用其餘領域的代碼,請務必當心學習率。
4. 正則化
此階段的一些提示和技巧:
獲取更多數據
數據擴充
創意加強:若是半假數據沒有作到這一點,僞造數據也可能會有所做爲。人們正在尋找擴展數據集的創新方法。例如,領域隨機化,模擬的使用,巧妙的混合,例如將(潛在模擬的)數據插入場景,甚至GAN。
使用預訓練網絡
堅持監督學習
減少輸入維數
減少模型尺寸
減少批量大小
Dropout
提前中止訓練。根據您測得的驗證損失提早中止訓練,以在模型快要過擬合的時候捕獲模型。
嘗試更大的模型。大型模型大多數最終會過擬合,可是它們的「早期中止」性能一般會比小型模型好得多。
5. 微調
此階段的一些提示和技巧:
隨機網格搜索
超參數優化
6. 進一步提升精確率
模型集成
分類器(Classifier)
分類器是數據挖掘中對樣本進行分類的方法的統稱,包含決策樹、邏輯迴歸、樸素貝葉斯、神經網絡等算法。
分類器的構造和實施大致會通過如下幾個步驟:
1. 決策樹分類器
構造這個分類器不須要任何領域的知識,也不須要任何的參數設置。所以它特別適合於探測式的知識發現。此外,這個分類器還能夠處理高維數據,並且採用的是相似於樹這種形式,也特別直觀和便於理解。所以,決策樹是許多商業規則概括系統的基礎。
2. 樸素貝葉斯分類器
素貝葉斯分類器是假設數據樣本特徵徹底獨立,以貝葉斯定理爲基礎的簡單機率分類器。
3. AdaBoost算法
AdaBoost算法的自適應在於前一個分類器產生的錯誤分類樣本會被用來訓練下一個分類器,從而提高分類準確率,可是對於噪聲樣本和異常樣本比較敏感。
4. 支持向量機
支持向量機是用過構建一個或者多個高維的超平面來將樣本數據進行劃分,超平面即爲樣本之間的分類邊界。
5. K近鄰算法
基於k近鄰的K個樣本做爲分析從而簡化計算提高效率,K近鄰算法分類器是基於距離計算的分類器。
集成學習方法
集成學習有許多集成模型,例如自助法、自助聚合(Bagging)、隨機森林、提高法(Boosting)、 堆疊法(stacking) 以及許多其它的基礎集成學習模型。
集成方法的思想是經過將這些個體學習器(個體學習器稱爲「基學習器」,基學習器也被稱爲弱學習器。)的偏置和/或方差結合起來,從而建立一個 強學習器(或 集成模型),從而得到更好的性能。
咱們能夠用三種主要的旨在組合弱學習器的元算法:
自助聚合(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】理論實踐:
https://tianchi.aliyun.com/competition/entrance/531795/information
本文電子版教程 後臺回覆 cv實踐指南 下載