PyTorch的nn.Linear()詳解
PyTorch的nn.Linear()是用于設(shè)置網(wǎng)絡(luò)中的全連接層的,需要注意的是全連接層的輸入與輸出都是二維張量,一般形狀為[batch_size, size],不同于卷積層要求輸入輸出是四維張量。其用法與形參說明如下:

in_features指的是輸入的二維張量的大小,即輸入的[batch_size, size]中的size。
??out_features指的是輸出的二維張量的大小,即輸出的二維張量的形狀為[batch_size,output_size],當(dāng)然,它也代表了該全連接層的神經(jīng)元個數(shù)。
??從輸入輸出的張量的shape角度來理解,相當(dāng)于一個輸入為[batch_size, in_features]的張量變換成了[batch_size, out_features]的輸出張量。
用法示例:


pytorch——nn.BatchNorm1d()
Batch Normalization原理:
? ? ? ? 其主要描述的是:訓(xùn)練深度網(wǎng)絡(luò)的時候經(jīng)常發(fā)生訓(xùn)練困難的問題,因為,每一次參數(shù)迭代更新后,上一層網(wǎng)絡(luò)的輸出數(shù)據(jù)經(jīng)過這一層網(wǎng)絡(luò)計算后,數(shù)據(jù)的分布會發(fā)生變化,為下一層網(wǎng)絡(luò)的學(xué)習(xí)帶來困難(神經(jīng)網(wǎng)絡(luò)本來就是要學(xué)習(xí)數(shù)據(jù)的分布,要是分布一直在變,學(xué)習(xí)就很難了),此現(xiàn)象稱之為InternalInternal Covariate Shift。
? ? ?? Internal Covariate Shift 和Covariate Shift具有相似性,但并不是一個東西,前者發(fā)生在神經(jīng)網(wǎng)絡(luò)的內(nèi)部,所以是InternalInternal,后者發(fā)生在輸入數(shù)據(jù)上。Covariate Shift主要描述的是由于訓(xùn)練數(shù)據(jù)和測試數(shù)據(jù)存在分布的差異性,給網(wǎng)絡(luò)的泛化性和訓(xùn)練速度帶來了影響,我們經(jīng)常使用的方法是做歸一化或者白化。
? ? ? 機器學(xué)習(xí)領(lǐng)域有個很重要的假設(shè):IID獨立同分布假設(shè),就是假設(shè)訓(xùn)練數(shù)據(jù)和測試數(shù)據(jù)是滿足相同分布的,這是通過訓(xùn)練數(shù)據(jù)獲得的模型能夠在測試集獲得好的效果的一個基本保障。
? ??BatchNorm就是在深度神經(jīng)網(wǎng)絡(luò)訓(xùn)練過程中使得每一層神經(jīng)網(wǎng)絡(luò)的輸入保持相同分布的。
原理:
? ? ? ? Internal Covariate Shift除了增加模型學(xué)習(xí)的難度之外,還會導(dǎo)致梯度消失的問題。深層神經(jīng)網(wǎng)絡(luò)在做非線性變換前的激活輸入值(就是那個x=WU+B,U是輸入)隨著網(wǎng)絡(luò)深度加深或者在訓(xùn)練過程中,其分布逐漸發(fā)生偏移或者變動,之所以訓(xùn)練收斂慢,一般是整體分布逐漸往非線性函數(shù)的取值區(qū)間的上下限兩端靠近(對于Sigmoid函數(shù)來說,意味著激活輸入值WU+B是大的負值或正值),所以這導(dǎo)致反向傳播時低層神經(jīng)網(wǎng)絡(luò)的梯度消失,這是訓(xùn)練深層神經(jīng)網(wǎng)絡(luò)收斂越來越慢的本質(zhì)原因。
? ? ? ? 就是說Internal Covariate Shift 主要導(dǎo)致兩個問題:1.中間層輸入分布總是變化,增加了模型擬合的難度。2.中間層輸入分布會使輸出逐漸靠近激活函數(shù)梯度較小的地方,導(dǎo)致梯度消失。
? ? ? ? 所以解決Internal Covariate Shift 就可以提升模型的性能,BatchNorm就是通過一定的規(guī)范化手段,把每層神經(jīng)網(wǎng)絡(luò)任意神經(jīng)元這個輸入值的分布強行拉回到正態(tài)分布。這樣使得激活輸入值落在非線性函數(shù)對輸入比較敏感的區(qū)域,這樣輸入的小變化就會導(dǎo)致?lián)p失函數(shù)較大的變化,意思是這樣讓梯度變大,避免梯度消失問題產(chǎn)生,而且梯度變大意味著學(xué)習(xí)收斂速度快,能大大加快訓(xùn)練速度。
對于每個隱層神經(jīng)元,把逐漸向非線性函數(shù)映射后向取值區(qū)間極限飽和區(qū)靠攏的輸入分布強制拉回到比較標(biāo)準(zhǔn)的正態(tài)分布,使得非線性變換函數(shù)的輸入值落入對輸入比較敏感的區(qū)域,以此避免梯度消失問題。因為梯度一直都能保持比較大的狀態(tài),所以很明顯對神經(jīng)網(wǎng)絡(luò)的參數(shù)調(diào)整效率比較高,就是變動大,就是說向損失函數(shù)最優(yōu)值邁動的步子大,也就是說收斂地快
實現(xiàn):
為了減小Internal Covariate Shift,對神經(jīng)網(wǎng)絡(luò)的每一層做歸一化不就可以了,假設(shè)將每一層輸出后的數(shù)據(jù)都歸一化到0均值,1方差,滿足正態(tài)分布。但是,此時有一個問題,每一層的數(shù)據(jù)分布都是標(biāo)準(zhǔn)正太分布,導(dǎo)致其完全學(xué)習(xí)不到輸入數(shù)據(jù)的特征,因為,費勁心思學(xué)習(xí)到的特征分布被歸一化了,因此,直接對每一層做歸一化顯然是不合理的。
但是如果稍作修改,加入可訓(xùn)練的參數(shù)做歸一化,那就是Batch Norm實現(xiàn)的。


代碼:

首先計算均值和方差,然后歸一化,然后縮放和平移,完事!但是這是在訓(xùn)練中完成的任務(wù),每次訓(xùn)練給一個批量,然后計算批量的均值方差,但是在測試的時候可不是這樣,測試的時候每次只輸入一個樣本,這怎么計算批量的均值和方差,于是,就有了代碼中下面兩行,在訓(xùn)練的時候?qū)崿F(xiàn)計算好mean var測試的時候直接拿來用就可以了,不用計算均值和方差。

應(yīng)用:
?根據(jù)前面的理論,Batch Norm主要是為了輸入在激活函數(shù)的敏感區(qū)。所以BatchNorm層要加在激活函數(shù)前面。



nn.BatchNorm1d(dim),dim等于前一層輸出的維度。BatchNorm層輸出的維度也是dim。
優(yōu)點:
①不僅僅極大提升了訓(xùn)練速度,收斂過程大大加快;
②還能增加分類效果,一種解釋是這是類似于Dropout的一種防止過擬合的正則化表達方式,所以不用Dropout也能達到相當(dāng)?shù)男Ч?/p>
③另外調(diào)參過程也簡單多了,對于初始化要求沒那么高,而且可以使用大的學(xué)習(xí)率等。
其他:https://www.itsiwei.com/22671.html
有種說法,BatchNorm起作用和Internal Covariate Shift沒啥關(guān)系。

BatchNorm對訓(xùn)練過程有著更根本的影響:它能使優(yōu)化問題的解空間更加平滑,而這種平滑性確保了梯度更具預(yù)測性和穩(wěn)定性,因此可以使用更大范圍的學(xué)習(xí)速率并獲得更快的網(wǎng)絡(luò)收斂。
nn.Sequential()
一、關(guān)于Sequential類的簡介
先來看一下它的定義吧,在之前,我們首先需要明確一個特別重要的觀念,那就是——torch的核心是Module類,
Module類在下面這個模塊中:
D:\ProgramData\Anaconda3\envs\pytorch1.1.0\Lib\site-packages\torch\nn\modules\module.py
Sequential繼承自Module,在下面這個模塊里面:
D:\ProgramData\Anaconda3\envs\pytorch1.1.0\Lib\site-packages\torch\nn\modules\container.py
這樣看起來,Sequential似乎是一個容器,的確,他確確實實是可以作為一個容器包裝幾個層,這里簡單看一下它的定義:

這里還看一下這個所謂的container.py里面還有哪些“容器”存在

二、Sequential類不同的實現(xiàn)(3種實現(xiàn))
2.1?最簡單的序貫?zāi)P?/p>

注意:這樣做有一個問題,每一個層是沒有名稱,默認(rèn)的是以0、1、2、3來命名,從上面的運行結(jié)果也可以看出。
2.2 給每一個層添加名稱

注意:從上面的結(jié)果中可以看出,這個時候每一個層都有了自己的名稱,但是此時需要注意,我并不能夠通過名稱直接獲取層,依然只能通過索引index,即
model[2] 是正確的
model["conv2"] 是錯誤的
這其實是由它的定義實現(xiàn)的,看上面的Sequenrial定義可知,只支持index訪問。
2.3 Sequential的第三種實現(xiàn)

Sequential里面并沒有定義?add_module()方法啊,實際上,這個方法是定義在它的父類Module里面的,Sequential繼承了而已,它的定義如下

總結(jié):上面的3種定義順序模型的方法是較為常見的,但是我們說了Sequential除了本身可以用來定義模型之外,它還可以包裝層,把幾個層包裝起來像一個塊一樣