CNN原理與實踐指南

2021-02-23 機器學習實驗室

Author:陳樺、夏雨柔、樊亮

From:Datawhale

卷積神經網絡CNN是深度學習中的基礎知識。本文對CNN的基礎原理及常見的CNN網絡進行了詳細解讀,並介紹了Pytorch構建深度網絡的流程。最後,以阿里天池零基礎入門CV賽事為學習實踐,對Pytorch構建CNN模型進行實現。數據及背景  https://tianchi.aliyun.com/competition/entrance/531795/introduction(阿里天池 - 零基礎入門CV賽事)CNN原理

CNN,又稱卷積神經網絡,是深度學習中重要的一個分支。CNN在很多領域都表現優異,精度和速度比傳統計算學習算法高很多。特別是在計算機視覺領域,CNN是解決圖像分類、圖像檢索、物體檢測和語義分割的主流模型。

1. 卷積

如圖1所示,圖中的X和O無論怎麼旋轉或者縮放,人眼其實還是很容易識別出X和O。

圖1

但是計算機不同,它看到的其實是一個個的像素陣列,如圖2。如何對像素的陣列進行特徵的提取其實就是卷積神經網絡要幹的事情。

圖2

再看圖3,我們發現X即使進行了旋轉,但是綠、橙、紫框標記的區域在兩張圖中還是一致的,某種程度上,這其實就是X的特徵。

圖3

因此可以將這三個特徵的區間提取出來,就形成了三個卷積核,如圖4所示。

圖4

既然有了卷積核,那麼卷積核是如何進行卷積操作的呢?其實很簡單,可以看一下圖5,卷積核其實就是拿著這個矩陣在圖片的矩陣上一點點的平移,就像掃地一樣。每掃到一處地方就可以進行卷積的運算,計算方法很簡單,如圖5所示,左上角的卷積核掃到綠色框的位置,則卷積核矩陣的數字就和掃到的位置的矩陣的數字一一對應相乘然後相加,最後取一個均值,該值就是卷積核提取的特徵。

圖5

卷積核提取的所有的特徵組成了一個長和寬變小的矩陣,這個矩陣又稱為feature map,如圖6。使用不同的卷積核也就能提取出不同的feature map。所以可以想像的是,如果不斷的進行卷積操作,那麼圖片的矩陣會逐步地長寬減少,厚度增加。

圖6

可以看到卷積操作通過卷積核是可以分別提取到圖片的特徵的,但是如何提前知道卷積核呢?像上文的例子,很容易可以找到3個卷積核,但是假如是人臉識別這樣成千上萬個特徵的圖片,就沒辦法提前知道什麼是合適的卷積核。其實也沒必要知道,因為選擇什麼樣的卷積核,完全可以通過訓練不斷優化。初始時只需要隨機設置一些卷積核,通過訓練,模型其實自己可以學習到合適的卷積核,這也是卷積神經網絡模型強大的地方。2. 池化(pooling)池化,也叫下採樣,本質上其實就是對數據進行一個縮小。因為我們知道,比如人臉識別,通過卷積操作得到成千上萬個feature map,每個feature map也有很多的像素點,這些對於後續的運算的時間會變得很長。

池化其實就是對每個feature map進一步提煉的過程。如圖7所示,原來4X4的feature map經過池化操作之後就變成了更小的2*2的矩陣。池化的方法包括max pooling,即取最大值,以及average pooling,即取平均值。

圖7

3. Normalization

這裡的Normalization就是將矩陣中負數的值轉成0,也就是使用一個稱之為ReLu的激活函數進行負數變為0的操作。ReLu函數本質上就是max(0,x)。這一步其實也是為了方便運算。

4. 卷積神經網絡理解

因此卷積、ReLu、pooling,不斷重複其實也就基本上構成了卷積神經網絡的框架,如圖8。然後將最終得到的feaure map 排成一列(圖8),接到全連接層,這樣就形成了我們的卷積神經網絡。值得注意的是,排成一列的數值,是有權重,而這些權重是通過訓練、反向傳播得到的,通過權重的計算,可以知道不同分類的概率是怎麼樣的。

圖8

卷積神經網絡手寫字體識別模型LeNet5誕生於1994年,是最早的卷積神經網絡之一。LeNet5通過巧妙的設計,利用卷積、參數共享、池化等操作提取特徵,避免了大量的計算成本,最後再使用全連接神經網絡進行分類識別,這個網絡也是最近大量神經網絡架構的起點。

如下圖所示為LeNet網絡結構,總共有7層網絡(不含輸入層),2個卷積層、2個池化層、3個全連接層。

LeNet分為卷積層塊和全連接層塊兩個部分。下面我們分別介紹這兩個模塊。卷積層塊裡的基本單位是卷積層後接最大池化層:卷積層用來識別圖像裡的空間模式,如線條和物體局部,之後的最大池化層則用來降低卷積層對位置的敏感性。卷積層塊由兩個這樣的基本單位重複堆疊構成。在卷積層塊中,每個卷積層都使用5*5的窗口,並在輸出上使用sigmoid激活函數。第一個卷積層輸出通道數為6,第二個卷積層輸出通道數則增加到16。這是因為第二個卷積層比第一個卷積層的輸入的高和寬要小,所以增加輸出通道使兩個卷積層的參數尺寸類似。卷積層塊的兩個最大池化層的窗口形狀均為2*2,且步幅為2。由於池化窗口與步幅形狀相同,池化窗口在輸入上每次滑動所覆蓋的區域互不重疊。卷積層塊的輸出形狀為(批量大小, 通道, 高, 寬)。當卷積層塊的輸出傳入全連接層塊時,全連接層塊會將小批量中每個樣本變平(flatten)。也就是說,全連接層的輸入形狀將變成二維,其中第一維是小批量中的樣本,第二維是每個樣本變平後的向量表示,且向量長度為通道、高和寬的乘積。全連接層塊含3個全連接層。它們的輸出個數分別是120、84和10,其中10為輸出的類別個數。

在卷積層塊中輸入的高和寬在逐層減小。卷積層由於使用高和寬均為5的卷積核,從而將高和寬分別減小4,而池化層則將高和寬減半,但通道數則從1增加到16。全連接層則逐層減少輸出個數,直到變成圖像的類別數10。

通過多次卷積和池化,CNN的最後一層將輸入的圖像像素映射為具體的輸出。如在分類任務中會轉換為不同類別的概率輸出,然後計算真實標籤與CNN模型的預測結果的差異,並通過反向傳播更新每層的參數,並在更新完成後再次前向傳播,如此反覆直到訓練完成 。 

一個數字識別的效果如圖所示:


卷積神經網絡進階

隨著網絡結構的發展,研究人員最初發現網絡模型結構越深、網絡參數越多模型的精度更優。比較典型的是AlexNet、VGG、InceptionV3和ResNet的發展脈絡。     

1. AlexNet(2012)

2012年,AlexNet橫空出世。這個模型的名字來源於論文第一作者的姓名Alex Krizhevsky。AlexNet使用了8層卷積神經網絡,並以很大的優勢贏得了ImageNet 2012圖像識別挑戰賽。它首次證明了學習到的特徵可以超越手工設計的特徵,從而一舉打破計算機視覺研究的前狀。

AlexNet與LeNet的設計理念非常相似,但也有顯著的區別。

1. 與相對較小的LeNet相比,AlexNet包含8層變換,其中有5層卷積和2層全連接隱藏層,以及1個全連接輸出層。下面我們來詳細描述這些層的設計:AlexNet第一層中的卷積窗口形狀是11*11。因為ImageNet中絕大多數圖像的高和寬均比MNIST圖像的高和寬大10倍以上,ImageNet圖像的物體佔用更多的像素,所以需要更大的卷積窗口來捕獲物體。第二層中的卷積窗口形狀減小到5*5,之後全採用3*3。此外,第一、第二和第五個卷積層之後都使用了窗口形狀為3*3、步幅為2的最大池化層。而且,AlexNet使用的卷積通道數也大於LeNet中的卷積通道數數十倍。緊接著最後一個卷積層的是兩個輸出個數為4096的全連接層。這兩個巨大的全連接層帶來將近1 GB的模型參數。由於早期顯存的限制,最早的AlexNet使用雙數據流的設計使一個GPU只需要處理一半模型。幸運的是,顯存在過去幾年得到了長足的發展,因此通常我們不再需要這樣的特別設計了。2. AlexNet將sigmoid激活函數改成了更加簡單的ReLU激活函數。一方面,ReLU激活函數的計算更簡單,例如它並沒有sigmoid激活函數中的求冪運算。另一方面,ReLU激活函數在不同的參數初始化方法下使模型更容易訓練。這是由於當sigmoid激活函數輸出極接近0或1時,這些區域的梯度幾乎為0,從而造成反向傳播無法繼續更新部分模型參數;而ReLU激活函數在正區間的梯度恆為1。因此,若模型參數初始化不當,sigmoid函數可能在正區間得到幾乎為0的梯度,從而令模型無法得到有效訓練。3. AlexNet通過丟棄法來控制全連接層的模型複雜度。而LeNet並沒有使用丟棄法。4. AlexNet引入了大量的圖像增廣,如翻轉、裁剪和顏色變化,從而進一步擴大數據集來緩解過擬合。我們將在後面的圖像增廣中詳細介紹這種方法。

小結:

2. VGG-16(2014)  

AlexNet在LeNet的基礎上增加了3個卷積層。但AlexNet作者對它們的卷積窗口、輸出通道數和構造順序均做了大量的調整。雖然AlexNet指明了深度卷積神經網絡可以取得出色的結果,但並沒有提供簡單的規則以指導後來的研究者如何設計新的網絡。VGG,它的名字來源於論文作者所在的實驗室Visual Geometry Group。VGG提出了可以通過重複使用簡單的基礎塊來構建深度模型的思路。VGG的結構圖如下:

VGG塊的組成規律是:連續使用數個相同的填充為1、窗口形狀為3*3的卷積層後接上一個步幅為2、窗口形狀為2*2的最大池化層。卷積層保持輸入的高和寬不變,而池化層則對其減半。我們使用vgg_block函數來實現這個基礎的VGG塊,它可以指定卷積層的數量和輸入輸出通道數。

對於給定的感受野(與輸出有關的輸入圖片的局部大小),採用堆積的小卷積核優於採用大的卷積核,因為可以增加網絡深度來保證學習更複雜的模式,而且代價還比較小(參數更少)。例如,在VGG中,使用了3個3x3卷積核來代替7x7卷積核,使用了2個3x3卷積核來代替5*5卷積核,這樣做的主要目的是在保證具有相同感知野的條件下,提升了網絡的深度,在一定程度上提升了神經網絡的效果。

與AlexNet和LeNet一樣,VGG網絡由卷積層模塊後接全連接層模塊構成。卷積層模塊串聯數個vgg_block,其超參數由變量conv_arch定義。該變量指定了每個VGG塊裡卷積層個數和輸入輸出通道數。全連接模塊則跟AlexNet中的一樣。現在我們構造一個VGG網絡。它有5個卷積塊,前2塊使用單卷積層,而後3塊使用雙卷積層。第一塊的輸入輸出通道分別是1(因為下面要使用的Fashion-MNIST數據的通道數為1)和64,之後每次對輸出通道數翻倍,直到變為512。因為這個網絡使用了8個卷積層和3個全連接層,所以經常被稱為VGG-11。可以看到,每次我們將輸入的高和寬減半,直到最終高和寬變成7後傳入全連接層。與此同時,輸出通道數每次翻倍,直到變成512。因為每個卷積層的窗口大小一樣,所以每層的模型參數尺寸和計算複雜度與輸入高、輸入寬、輸入通道數和輸出通道數的乘積成正比。VGG這種高和寬減半以及通道翻倍的設計使得多數卷積層都有相同的模型參數尺寸和計算複雜度。

VGG:通過重複使⽤簡單的基礎塊來構建深度模型。   Block: 數個相同的填充為1、窗口形狀為3×3的卷積層,接上一個步幅為2、窗口形狀為2×2的最大池化層。卷積層保持輸入的高和寬不變,而池化層則對其減半。VGG和AlexNet的網絡圖對比如下:

小結:VGG-11通過5個可以重複使用的卷積塊來構造網絡。根據每塊裡卷積層個數和輸出通道數的不同可以定義出不同的VGG模型。     

3. 網絡中的網絡(NiN)LeNet、AlexNet和VGG:先以由卷積層構成的模塊充分抽取空間特徵,再以由全連接層構成的模塊來輸出分類結果。NiN:串聯多個由卷積層和「全連接」層構成的小⽹絡來構建⼀個深層⽹絡。 ⽤了輸出通道數等於標籤類別數的NiN塊,然後使⽤全局平均池化層對每個通道中所有元素求平均並直接用於分類。 1×1卷積核作用

NiN塊我們知道,卷積層的輸入和輸出通常是四維數組(樣本,通道,高,寬),而全連接層的輸入和輸出則通常是二維數組(樣本,特徵)。如果想在全連接層後再接上卷積層,則需要將全連接層的輸出變換為四維。回憶在多輸入通道和多輸出通道裡介紹的1*1卷積層。它可以看成全連接層,其中空間維度(高和寬)上的每個元素相當於樣本,通道相當於特徵。因此,NiN使用1*1卷積層來替代全連接層,從而使空間信息能夠自然傳遞到後面的層中去。

NiN塊是NiN中的基礎塊。它由一個卷積層加兩個充當全連接層的1*1卷積層串聯而成。其中第一個卷積層的超參數可以自行設置,而第二和第三個卷積層的超參數一般是固定的。NiN是在AlexNet問世不久後提出的。它們的卷積層設定有類似之處。NiN使用卷積窗口形狀分別為11*11、5*5和的3*3卷積層,相應的輸出通道數也與AlexNet中的一致。每個NiN塊後接一個步幅為2、窗口形狀為3*3的最大池化層。除使用NiN塊以外,NiN還有一個設計與AlexNet顯著不同:NiN去掉了AlexNet最後的3個全連接層,取而代之地,NiN使用了輸出通道數等於標籤類別數的NiN塊,然後使用全局平均池化層對每個通道中所有元素求平均並直接用於分類。這裡的全局平均池化層即窗口形狀等於輸入空間維形狀的平均池化層。NiN的這個設計的好處是可以顯著減小模型參數尺寸,從而緩解過擬合。然而,該設計有時會造成獲得有效模型的訓練時間的增加。

小結:

NiN重複使用由卷積層和代替全連接層的1*1卷積層構成的NiN塊來構建深層網絡。

NiN去除了容易造成過擬合的全連接輸出層,而是將其替換成輸出通道數等於標籤類別數的NiN塊和全局平均池化層。

NiN的以上設計思想影響了後面一系列卷積神經網絡的設計。

4. 含並行連結的網絡(GoogLeNet)

在2014年的ImageNet圖像識別挑戰賽中,一個名叫GoogLeNet的網絡結構大放異彩。它雖然在名字上向LeNet致敬,但在網絡結構上已經很難看到LeNet的影子。GoogLeNet吸收了NiN中網絡串聯網絡的思想,並在此基礎上做了很大改進。在隨後的幾年裡,研究人員對GoogLeNet進行了數次改進,本節將介紹這個模型系列的第一個版本。

Inception塊GoogLeNet中的基礎卷積塊叫作Inception塊,得名於同名電影《盜夢空間》(Inception)。與上一節介紹的NiN塊相比,這個基礎塊在結構上更加複雜。Inception塊裡有4條並行的線路。前3條線路使用窗口大小分別是1*1、3*3和5*5的卷積層來抽取不同空間尺寸下的信息,其中中間2個線路會對輸入先做1*1卷積來減少輸入通道數,以降低模型複雜度。第四條線路則使用3*3最大池化層,後接1*1卷積層來改變通道數。4條線路都使用了合適的填充來使輸入與輸出的高和寬一致。最後我們將每條線路的輸出在通道維上連結,並輸入接下來的層中去。Inception塊中可以自定義的超參數是每個層的輸出通道數,我們以此來控制模型複雜度。GoogLeNet跟VGG一樣,在主體卷積部分中使用5個模塊(block),每個模塊之間使用步幅為2的3*3最大池化層來減小輸出高寬。第二模塊使用2個卷積層:首先是64通道的1*1卷積層,然後是將通道增大3倍的3*3卷積層。它對應Inception塊中的第二條線路。第三模塊串聯2個完整的Inception塊。第一個Inception塊的輸出通道數為64+128+32+32=256,其中4條線路的輸出通道數比例為64:128:32:32=2:4:1:1。其中第二、第三條線路先分別將輸入通道數減小至96/192=1/2和16/192=1/12後,再接上第二層卷積層。第二個Inception塊輸出通道數增至128+192+96+64=480,每條線路的輸出通道數之比為128:192:96:64 = 4:6:3:2。其中第二、第三條線路先分別將輸入通道數減小至128/256=1/2和32/256=1/8。第四模塊更加複雜。它串聯了5個Inception塊,其輸出通道數分別是192+208+48+64=512、160+224+64+64=512、128+256+64+64=512、112+288+64+64=528和256+320+128+128=832。這些線路的通道數分配和第三模塊中的類似,首先含3*3卷積層的第二條線路輸出最多通道,其次是僅含1*1卷積層的第一條線路,之後是含5*5卷積層的第三條線路和含1*1最大池化層的第四條線路。其中第二、第三條線路都會先按比例減小通道數。這些比例在各個Inception塊中都略有不同。第五模塊有輸出通道數為256+320+128+128=832和384+384+128+128=1024的兩個Inception塊。其中每條線路的通道數的分配思路和第三、第四模塊中的一致,只是在具體數值上有所不同。需要注意的是,第五模塊的後面緊跟輸出層,該模塊同NiN一樣使用全局平均池化層來將每個通道的高和寬變成1。最後我們將輸出變成二維數組後接上一個輸出個數為標籤類別數的全連接層。GoogLeNet模型的計算複雜,而且不如VGG那樣便於修改通道數。

小結:

Inception塊相當於一個有4條線路的子網絡。它通過不同窗口形狀的卷積層和最大池化層來並行抽取信息,並使用1*1卷積層減少通道數從而降低模型複雜度。

GoogLeNet將多個設計精細的Inception塊和其他層串聯起來。其中Inception塊的通道數分配之比是在ImageNet數據集上通過大量的實驗得來的。

GoogLeNet和它的後繼者們一度是ImageNet上最高效的模型之一:在類似的測試精度下,它們的計算複雜度往往更低。

5、殘差網絡(ResNet-50)      

深度學習的問題:深度CNN網絡達到一定深度後再一味地增加層數並不能帶來進一步地分類性能提高,反而會招致網絡收斂變得更慢,準確率也變得更差。- - -殘差塊(Residual Block)恆等映射:

ResNet沿用了VGG全3*3卷積層的設計。殘差塊裡首先有2個有相同輸出通道數的3*3卷積層。每個卷積層後接一個批量歸一化層和ReLU激活函數。然後我們將輸入跳過這兩個卷積運算後直接加在最後的ReLU激活函數前。這樣的設計要求兩個卷積層的輸出與輸入形狀一樣,從而可以相加。如果想改變通道數,就需要引入一個額外的1*1卷積層來將輸入變換成需要的形狀後再做相加運算。在殘差塊中,輸⼊可通過跨層的數據線路更快地向前傳播。

ResNet的前兩層跟之前介紹的GoogLeNet中的一樣:在輸出通道數為64、步幅為2的7*7卷積層後接步幅為2的3*3的最大池化層。不同之處在於ResNet每個卷積層後增加的批量歸一化層。ResNet-50網絡結構如下:

GoogLeNet在後面接了4個由Inception塊組成的模塊。ResNet則使用4個由殘差塊組成的模塊,每個模塊使用若干個同樣輸出通道數的殘差塊。第一個模塊的通道數同輸入通道數一致。由於之前已經使用了步幅為2的最大池化層,所以無須減小高和寬。之後的每個模塊在第一個殘差塊裡將上一個模塊的通道數翻倍,並將高和寬減半。

小結:

Pytorch構建模型
import torchtorch.manual_seed(0)torch.backends.cudnn.deterministic= Falsetorch.backends.cudnn.benchmark = Trueimport torchvision.models as modelsimport torchvision.transforms as transformsimport torchvision.datasets as datasetsimport torch.nn as nnimport torch.nn.functional as Fimport torch.optim as optimfrom torch.autograd import Variablefrom torch.utils.data.dataset import Dataset

1. pytorch常用網絡1.1 Linear介紹 [全連接層]
nn.Linear(input_feature,out_feature,bias=True)

1.2 卷積介紹 [2D卷積層]
nn.Conv2d(in_channels,out_channels,kernel_size,stride=1,padding=0,dilation=1,groups,bias=True,padding_mode='zeros')
##kernel_size,stride,padding 都可以是元組## dilation 為在卷積核中插入的數量

1.3 轉置卷積介紹 [2D反卷積層]
nn.ConvTranspose2d(in_channels,out_channels,kernel_size,stride=1,padding=0,out_padding=0,groups=1,bias=True,dilation=1,padding_mode='zeros')
##padding是輸入填充,out_padding填充到輸出

1.4 最大值池化層 [2D池化層]
nn.MaxPool2d(kernel_size,stride=None,padding=0,dilation=1)

1.5 批量歸一化層 [2D歸一化層]
nn.BatchNorm2d(num_features,eps,momentum,affine=True,track_running_stats=True)
affine=True 表示批量歸一化的α,β是被學到的track_running_stats=True 表示對數據的統計特徵進行關注

2. pytorch 創建模型的四種方法

假設創建卷積層–》Relu層–》池化層–》全連接層–》Relu層–》全連接層

# 導入包import torchimport torch.nn.functional as Ffrom collections import OrderedDict

2.1.自定義型[定義在init,前向過程在forward]
class Net1(torch.nn.Module):    def __init__(self):      super(Net1, self).__init__()      self.conv1 = torch.nn.Conv2d(3, 32, 3, 1, 1)      self.dense1 = torch.nn.Linear(32 * 3 * 3, 128)      self.dense2 = torch.nn.Linear(128, 10)
def forward(self, x): x = F.max_pool2d(F.relu(self.conv(x)), 2) x = x.view(x.size(0), -1) x = F.relu(self.dense1(x)) x = self.dense2(x)    return x

2.2 序列集成型[利用nn.Squential(順序執行的層函數)]

訪問各層只能通過數字索引

class Net2(torch.nn.Module):    def __init__(self):        super(Net2, self).__init__()        self.conv = torch.nn.Sequential(        torch.nn.Conv2d(3, 32, 3, 1, 1),        torch.nn.ReLU(),        torch.nn.MaxPool2d(2))        self.dense = torch.nn.Sequential(        torch.nn.Linear(32 * 3 * 3, 128),        torch.nn.ReLU(),        torch.nn.Linear(128, 10)        )
def forward(self, x): conv_out = self.conv(x) res = conv_out.view(conv_out.size(0), -1) out = self.dense(res)        return out

2.3 序列添加型[利用Squential類add_module順序逐層添加]

給予各層的name屬性

class Net3(torch.nn.Module):    def __init__(self):        super(Net3, self).__init__()        self.conv=torch.nn.Sequential()        self.conv.add_module("conv1",torch.nn.Conv2d(3, 32, 3, 1, 1))        self.conv.add_module("relu1",torch.nn.ReLU())        self.conv.add_module("pool1",torch.nn.MaxPool2d(2))        self.dense = torch.nn.Sequential()        self.dense.add_module("dense1",torch.nn.Linear(32 * 3 * 3, 128))        self.dense.add_module("relu2",torch.nn.ReLU())        self.dense.add_module("dense2",torch.nn.Linear(128, 10))
def forward(self, x): conv_out = self.conv(x) res = conv_out.view(conv_out.size(0), -1) out = self.dense(res)        return out

2.4 序列集成字典型[OrderDict集成模型字典【『name』:層函數】]

name為key

lass Net4(torch.nn.Module):    def __init__(self):        super(Net4, self).__init__()        self.conv = torch.nn.Sequential(        OrderedDict(        [        ("conv1", torch.nn.Conv2d(3, 32, 3, 1, 1)),        ("relu1", torch.nn.ReLU()),        ("pool", torch.nn.MaxPool2d(2))        ]        ))
self.dense = torch.nn.Sequential( OrderedDict([ ("dense1", torch.nn.Linear(32 * 3 * 3, 128)), ("relu2", torch.nn.ReLU()), ("dense2", torch.nn.Linear(128, 10)) ]) )
def forward(self, x): conv_out = self.conv1(x) res = conv_out.view(conv_out.size(0), -1) out = self.dense(res)        return out

3. pytorch 對模型參數的訪問,初始化,共享3.1 訪問參數

訪問層

訪問參數【權重參數名:層名_weight/bias】

layer.params----訪問該層參數字典;

layer.weight , layer.bias訪問該層權重和偏置;

layer.weight.data()/grad() -訪問該層權重的具體數值/梯度【bias也使用】;

net.collect_params() ----返回該網絡的所有參數,返回一個由參數名稱到實例的字典。

3.2 初始化[若非首次初始化,force_reinit=True]

常規初始化【網絡初始化】

net.initialize(init=init.Normal(sigma=0.1),force_reinit=True)

net.initialize(init=init.Constant(1))

特定參數初始化

(某參數).initialize(init=init.Xavier(),force_reinit=True)

自定義初始化

繼承init的Initialize類,並實現函數_init_weight(self,name,data)

def _init_weight(self, name, data):    print('Init', name, data.shape)    data[:] = nd.random.uniform(low=-10, high=10, shape=data.shape)    # 表示一半機率為0,一半機率為[-10,-5]U[5,10]的均勻分布    data *= data.abs() >= 5# 調用自定義初始化函數1net.initialize(MyInit(), force_reinit=True)

3.3 參數共享

net = nn.Sequential()shared = nn.Dense(8, activation='relu')net.add(nn.Dense(8, activation='relu'),        shared,        nn.Dense(8, activation='relu', params=shared.params),        nn.Dense(10))net.initialize()
X = nd.random.uniform(shape=(2, 20))net(X)
net[1].weight.data()[0] == net[2].weight.data()[0]

pytorch在SVHN網絡構建實戰

構建網絡模型:繼承nn.Module函數的__init__ 函數,重定義前向傳播函數forward

構造優化器

構造損失函數

訓練 確定幾個epoch【若運用數據增廣,隨機增廣epoch次達到多樣性】

對每個batch損失函數後向傳播,優化器更新參數

   optimizer.zero_grad() 清空梯度

   loss.backward()

   optimizer.step()

4.1 普通自建網絡
class SVHN_model(nn.Module):  def __init__(self):    super(SVHN_model,self).__init__()    self.cnn = nn.Squential(          nn.Conv2d(3,16,kernel_size=(3,3),stride=(2,2)),   #3X64X128--> 16X31X63          nn.Relu(),          nn.MaxPool2d(2), #16X31X63--> 16X15X31          nn.Conv2d(16,32,kernel_size=(3,3),stride=(2,2)),#16X15X31--> 32X7X15          nn.Relu(),          nn.MaxPool2d(2) #32X7X15--> 32X3X7    )    # 並行五次字符預測    self.fc1 = nn.Linear(32*3*7,11)    self.fc2 = nn.Linear(32*3*7,11)    self.fc3 = nn.Linear(32*3*7,11)    self.fc4 = nn.Linear(32*3*7,11)    self.fc5 = nn.Linear(32*3*7,11)
def forward(self,x): cnn_result = self.cnn(x) cnn_result = cnn_result.view(cnn_result.shape[0],-1) f1 = fc1(cnn_result) f2 = fc2(cnn_result) f3 = fc3(cnn_result) f4 = fc4(cnn_result) f5 = fc5(cnn_result)    return f1,f2,f3,f4,f5

4.2 利用resnet預訓練模型
class SVHN_resnet_Model(nn.Module):  def __init__(self):    super(SVHN_resnet_Model,self).__init__()    resnet_conv = models.resnet18(pretrain=True)    resnet_conv.avgpool = nn.AdaptiveAvgPool2d(1)    resnet_conv = nn.Sequential(*list(resnet_conv.children()[:-1]))    self.cnn = model_conv    self.fc1 = nn.Linear(512,11)    self.fc2 = nn.Linear(512,11)    self.fc3 = nn.Linear(512,11)    self.fc4 = nn.Linear(512,11)    self.fc5 = nn.Linear(512,11)
def forward(self): cnn_result = cnn(x) cnn_result.view(cnn_result.shape[0],-1) f1 = fc1(cnn_result) f2 = fc2(cnn_result) f3 = fc3(cnn_result) f4 = fc4(cnn_result) f5 = fc5(cnn_result)    return f1,f2,f3,f4,f5

往期精彩:

數學推導+純Python實現機器學習算法18:LightGBM

數學推導+純Python實現機器學習算法27:LDA線性判別分析

一個算法工程師的成長之路

長按二維碼.關注機器學習實驗室

相關焦點

  • CNN 原理與實踐指南
    本文對CNN的基礎原理及常見的CNN網絡進行了詳細解讀,並介紹了Pytorch構建深度網絡的流程。最後,以阿里天池零基礎入門CV賽事為學習實踐,對Pytorch構建CNN模型進行實現。數據及背景  https://tianchi.aliyun.com/competition/entrance/531795/introduction(阿里天池 - 零基礎入門CV賽事)CNN原理CNN,又稱卷積神經網絡,是深度學習中重要的一個分支。CNN在很多領域都表現優異,精度和速度比傳統計算學習算法高很多。
  • Matlab編程之——卷積神經網絡CNN代碼解析
    五、cnnapplygrads.m.六、cnntest.m. 一、Test_example_CNN:1設置CNN的基本參數規格,如卷積、降採樣層的數量,卷積核的大小、降採樣的降幅2 cnnsetup函數 初始化卷積核、偏置等3 cnntrain函數 訓練cnn,把訓練數據分成batch,然後調用3.1  cnnff 完成訓練的前向過程,3.2  cnnbp計算並傳遞神經網絡的
  • 基礎級tf2.0+cnn 中文文本分類實踐練習
    1 前言今天講述基礎級別的中文文本分類實踐練習。數據集是復旦大學開源的文本數據集,label種類為20,該數據集有點久遠,感興趣可網上搜到。
  • 【源頭活水】Sparse R-CNN:簡化版fast rcnn
    算法,是faster rcnn算法的前身,由於其巨大計算量以及無法端到端訓練,故而提出區域提取網絡RPN加上fast rcnn的faster rcnn算法。但是你是否想過去掉RPN,僅僅在fast rcnn算法基礎上額外引入點新技術就可以實現更簡潔、更高精度的替代算法?本文借鑑了最新提出的detr算法核心思想,從而實現了上述想法。Sparse R-CNN極其簡單,不需要設置煩人的密集anchor,不需要RPN、不需要複雜後處理和nms,不需要小心的平衡RPN和fast rcnn訓練過程,也沒有難調的超參,和detr一樣完美。
  • 「68本」電氣自動化控制相關-技能提高書,原理+實踐
    【68本】電氣自動化控制相關資料書原理+實踐下載方式見文末[王春俠 主編]自動控制原理 [王建輝,顧樹生 主編]自動控制原理 [王勉華 主編]自動控制原理全程輔導 (第四版)自動控制原理上 [謝昭莉 主編]自動控制原理少學時 [文友先 主編]自動控制原理實驗教程 [丁紅,賈玉瑛 主編]自動控制原理實驗與實踐 [王素青 主編]自動控制原理實驗與實踐篇
  • cnn.com網站被封
    cnn.com網站被封 美亞 00年10月19日 【原創】 作者: 中關村在線     CNN(美國有線電視新聞網)是全球最大也是最盈利的新聞機構之一,在全球有非常高的知名度
  • 免抽氣馬德堡半球演示器——《創思實踐活動指南》案例解讀
    通過獨樹一幟的視角,路徑,詳細地描述了整個創新研究過程中的每個步驟,特別是融入各章節中的任務驅動教學,將教學從理論層面引導向親身實踐。該書是創思實踐(或研究性學習)活動開展具有「啟蒙意義」的行動指南。《創思實踐活動指南》是福建省教育廳立項課題《基於科學素養培養的創思教育實踐研究》(項目編號:JZ170467)研究成果、福建省高中綜合實踐活動學科張群林名師工作室研究成果、三明是高中綜合實踐活動學科林勝貴名師工作室研究成果。2019年1月獲評「福建省中小學精品校本課程」。
  • tf2+cnn+中文文本分類優化系列(2)
    1 前言接著上次的tf2+cnn+中文文本分類優化系列(1),本次進行優化:使用多個卷積核進行特徵抽取。
  • 「遠程醫療實踐規範與指南」內容簡介
    第五部分家庭遠程醫療臨床實踐指南該實踐指南是ATA綜合了遠程技術應用於家庭醫療和保健的各種服務規範以及普適性要求,包括指導遠程家庭醫療的具體活動,以及進一步拓展未來遠程家庭醫療服務的相關內容等。第十一部分皮膚疾病實時性和儲存信息遠程會診及轉診實踐指南該指南提供了指導皮膚疾病遠程會診和進一步轉診交流的技術規範,包括臨床實踐流程、所需設備要求,以及實時性和儲存信息遠程交流的最佳實踐建議。
  • 深度學習如何做文本分類——TextCNN原理詳解及代碼實踐(附數據集&Github)
    原作者準備寫一個系列,每周更新一篇,現在更新了兩篇,後續還有幾篇更新,對TextCNN文本分類和自然語言處理感興趣的可以後續關注公眾號ModifyAI正文:最近一直在研究TextCNN算法,準備寫一個系列,每周更新一篇,大致包括以下內容:    今天主要講TextCNN的基本原理和優劣勢,包括網絡結構、如何更新參數以及應用場景等。
  • 【深度學習】textCNN論文與原理——短文本分類(基於pytorch)
    前言前文已經介紹了TextCNN的基本原理,如果還不熟悉的建議看看原理:【深度學習】textCNN論文與原理[1]及一個簡單的基於pytorch的圖像分類案例:【深度學習】卷積神經網絡-圖片分類案例(pytorch實現)[2]。
  • CNN卷積神經網絡實例(基於pytorch)
    2.1 代碼示例# @Time : 2020/6/6 13:23 # @Author : kingback# @File : cnn_test.py # @Software: PyCharm=CNN()# print(cnn)# 添加優化方法optimizer=torch.optim.Adam(cnn.parameters(),lr=LR)# 指定損失函數使用交叉信息熵loss_fn=nn.CrossEntropyLoss()'''開始訓練我們的模型哦'''step=0for epoch in
  • 深度學習目標檢測系列:faster RCNN實現|附python源碼
    在掌握基本原理後,下面進入實戰部分。本文將使用一個非常酷且有用的數據集來實現faster R-CNN,這些數據集具有潛在的真實應用場景。問題陳述數據來源於醫療相關數據集,目的是解決血細胞檢測問題。任務是通過顯微圖像讀數來檢測每張圖像中的所有紅細胞(RBC)、白細胞(WBC)以及血小板。
  • 新書速遞:《新高考英語概要寫作實踐指南 提升版》
    使用說明:‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍新高考英語概要寫作實踐指南 提升版‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍讀後續寫和概要寫作是浙江省新高考書面表達的兩種新題型,綜合考查學生的語篇知識
  • CNN中的maxpool到底是什麼原理?
    筆者在 flask-keras-cnn-image-retrieval中採用的正是 MAX pooling 的方式。 MOP pooling 的基本思想是多尺度與 VLAD(VLAD 原理可以參考筆者之前寫的博文圖像檢索:BoF、VLAD、FV 三劍客),其具體的 pooling 步驟如下:
  • 教程 | 基於Matlab的卷積神經網絡(CNN)
    rand('state',0) %指定狀態使每次運行產生的隨機結果相同cnn.layers = {    struct('type', 'i') % 輸入層    struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) % 卷積層    struct('type', 's', 'scale',
  • 論德性倫理學的實踐原理的兩個基本含義
    實踐原理是一種內在觀點的德性倫理學的最基本的原理。它的第一個含義是,生活可以是實踐的,表明生活的實踐的可能性。實踐原理的第二個含義是,生活實踐可以是德性的,表明德性地生活的可能性。一個人如果沒有在他的生活中發展第一種可能性,就會受到人們指責。但是,當他通過生活充分展示出第二種可能性,他才受到稱讚。倫理學可以或明確或隱含地以生活的實踐的可能性和德性地生活的可能性作為它的基礎。
  • 機器學習實踐指南
    ◈ Edx 上關於 Python 或者 R 的介紹性課程: Python 語言數據科學介紹[12] 和 R 語言數據科學介紹[13]。◈ 還有很多其他免費的課程。查看 Coursera[14] 或者 Codeacademy[15] 了解更多。當你打牢基礎知識後,請查看 DataCamp 上的博客 Python 統計學:40+ 數據科學資源[16]。
  • 李季湄:理論與實踐有多遠——淺析《指南》實踐理解的誤區
    》(以下簡稱《指南》)研製組核心成員,李季湄老師總結了貫徹「指南」以來各地幼教工作者在實踐中出現的問題並予以分析和解答。就拿語言活動來說,符合《指南》精神的語言教學活動,應該是在一日生活中,在遊戲,在對話中,在老師與孩子互動中的方方面面來進行,而不是僅僅以一個語言集體教學活動來做語言教學。教師從理念到行為的轉變需要時間,需要反反覆覆的學習與感悟,在實踐情景中行動,反思,再行動,再反思。這樣不斷深入地推進指南的實施。否則,非常容易出現穿新鞋走老路的現象。
  • 康德《實踐理性批判》——內容分析第一篇/實踐理性諸原理
    所以在《實踐理性批判》中的第一大部分要素論(第一部分)的分析論(第一卷)中,就跟《純粹理性批判》的要素論是正好相反,先從原理入手(第一章),再到概念(第二章),然後進入經驗(第三章)。 下面我們會分兩次來去了解純粹實踐理性的諸原理。這一次內容主要是原理的提出,下一次將會是原理的演繹。