⑴ sc-RNA-seq | dropout 的由來以及處理辦法
cell-gene矩陣中的零 可能真的是未表達的也可能是由於一些原因未檢測到 ,就是零有兩種可能,而不同的解釋對結果是有影響的。
一般的處理思路有倆:
提出問題的人在某種程度上有責任提出解決辦法,或者建議。所以開發了R包,由於只能做聚類就顯得有些小眾了。
用於單細胞RNA-seq(scRNA-seq)數據的大多數現有降維和聚類包通過heavy modeling和computational machinery 來處理dropouts.
CIDR,一種隱式的插補方法(imputation),減輕scRNA-seq數據中dropout的影響。
CIDR改進了標准主成分分析,並且在聚類精度方面優於最先進的方法,即t-SNE,ZIFA和RaceID。
CIDR通常在幾秒鍾內完成處理數百個cell的數據集,幾分鍾內完成處理數千個cell的數據集。
Missing data and technical variability in single-cell RNA-sequencing experiments
github|CIDR
CIDR: Ultrafast and accurate clustering through imputation for single-cell RNA-seq data
⑵ BN和Dropout在訓練和測試時的差別
From: https://zhuanlan.hu.com/p/61725100
BN,Batch Normalization,就是在深度神經網路訓練過程中使得每一層神經網路的輸入保持相近的分布。
BN訓練和測試時的參數是一樣的嘛?
對於BN,在訓練時,是對每一批的訓練數據進行歸一化,也即用每一批數據的均值和方差。
而在測試時,比如進行一個樣本的預測,就並沒有batch的概念,因此,這個時候用的均值和方差是全量訓練數據的均值和方差,這個可以通過移動平均法求得。
對於BN,當一個模型訓練完成之後,它的所有參數都確定了,包括均值和方差,gamma和bata。
BN訓練時為什麼不用全量訓練集的均值和方差呢?
因為在訓練的第一個完整epoch過程中是無法得到輸入層之外其他層全量訓練集的均值和方差,只能在前向傳播過程中獲取已訓練batch的均值和方差。那在一個完整epoch之後可以使用全量數據集的均值和方差嘛?
對於BN,是對每一批數據進行歸一化到一個相同的分布,而每一批數據的均值和方差會有一定的差別,而不是用固定的值,這個差別實際上也能夠增加模型的魯棒性,也會在一定程度上減少過擬合。
但是一批數據和全量數據的均值和方差相差太多,又無法較好地代表訓練集的分布,因此,BN一般要求將訓練集完全打亂,並用一個較大的batch值,去縮小與全量數據的差別。
Dropout 是在訓練過程中以一定的概率的使神經元失活,即輸出為0,以提高模型的泛化能力,減少過擬合。
Dropout 在訓練和測試時都需要嘛?
Dropout 在訓練時採用,是為了減少神經元對部分上層神經元的依賴,類似將多個不同網路結構的模型集成起來,減少過擬合的風險。
而在測試時,應該用整個訓練好的模型,因此不需要dropout。
Dropout 如何平衡訓練和測試時的差異呢?
Dropout ,在訓練時以一定的概率使神經元失活,實際上就是讓對應神經元的輸出為0
假設失活概率為 p ,就是這一層中的每個神經元都有p的概率失活,如下圖的三層網路結構中,如果失活概率為0.5,則平均每一次訓練有3個神經元失活,所以輸出層每個神經元只有3個輸入,而實際測試時是不會有dropout的,輸出層每個神經元都有6個輸入,這樣在訓練和測試時,輸出層每個神經元的輸入和的期望會有量級上的差異。
因此在訓練時還要對第二層的輸出數據除以(1-p)之後再傳給輸出層神經元,作為神經元失活的補償,以使得在訓練時和測試時每一層輸入有大致相同的期望。
dropout部分參考: https://blog.csdn.net/program_developer/article/details/80737724
BN和Dropout單獨使用都能減少過擬合並加速訓練速度,但如果一起使用的話並不會產生1+1>2的效果,相反可能會得到比單獨使用更差的效果。
相關的研究參考論文: Understanding the Disharmony between Dropout and Batch Normalization by Variance Shift
本論文作者發現理解 Dropout 與 BN 之間沖突的關鍵是網路狀態切換過程中存在神經方差的(neural variance)不一致行為。試想若有圖一中的神經響應 X,當網路從訓練轉為測試時,Dropout 可以通過其隨機失活保留率(即 p)來縮放響應,並在學習中改變神經元的方差,而 BN 仍然維持 X 的統計滑動方差。這種方差不匹配可能導致數值不穩定(見下圖中的紅色曲線)。而隨著網路越來越深,最終預測的數值偏差可能會累計,從而降低系統的性能。簡單起見,作者們將這一現象命名為「方差偏移」。事實上,如果沒有 Dropout,那麼實際前饋中的神經元方差將與 BN 所累計的滑動方差非常接近(見下圖中的藍色曲線),這也保證了其較高的測試准確率。
作者採用了兩種策略來探索如何打破這種局限。一個是在所有 BN 層後使用 Dropout,另一個就是修改 Dropout 的公式讓它對方差並不那麼敏感,就是高斯Dropout。
第一個方案比較簡單,把Dropout放在所有BN層的後面就可以了,這樣就不會產生方差偏移的問題,但實則有逃避問題的感覺。
第二個方案來自Dropout原文里提到的一種高斯Dropout,是對Dropout形式的一種拓展。作者進一步拓展了高斯Dropout,提出了一個均勻分布Dropout,這樣做帶來了一個好處就是這個形式的Dropout(又稱為「Uout」)對方差的偏移的敏感度降低了,總得來說就是整體方差偏地沒有那麼厲害了。
⑶ 談談Tensorflow的dropout
Dropout這個概念已經推出4年了,它的詳細描述見 論文 。可是呢,它彷彿是個猶抱琵琶半遮面的美女,難以捉摸!!許多文獻都對dropout有過描述,但解釋的含糊不清,這里呢,我也不打算解釋清楚,只是通過tensorflow來看一看dropout的運行機理。
文章分兩部分,第一部分介紹tensorflow中的dropout函數,第二部分是我的思考
首先看官方函數定義:
輸入是:
輸出是:
然後我們看看官方API是怎麼說這個函數的:
注意,輸出的非0元素是原來的 「1/keep_prob」 倍!說了這么多,下面給一個程序例子:
運行的結果如下:
分析一下運行結果:
特點分析完畢,小總結一下,dropout這個概念看起來好高大上,然而在程序中實現竟然如此簡單!說白了,tensorflow中的dropout就是: 使輸入tensor中某些元素變為0,其它沒變0的元素變為原來的1/keep_prob大小 !
首先引用此篇 博文 的話:
然後,我就自己試了試,看看小型網路中dropout效果到底怎麼樣,程序片段如下:
網路很簡單,形如 784-30-10 的一個網路,只不過在輸出層前用dropout處理了一下,訓練的數據是MNIST的手寫數據集,然後你猜怎麼著?採用dropout以後的訓練精度 不升反降 ,後來我把網路隱藏層改成100個神經元,結果依舊,看來,我的網路還是太小了,真的如上面那篇博客所說,dropout用不好的話,真是個累贅!
⑷ 如何理解dropout
開篇明義,dropout是指在深度學習網路的訓練過程中,對於神經網路單元,按照一定的概率將其暫時從網路中丟棄。注意是暫時,對於隨機梯度下降來說,由於是隨機丟棄,故而每一個mini-batch都在訓練不同的網路。
dropout是CNN中防止過擬合提高效果的一個大殺器,但對於其為何有效,卻眾說紛紜。在下讀到兩篇代表性的論文,代表兩種不同的觀點,特此分享給大家。
組合派
參考文獻中第一篇中的觀點,Hinton老大爺提出來的,關於Hinton在深度學習界的地位我就不再贅述了,光是這地位,估計這一派的觀點就是「武當少林」了。注意,派名是我自己起的,各位勿笑。
觀點
該論文從神經網路的難題出發,一步一步引出dropout為何有效的解釋。大規模的神經網路有兩個缺點:
費時
容易過擬合
這兩個缺點真是抱在深度學習大腿上的兩個大包袱,一左一右,相得益彰,額不,臭氣相投。過擬合是很多機器學習的通病,過擬合了,得到的模型基本就廢了。而為了解決過擬合問題,一般會採用ensemble方法,即訓練多個模型做組合,此時,費時就成為一個大問題,不僅訓練起來費時,測試起來多個模型也很費時。總之,幾乎形成了一個死鎖。
Dropout的出現很好的可以解決這個問題,每次做完dropout,相當於從原始的網路中找到一個更瘦的網路,如下圖所示:
因而,對於一個有N個節點的神經網路,有了dropout後,就可以看做是2n個模型的集合了,但此時要訓練的參數數目卻是不變的,這就解脫了費時的問題。
動機論
⑸ ReLU和Dropout
從解決最小的問題開始。
ReLU家族的激活函數通常是神經網路中激活函數的首選項,其優點在於:
Dropout是一種有效的防止過擬合的方法,該方法的實質是在一次前向傳播過程中,隨機地丟棄(使失活)網路中的某些神經元。所謂的丟棄神經元,其實是在數據流過每個神經元時,都額外的乘上一個概率p,p的值為0時,當前神經元即被丟棄。隨機丟棄神經元的意義在於 使網路不依賴與某一個神經元或某一種神經元組合 ,因為每次隨機丟棄都會使網路產生新的結構。
Dropout通常用於神經網路的全連接層,因為在卷積層、池化層等部分網路已經是稀疏的,並且具有完備的理論解釋(權重共享、感受野等),而全連接層是稠密的,使用Dropout減少參數量能有效地改變其泛化能力。下面是使用tensorflow(v1)的一個簡單示例:
⑹ 卷積神經網路
關於花書中卷積網路的筆記記錄於 https://www.jianshu.com/p/5a3c90ea0807 。
卷積神經網路(Convolutional Neural Network,CNN或ConvNet)是一種具有 局部連接、權重共享 等特性的深層前饋神經網路。卷積神經網路是受生物學上感受野的機制而提出。 感受野(Receptive Field) 主要是指聽覺、視覺等神經系統中一些神經元的特性,即 神經元只接受其所支配的刺激區域內的信號 。
卷積神經網路最早是主要用來處理圖像信息。如果用全連接前饋網路來處理圖像時,會存在以下兩個問題:
目前的卷積神經網路一般是由卷積層、匯聚層和全連接層交叉堆疊而成的前饋神經網路,使用反向傳播演算法進行訓練。 卷積神經網路有三個結構上的特性:局部連接,權重共享以及匯聚 。這些特性使卷積神經網路具有一定程度上的平移、縮放和旋轉不變性。
卷積(Convolution)是分析數學中一種重要的運算。在信號處理或圖像處理中,經常使用一維或二維卷積。
一維卷積經常用在信號處理中,用於計算信號的延遲累積。假設一個信號發生器每個時刻t 產生一個信號 ,其信息的衰減率為 ,即在 個時間步長後,信息為原來的 倍。假設 ,那麼在時刻t收到的信號 為當前時刻產生的信息和以前時刻延遲信息的疊加:
我們把 稱為 濾波器(Filter)或卷積核(Convolution Kernel) 。假設濾波器長度為 ,它和一個信號序列 的卷積為:
信號序列 和濾波器 的卷積定義為:
一般情況下濾波器的長度 遠小於信號序列長度 ,下圖給出一個一維卷積示例,濾波器為 :
二維卷積經常用在圖像處理中。因為圖像為一個兩維結構,所以需要將一維卷積進行擴展。給定一個圖像 和濾波器 ,其卷積為:
下圖給出一個二維卷積示例:
注意這里的卷積運算並不是在圖像中框定卷積核大小的方框並將各像素值與卷積核各個元素相乘並加和,而是先把卷積核旋轉180度,再做上述運算。
在圖像處理中,卷積經常作為特徵提取的有效方法。一幅圖像在經過卷積操作後得到結果稱為 特徵映射(Feature Map) 。
最上面的濾波器是常用的高斯濾波器,可以用來對圖像進行 平滑去噪 ;中間和最下面的過濾器可以用來 提取邊緣特徵 。
在機器學習和圖像處理領域,卷積的主要功能是在一個圖像(或某種特徵)上滑動一個卷積核(即濾波器),通過卷積操作得到一組新的特徵。在計算卷積的過程中,需要進行卷積核翻轉(即上文提到的旋轉180度)。 在具體實現上,一般會以互相關操作來代替卷積,從而會減少一些不必要的操作或開銷。
互相關(Cross-Correlation)是一個衡量兩個序列相關性的函數,通常是用滑動窗口的點積計算來實現 。給定一個圖像 和卷積核 ,它們的互相關為:
互相關和卷積的區別僅在於卷積核是否進行翻轉。因此互相關也可以稱為不翻轉卷積 。當卷積核是可學習的參數時,卷積和互相關是等價的。因此,為了實現上(或描述上)的方便起見,我們用互相關來代替卷積。事實上,很多深度學習工具中卷積操作其實都是互相關操作。
在卷積的標準定義基礎上,還可以引入濾波器的 滑動步長 和 零填充 來增加卷積多樣性,更靈活地進行特徵抽取。
濾波器的步長(Stride)是指濾波器在滑動時的時間間隔。
零填充(Zero Padding)是在輸入向量兩端進行補零。
假設卷積層的輸入神經元個數為 ,卷積大小為 ,步長為 ,神經元兩端各填補 個零,那麼該卷積層的神經元數量為 。
一般常用的卷積有以下三類:
因為卷積網路的訓練也是基於反向傳播演算法,因此我們重點關注卷積的導數性質:
假設 。
, , 。函數 為一個標量函數。
則由 有:
可以看出, 關於 的偏導數為 和 的卷積 :
同理得到:
當 或 時, ,即相當於對 進行 的零填充。從而 關於 的偏導數為 和 的寬卷積 。
用互相關的「卷積」表示,即為(注意 寬卷積運算具有交換性性質 ):
在全連接前饋神經網路中,如果第 層有 個神經元,第 層有 個神經元,連接邊有 個,也就是權重矩陣有 個參數。當 和 都很大時,權重矩陣的參數非常多,訓練的效率會非常低。
如果採用卷積來代替全連接,第 層的凈輸入 為第 層活性值 和濾波器 的卷積,即:
根據卷積的定義,卷積層有兩個很重要的性質:
由於局部連接和權重共享,卷積層的參數只有一個m維的權重 和1維的偏置 ,共 個參數。參數個數和神經元的數量無關。此外,第 層的神經元個數不是任意選擇的,而是滿足 。
卷積層的作用是提取一個局部區域的特徵,不同的卷積核相當於不同的特徵提取器。
特徵映射(Feature Map)為一幅圖像(或其它特徵映射)在經過卷積提取到的特徵,每個特徵映射可以作為一類抽取的圖像特徵。 為了提高卷積網路的表示能力,可以在每一層使用多個不同的特徵映射,以更好地表示圖像的特徵。
在輸入層,特徵映射就是圖像本身。如果是灰度圖像,就是有一個特徵映射,深度 ;如果是彩色圖像,分別有RGB三個顏色通道的特徵映射,深度 。
不失一般性,假設一個卷積層的結構如下:
為了計算輸出特徵映射 ,用卷積核 分別對輸入特徵映射 進行卷積,然後將卷積結果相加,並加上一個標量偏置 得到卷積層的凈輸入 再經過非線性激活函數後得到輸出特徵映射 。
在輸入為 ,輸出為 的卷積層中,每個輸出特徵映射都需要 個濾波器以及一個偏置。假設每個濾波器的大小為 ,那麼共需要 個參數。
匯聚層(Pooling Layer)也叫子采樣層(Subsampling Layer),其作用是進行特徵選擇,降低特徵數量,並從而減少參數數量。
常用的匯聚函數有兩種:
其中 為區域 內每個神經元的激活值。
可以看出,匯聚層不但可以有效地減少神經元的數量,還可以使得網路對一些小的局部形態改變保持不變性,並擁有更大的感受野。
典型的匯聚層是將每個特徵映射劃分為 大小的不重疊區域,然後使用最大匯聚的方式進行下采樣。匯聚層也可以看做是一個特殊的卷積層,卷積核大小為 ,步長為 ,卷積核為 函數或 函數。過大的采樣區域會急劇減少神經元的數量,會造成過多的信息損失。
一個典型的卷積網路是由卷積層、匯聚層、全連接層交叉堆疊而成。
目前常用卷積網路結構如圖所示,一個卷積塊為連續 個卷積層和 個匯聚層( 通常設置為 , 為 或 )。一個卷積網路中可以堆疊 個連續的卷積塊,然後在後面接著 個全連接層( 的取值區間比較大,比如 或者更大; 一般為 )。
目前,整個網路結構 趨向於使用更小的卷積核(比如 和 )以及更深的結構(比如層數大於50) 。此外,由於卷積的操作性越來越靈活(比如不同的步長),匯聚層的作用變得也越來越小,因此目前比較流行的卷積網路中, 匯聚層的比例也逐漸降低,趨向於全卷積網路 。
在全連接前饋神經網路中,梯度主要通過每一層的誤差項 進行反向傳播,並進一步計算每層參數的梯度。在卷積神經網路中,主要有兩種不同功能的神經層:卷積層和匯聚層。而參數為卷積核以及偏置,因此 只需要計算卷積層中參數的梯度。
不失一般性,第 層為卷積層,第 層的輸入特徵映射為 ,通過卷積計算得到第 層的特徵映射凈輸入 ,第 層的第 個特徵映射凈輸入
由 得:
同理可得,損失函數關於第 層的第 個偏置 的偏導數為:
在卷積網路中,每層參數的梯度依賴其所在層的誤差項 。
卷積層和匯聚層中,誤差項的計算有所不同,因此我們分別計算其誤差項。
第 層的第 個特徵映射的誤差項 的具體推導過程如下:
其中 為第 層使用的激活函數導數, 為上采樣函數(upsampling),與匯聚層中使用的下采樣操作剛好相反。如果下采樣是最大匯聚(max pooling),誤差項 中每個值會直接傳遞到上一層對應區域中的最大值所對應的神經元,該區域中其它神經元的誤差項的都設為0。如果下采樣是平均匯聚(meanpooling),誤差項 中每個值會被平均分配到上一層對應區域中的所有神經元上。
第 層的第 個特徵映射的誤差項 的具體推導過程如下:
其中 為寬卷積。
LeNet-5雖然提出的時間比較早,但是是一個非常成功的神經網路模型。基於LeNet-5 的手寫數字識別系統在90年代被美國很多銀行使用,用來識別支票上面的手寫數字。LeNet-5 的網路結構如圖:
不計輸入層,LeNet-5共有7層,每一層的結構為:
AlexNet是第一個現代深度卷積網路模型,其首次使用了很多現代深度卷積網路的一些技術方法,比如採用了ReLU作為非線性激活函數,使用Dropout防止過擬合,使用數據增強來提高模型准確率等。AlexNet 贏得了2012 年ImageNet 圖像分類競賽的冠軍。
AlexNet的結構如圖,包括5個卷積層、3個全連接層和1個softmax層。因為網路規模超出了當時的單個GPU的內存限制,AlexNet 將網路拆為兩半,分別放在兩個GPU上,GPU間只在某些層(比如第3層)進行通訊。
AlexNet的具體結構如下:
在卷積網路中,如何設置卷積層的卷積核大小是一個十分關鍵的問題。 在Inception網路中,一個卷積層包含多個不同大小的卷積操作,稱為Inception模塊。Inception網路是由有多個inception模塊和少量的匯聚層堆疊而成 。
v1版本的Inception模塊,採用了4組平行的特徵抽取方式,分別為1×1、3× 3、5×5的卷積和3×3的最大匯聚。同時,為了提高計算效率,減少參數數量,Inception模塊在進行3×3、5×5的卷積之前、3×3的最大匯聚之後,進行一次1×1的卷積來減少特徵映射的深度。如果輸入特徵映射之間存在冗餘信息, 1×1的卷積相當於先進行一次特徵抽取 。
⑺ CNN之Lenet5
LeNet誕生於 1994 年,是最早的卷積神經網路之一,並且推動了深度學習領域的發展。
LeNet-5是Yann LeCun等人在多次研究後提出的最終卷積神經網路結構,主要用於手寫數字識別
LeNet5的網路結構如下所示:
LeNet-5包含七層,不包括輸入,每一層都包含可訓練參數(權重),當時使用的輸入數據是32*32像素的圖像。下面逐層介紹LeNet-5的結構,並且,卷積層將用Cx表示,子采樣層則被標記為Sx,全連接層被標記為Fx,其中x是層索引。
該層使用了6個卷積核,每個卷積核的大小為5×5,這樣就得到了6個feature map(特徵圖)。
每個卷積核(5×5)與原始的輸入圖像(32×32)進行卷積,這樣得到的feature map(特徵圖)大小為(32-5+1)×(32-5+1)= 28×28
卷積核與輸入圖像按卷積核大小逐個區域進行匹配計算,匹配後原始輸入圖像的尺寸將變小,因為邊緣部分卷積核無法越出界,只能匹配一次,匹配計算後的尺寸變為Cr×Cc=(Ir-Kr+1)×(Ic-Kc+1),其中Cr、Cc,Ir、Ic,Kr、Kc分別表示卷積後結果圖像、輸入圖像、卷積核的行列大小。
由於參數(權值)共享的原因,對於同個卷積核每個神經元均使用相同的參數,因此,參數個數為(5×5+1)×6= 156,其中5×5為卷積核參數,1為偏置參數
卷積後的圖像大小為28×28,因此每個特徵圖有28×28個神經元,每個卷積核參數為(5×5+1)×6,因此,該層的連接數為(5×5+1)×6×28×28=122304
這一層主要是做池化或者特徵映射(特徵降維),池化單元為2×2,因此,6個特徵圖的大小經池化後即變為14×14。池化單元之間沒有重疊,在池化區域內進行聚合統計後得到新的特徵值,因此經2×2池化後,每兩行兩列重新算出一個特徵值出來,相當於圖像大小減半,因此卷積後的28×28圖像經2×2池化後就變為14×14。
這一層的計算過程是:2×2 單元里的值相加,然後再乘以訓練參數w,再加上一個偏置參數b(每一個特徵圖共享相同的w和b),然後取sigmoid值(S函數:0-1區間),作為對應的該單元的值。卷積操作與池化的示意圖如下:
S2層由於每個特徵圖都共享相同的w和b這兩個參數,因此需要2×6=12個參數
下采樣之後的圖像大小為14×14,因此S2層的每個特徵圖有14×14個神經元,每個池化單元連接數為2×2+1(1為偏置量),因此,該層的連接數為(2×2+1)×14×14×6 = 5880
C3層有16個卷積核,卷積模板大小為5×5。
與C1層的分析類似,C3層的特徵圖大小為(14-5+1)×(14-5+1)= 10×10
需要注意的是,C3與S2並不是全連接而是部分連接,有些是C3連接到S2三層、有些四層、甚至達到6層,通過這種方式提取更多特徵,連接的規則如下表所示:
例如第一列表示C3層的第0個特徵圖(feature map)只跟S2層的第0、1和2這三個feature maps相連接,計算過程為:用3個卷積模板分別與S2層的3個feature maps進行卷積,然後將卷積的結果相加求和,再加上一個偏置,再取sigmoid得出卷積後對應的feature map了。其它列也是類似(有些是3個卷積模板,有些是4個,有些是6個)。因此,C3層的參數數目為(5×5×3+1)×6 +(5×5×4+1)×9 +5×5×6+1 = 1516
卷積後的特徵圖大小為10×10,參數數量為1516,因此連接數為1516×10×10= 151600
與S2的分析類似,池化單元大小為2×2,因此,該層與C3一樣共有16個特徵圖,每個特徵圖的大小為5×5。
與S2的計算類似,所需要參數個數為16×2 = 32
連接數為(2×2+1)×5×5×16 = 2000
該層有120個卷積核,每個卷積核的大小仍為5×5,因此有120個特徵圖。由於S4層的大小為5×5,而該層的卷積核大小也是5×5,因此特徵圖大小為(5-5+1)×(5-5+1)= 1×1。這樣該層就剛好變成了全連接,這只是巧合,如果原始輸入的圖像比較大,則該層就不是全連接了。
與前面的分析類似,本層的參數數目為120×(5×5×16+1) = 48120
由於該層的特徵圖大小剛好為1×1,因此連接數為48120×1×1=48120
F6層有84個單元,之所以選這個數字的原因是來自於輸出層的設計,對應於一個7×12的比特圖,如下圖所示,-1表示白色,1表示黑色,這樣每個符號的比特圖的黑白色就對應於一個編碼。
該層有84個特徵圖,特徵圖大小與C5一樣都是1×1,與C5層全連接。
由於是全連接,參數數量為(120+1)×84=10164。跟經典神經網路一樣,F6層計算輸入向量和權重向量之間的點積,再加上一個偏置,然後將其傳遞給sigmoid函數得出結果。
由於是全連接,連接數與參數數量一樣,也是10164。
Output層也是全連接層,共有10個節點,分別代表數字0到9。如果第i個節點的值為0,則表示網路識別的結果是數字i。
該層採用徑向基函數(RBF)的網路連接方式,假設x是上一層的輸入,y是RBF的輸出,則RBF輸出的計算方式是:
上式中的Wij的值由i的比特圖編碼確定,i從0到9,j取值從0到7×12-1。RBF輸出的值越接近於0,表示當前網路輸入的識別結果與字元i越接近。
由於是全連接,參數個數為84×10=840
由於是全連接,連接數與參數個數一樣,也是840
from skimage import io,transform
import os
import glob
import numpy as np
import tensorflow as tf
#將所有的圖片重新設置尺寸為32*32
w = 32
h = 32
c = 1
#mnist數據集中訓練數據和測試數據保存地址
train_path = "E:/data/datasets/mnist/train/"
test_path = "E:/data/datasets/mnist/test/"
#讀取圖片及其標簽函數
'''os.listdir()返回指定的文件夾包含的文件或文件夾的名字,存放於一個列表中;os.path.isdir()判斷某一路徑是否為目錄
enumerate()將一個可遍歷的數據對象(如列表、元組或字元串)組合為一個索引序列,數據下標和相應數據'''
def read_image(path):
label_dir = [path+x for x in os.listdir(path) if os.path.isdir(path+x)]
images = []
labels = []
for index,folder in enumerate(label_dir):
for img in glob.glob(folder+'/*.png'):
print("reading the image:%s"%img)
image = io.imread(img)
image = transform.resize(image,(w,h,c))
images.append(image)
labels.append(index)
return np.asarray(images,dtype=np.float32),np.asarray(labels,dtype=np.int32)
#讀取訓練數據及測試數據
train_data,train_label = read_image(train_path)
test_data,test_label = read_image(test_path)
#打亂訓練數據及測試數據 np.arange()返回一個有終點和起點的固定步長的排列,
train_image_num = len(train_data)
train_image_index = np.arange(train_image_num) ##起始點0,結束點train_image_num,步長1,返回類型array,一維
np.random.shuffle(train_image_index)
train_data = train_data[train_image_index]
train_label = train_label[train_image_index]
test_image_num = len(test_data)
test_image_index = np.arange(test_image_num)
np.random.shuffle(test_image_index)
test_data = test_data[test_image_index]
test_label = test_label[test_image_index]
#搭建CNN 此函數可以理解為形參,用於定義過程,在執行的時候再賦具體的值,形參名X,y_
x = tf.placeholder(tf.float32,[None,w,h,c],name='x')
y_ = tf.placeholder(tf.int32,[None],name='y_')
def inference(input_tensor,train,regularizer):
#第一層:卷積層,過濾器的尺寸為5×5,深度為6,不使用全0補充,步長為1。
#尺寸變化:32×32×1->28×28×6
'''參數的初始化:tf.truncated_normal_initializer()或者簡寫為tf.TruncatedNormal()、tf.RandomNormal() 去掉_initializer,大寫首字母即可
生成截斷正態分布的隨機數,這個初始化方法好像在tf中用得比較多mean=0.0, stddev=1.0 正態分布
http://www.mamicode.com/info-detail-1835147.html'''
with tf.variable_scope('layer1-conv1'):
conv1_weights = tf.get_variable('weight',[5,5,c,6],initializer=tf.truncated_normal_initializer(stddev=0.1))
conv1_biases = tf.get_variable('bias',[6],initializer=tf.constant_initializer(0.0))
conv1 = tf.nn.conv2d(input_tensor,conv1_weights,strides=[1,1,1,1],padding='VALID')
relu1 = tf.nn.relu(tf.nn.bias_add(conv1,conv1_biases))
#第二層:池化層,過濾器的尺寸為2×2,使用全0補充,步長為2。
#尺寸變化:28×28×6->14×14×6
with tf.name_scope('layer2-pool1'):
pool1 = tf.nn.max_pool(relu1,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
#第三層:卷積層,過濾器的尺寸為5×5,深度為16,不使用全0補充,步長為1。
#尺寸變化:14×14×6->10×10×16
with tf.variable_scope('layer3-conv2'):
conv2_weights = tf.get_variable('weight',[5,5,6,16],initializer=tf.truncated_normal_initializer(stddev=0.1))
conv2_biases = tf.get_variable('bias',[16],initializer=tf.constant_initializer(0.0))
conv2 = tf.nn.conv2d(pool1,conv2_weights,strides=[1,1,1,1],padding='VALID')
relu2 = tf.nn.relu(tf.nn.bias_add(conv2,conv2_biases))
#第四層:池化層,過濾器的尺寸為2×2,使用全0補充,步長為2。
#尺寸變化:10×10×6->5×5×16
with tf.variable_scope('layer4-pool2'):
pool2 = tf.nn.max_pool(relu2,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
#將第四層池化層的輸出轉化為第五層全連接層的輸入格式。第四層的輸出為5×5×16的矩陣,然而第五層全連接層需要的輸入格式
#為向量,所以我們需要把代表每張圖片的尺寸為5×5×16的矩陣拉直成一個長度為5×5×16的向量。
#舉例說,每次訓練64張圖片,那麼第四層池化層的輸出的size為(64,5,5,16),拉直為向量,nodes=5×5×16=400,尺寸size變為(64,400)
pool_shape = pool2.get_shape().as_list()
nodes = pool_shape[1]*pool_shape[2]*pool_shape[3]
reshaped = tf.reshape(pool2,[-1,nodes])
#第五層:全連接層,nodes=5×5×16=400,400->120的全連接
#尺寸變化:比如一組訓練樣本為64,那麼尺寸變化為64×400->64×120
#訓練時,引入dropout,dropout在訓練時會隨機將部分節點的輸出改為0,dropout可以避免過擬合問題。
#這和模型越簡單越不容易過擬合思想一致,和正則化限制權重的大小,使得模型不能任意擬合訓練數據中的隨機雜訊,以此達到避免過擬合思想一致。
#本文最後訓練時沒有採用dropout,dropout項傳入參數設置成了False,因為訓練和測試寫在了一起沒有分離,不過大家可以嘗試。
'''tf.matmul()這個函數是專門矩陣或者tensor乘法,而不是矩陣元素對應元素相乘
tf.multiply()兩個矩陣中對應元素各自相乘
tf.nn.dropout(x, keep_prob):TensorFlow裡面為了防止或減輕過擬合而使用的函數,它一般用在全連接層,
x:指輸入;keep_prob: 設置神經元被選中的概率,使輸入tensor中某些元素變為0,其它沒變0的元素變為原來的1/keep_prob大小,可以想像下,比如某些元素棄用
在初始化時keep_prob是一個佔位符,keep_prob = tf.placeholder(tf.float32).
tensorflow在run時設置keep_prob具體的值,例如keep_prob: 0.5,train的時候才是dropout起作用的時候
keep_prob: A scalar Tensor with the same type as x. The probability that each element is kept.'''
with tf.variable_scope('layer5-fc1'):
fc1_weights = tf.get_variable('weight',[nodes,120],initializer=tf.truncated_normal_initializer(stddev=0.1))
if regularizer != None:
tf.add_to_collection('losses',regularizer(fc1_weights))
fc1_biases = tf.get_variable('bias',[120],initializer=tf.constant_initializer(0.1))
fc1 = tf.nn.relu(tf.matmul(reshaped,fc1_weights) + fc1_biases)
if train:
fc1 = tf.nn.dropout(fc1,0.5)
#第六層:全連接層,120->84的全連接
#尺寸變化:比如一組訓練樣本為64,那麼尺寸變化為64×120->64×84
'''tf.add_to_collection:把變數放入一個集合,把很多變數變成一個列表
tf.get_collection:從一個結合中取出全部變數,是一個列表
tf.add_n:把一個列表的東西都依次加起來'''
with tf.variable_scope('layer6-fc2'):
fc2_weights = tf.get_variable('weight',[120,84],initializer=tf.truncated_normal_initializer(stddev=0.1))
if regularizer != None:
tf.add_to_collection('losses',regularizer(fc2_weights))
fc2_biases = tf.get_variable('bias',[84],initializer=tf.truncated_normal_initializer(stddev=0.1))
fc2 = tf.nn.relu(tf.matmul(fc1,fc2_weights) + fc2_biases)
if train:
fc2 = tf.nn.dropout(fc2,0.5)
#第七層:全連接層(近似表示),84->10的全連接
#尺寸變化:比如一組訓練樣本為64,那麼尺寸變化為64×84->64×10。最後,64×10的矩陣經過softmax之後就得出了64張圖片分類於每種數字的概率,
#即得到最後的分類結果。
with tf.variable_scope('layer7-fc3'):
fc3_weights = tf.get_variable('weight',[84,10],initializer=tf.truncated_normal_initializer(stddev=0.1))
if regularizer != None:
tf.add_to_collection('losses',regularizer(fc3_weights))
fc3_biases = tf.get_variable('bias',[10],initializer=tf.truncated_normal_initializer(stddev=0.1))
logit = tf.matmul(fc2,fc3_weights) + fc3_biases
return logit
#正則化,交叉熵,平均交叉熵,損失函數,最小化損失函數,預測和實際equal比較,tf.equal函數會得到True或False,
#accuracy首先將tf.equal比較得到的布爾值轉為float型,即True轉為1.,False轉為0,最後求平均值,即一組樣本的正確率。
#比如:一組5個樣本,tf.equal比較為[True False True False False],轉化為float型為[1. 0 1. 0 0],准確率為2./5=40%。
'''規則化可以幫助防止過度配合,提高模型的適用性。(讓模型無法完美匹配所有的訓練項。)(使用規則來使用盡量少的變數去擬合數據)
規則化就是說給需要訓練的目標函數加上一些規則(限制),讓他們不要自我膨脹。
TensorFlow會將L2的正則化損失值除以2使得求導得到的結果更加簡潔
如tf.contrib.layers.apply_regularization/l1_regularizer/l2_regularizer/sum_regularizer
https://blog.csdn.net/liushui94/article/details/73481112
sparse_softmax_cross_entropy_with_logits()是將softmax和cross_entropy放在一起計算
https://blog.csdn.net/ZJRN1027/article/details/80199248'''
regularizer = tf.contrib.layers.l2_regularizer(0.001)
y = inference(x,False,regularizer)
cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y,labels=y_)
cross_entropy_mean = tf.rece_mean(cross_entropy)
loss = cross_entropy_mean + tf.add_n(tf.get_collection('losses'))
train_op = tf.train.AdamOptimizer(0.001).minimize(loss)
correct_prediction = tf.equal(tf.cast(tf.argmax(y,1),tf.int32),y_)
accuracy = tf.rece_mean(tf.cast(correct_prediction,tf.float32))
#每次獲取batch_size個樣本進行訓練或測試
def get_batch(data,label,batch_size):
for start_index in range(0,len(data)-batch_size+1,batch_size):
slice_index = slice(start_index,start_index+batch_size)
yield data[slice_index],label[slice_index]
#創建Session會話
with tf.Session() as sess:
#初始化所有變數(權值,偏置等)
sess.run(tf.global_variables_initializer())
#將所有樣本訓練10次,每次訓練中以64個為一組訓練完所有樣本。
#train_num可以設置大一些。
train_num = 10
batch_size = 64
for i in range(train_num):
train_loss,train_acc,batch_num = 0, 0, 0
for train_data_batch,train_label_batch in get_batch(train_data,train_label,batch_size):
_,err,acc = sess.run([train_op,loss,accuracy],feed_dict={x:train_data_batch,y_:train_label_batch})
train_loss+=err;train_acc+=acc;batch_num+=1
print("train loss:",train_loss/batch_num)
print("train acc:",train_acc/batch_num)
test_loss,test_acc,batch_num = 0, 0, 0
for test_data_batch,test_label_batch in get_batch(test_data,test_label,batch_size):
err,acc = sess.run([loss,accuracy],feed_dict={x:test_data_batch,y_:test_label_batch})
test_loss+=err;test_acc+=acc;batch_num+=1
print("test loss:",test_loss/batch_num)
print("test acc:",test_acc/batch_num)
⑻ Multi-Sample Dropout
1. 模型結構
orginal dropout : 對單個樣本,進行單次drop out。
2. 思想
stacking方法中的子模型 。事實證明,用 多個子模型 做模型 融合 可以提高模型的性能。
訓練時,對原始數據進行變換,創建出多個分身。分身可能是帶噪音,可能是不完整(此方法)。從而提高泛化能力。
3. 實現方法
訓練階段,每次dropout首先會隨機的選取50%(這個比例可以自己設置)的神經元,其他50%被丟棄。
通過多次的dropout,從特徵中選擇了不同的 特徵子集 進行訓練,相當於重采樣。
再通過共享的全連接層和loss層。
loss:每條樣本,多個分身,得到的多個loss的平均值最小。
4. 優點
加快收斂,性能提升。dropout只使用在最後的幾層,而全連接層的訓練時間較快。因此,對比更大的 mini-batch,雖然可以達到相同的效果,但是實際上會增加計算的耗時。
實現簡單:在 dropout 層後復制部分訓練網路,並在這些復制的全連接層之間共享權重就可以了,無需新運算符。
5. 發散
傳統的機器學習演算法,如排序中常用的樹模型。stack思想下,得到了不同的樹。如果就用一棵樹呢??泛化能力能變強嗎?
Stacking是通過 一個 元分類器或者元回歸器來 整合多個 分類模型或回歸模型的集成學習技術。基礎模型利用整個訓練集做訓練,元模型將基礎模型的特徵作為特徵進行訓練。(N->1) 。基礎模型通常包含不同的學習演算法,因此stacking通常是異質集成。
6. 缺點
1)模型的設計,存在訓練和預測 不一致問題 。訓練時,Dropout 往(某些層的)輸入加上了乘性雜訊。而預測時,理論上,應該是對同一個輸入多次傳入模型中(模型不關閉Dropout),然後把多次的預測結果平均值作為最終的預測結果。實際上,預測的時候用的是關閉Dropout的單模型,兩者未必等價,這就是Dropout的訓練預測不一致問題。
2)損失函數的設計,只有交叉熵。如果只有交叉熵這一項,模型的訓練結果是「不同的Dropout下,目標類的得分都大於非目標類的得分」。
鏈接:https://kexue.fm/archives/8496
⑼ 神經網路dropout什麼意思啊
dropout是指在深度學習網路的訓練過程中,對於神經網路單元,按照一定的概率將其暫時從網路中丟棄。注意是暫時,對於隨機梯度下降來說,由於是隨機丟棄,故而每一個mini-batch都在訓練不同的網路。
然而Hinton在2012年文獻:《Improving neural networks by preventing co-adaptation of feature detectors》提出了,在每次訓練的時候,隨機讓一半的特徵檢測器停過工作,這樣可以提高網路的泛化能力,Hinton又把它稱之為dropout。
⑽ AI數學基礎18——常見的正則化方法
1,L2 regularization(權重衰減) L2正則化就是在代價函數後面再加上一個正則化項λ ,使得權重在更新的時候,乘以一個小於1的因子(1-a(λ/m)),這個可以防止W過大。正則化項裡面有一個系數1/2,1/2經常會看到,主要是為了後面求導的結果方便,後面那一項求導會產生一個2,與1/2相乘剛好湊整。
過擬合的時候,擬合函數的系數往往非常大。過擬合,就是擬合函數需要顧忌每一個點,最終形成的擬合函數波動很大。在某些很小的區間里,函數值的變化很劇烈。這就意味著函數在某些小區間里的導數值(絕對值)非常大,由於自變數值可大可小,所以只有系數足夠大,才能保證導數值很大
L2 Regularization 防止了系數W過大,也就防止了擬合函數導數值過大,也就防止了函數導數值波動過大,也就解決了過擬合問題。
L2正則化是訓練深度學習模型中最常用的一種解決過擬合問題的方法。
2,L1 regularization, L1正則化的正則項是所有權重w的絕對值的和,乘以λ/n(這里不像L2正則化項那樣,需要再乘以1/2);消除過擬合的原因與L2類似。使用頻率沒有L2正則化高。
3,Dropout正則化
L1、L2正則化是通過修改代價函數來實現的,而Dropout則是通過修改神經網路本身來實現的。
Dropout是指在深度學習網路的訓練過程中,對於神經網路單元,按照一定的概率將其暫時從網路中丟棄。注意是暫時,對於隨機梯度下降來說,由於是隨機丟棄,故而每一個mini-batch都在訓練不同的網路。
運用了dropout的訓練過程,相當於訓練了很多個只有半數隱層單元的神經網路(後面簡稱為「半數網路」),每一個這樣的半數網路,都可以給出一個分類結果,這些結果有的是正確的,有的是錯誤的。隨著訓練的進行,大部分半數網路都可以給出正確的分類結果,那麼少數的錯誤分類結果就不會對最終結果造成大的影響。
dropout率的選擇:經過交叉驗證, 隱含節點dropout率等於0.5的時候效果最好 ,原因是0.5的時候dropout隨機生成的網路結構最多
具體細節,推薦Alex和Hinton的論文《 ImageNet Classification with Deep Convolutional Neural Networks 》
4,數據集擴增(data augmentation)
在深度學習方法中,更多的訓練數據,意味著可以用更深的網路,訓練出更好的模型。
但是很多時候,收集更多的數據意味著需要耗費更多的人力物力,非常困難。
所以,可以在原始數據上做些改動,得到更多的數據,以圖片數據集舉例,可以做各種變換,如:
1,水平翻轉或任意角度旋轉;2,裁剪;3,添加雜訊
更多數據意味著什麼?
用50000個MNIST的樣本訓練SVM得出的accuracy94.48%,用5000個MNIST的樣本訓練NN得出accuracy為93.24%,所以更多的數據可以使演算法表現得更好。在機器學習中,演算法本身並不能決出勝負,不能武斷地說這些演算法誰優誰劣,因為數據對演算法性能的影響很大。
5,提前停止訓練神經網路(Early Stop)
在一個適中的迭代次數,W不是很大的時候,dev set error接近最小,train set error適中的時候,提前停止訓練,如下圖所示
參考文獻:Andrew Ng《Prractical aspects of Deep learning》1.1~1.8