1、Normalization是什麼java
Normalization一句話歸納來講就是用一種辦法,將一組數據壓到均值爲0,方差爲1的正態分佈上去,具體作法是數據集的每個元素減去均值再除以標準差。公式以下:(請忽略參數g,g的問題很詭異,後面說)api
這個公式說的更直白一點就是,把每個a,通過平移和縮放,獲得一個新值。而這樣作的一個理由是,平移縮放並不會改變原始數據的分佈狀況,原來最大的仍是最大,原來最小的仍是最小。網絡
Deeplearning中有不少Normalization的方法,有BN、LN、IN、GN等等,每一種Normalization公式都同樣,只是沿着的軸不同,BN就是沿着minibatch方向,LN就是沿着影藏層的output vector維方向,舉個例子,對於四維張量[minibatch,depth、height、width],那就是沿着depth方向,把height、width維約簡掉。ide
2、說說Layer Normalization函數
論文地址:https://arxiv.org/pdf/1607.06450.pdfthis
Layer Normalization對於時間序列數據有奇效,下面截一段論文的原文。這是在RNN上用Layer Normalizationcode
簡短的話說一下論文的變量含義,a表示t時刻點rnn的預輸出值(尚未通過激活函數哦),h表示rnn某一個隱層t時刻點的輸出。orm
那麼,這裏Normalization是哪個維度呢?假設RNN的輸入張量爲[minibatch、layerSize、timesteps],這麼這裏Normalization的就是layerSize這一維。這樣可能仍是太抽象,請看下圖:blog
這裏Normalization的就是紅色箭頭指向的每個維度的向量,對於一條數據的每一個time step而言,就求出一個均值和方差,進行變換,下一個time step類推下去。那麼多個time step就有多個均值和方差。get
3、重點說說參數g和b
這裏g和b的維度要和h的維度相同,也就是上圖的values per time step這一維度,也就是layer size的大小,這裏g和b是跟隨着網絡參數學出來的。開始實現時,g的全部值通常會初始化爲1,b的全部值會被初始化爲0,隨着訓練的進行,g和b就會被修改成任意值了。那麼Normalization也就沒有了正態分佈的效果,至關於layer size維乘以了一個隨機向量,注意這裏是向量點積,那麼就等同於給一個隨機的噪聲,竟然也能起做用,也是一個不能解釋的問題。有點沒有道理,但就是這麼難以置信,竟然是work的。
4、deeplearning4j的自動微分實現Layer Normalization
import java.util.Map; import org.deeplearning4j.nn.conf.inputs.InputType; import org.deeplearning4j.nn.conf.layers.samediff.SDLayerParams; import org.deeplearning4j.nn.conf.layers.samediff.SameDiffLayer; import org.nd4j.autodiff.samediff.SDVariable; import org.nd4j.autodiff.samediff.SameDiff; import org.nd4j.linalg.api.ndarray.INDArray; public class LayerNormaliztion extends SameDiffLayer { // gain * standardize(x) + bias private double eps = 1e-5; private static String GAIN = "gain"; private static String BIAS = "bias"; private int nOut; private int timeStep; public LayerNormaliztion(int nOut, int timeStep) { this.timeStep = timeStep; this.nOut = nOut; } protected LayerNormaliztion() { } @Override public InputType getOutputType(int layerIndex, InputType inputType) { return InputType.recurrent(nOut); } @Override public void defineParameters(SDLayerParams params) { params.addWeightParam(GAIN, 1, nOut, 1); params.addWeightParam(BIAS, 1, nOut, 1); } @Override public SDVariable defineLayer(SameDiff sd, SDVariable layerInput, Map<String, SDVariable> paramTable, SDVariable mask) { SDVariable gain = paramTable.get(GAIN);//論文中的g SDVariable bias = paramTable.get(BIAS);//論文中的b SDVariable mean = layerInput.mean("mean", true, 1);//均值 SDVariable variance = sd.math().square(layerInput.sub(mean)).sum(true, 1).div(layerInput.getShape()[1]);//平方差 SDVariable standardDeviation = sd.math().sqrt("standardDeviation", variance.add(eps));//標準差,加上eps 防止分母爲0 long[] maskShape = mask.getShape(); return gain.mul(layerInput.sub(mean).div(standardDeviation)).add(bias) .mul(mask.reshape(maskShape[0], 1, timeStep));//掩碼掩掉多餘長度 } @Override public void initializeParameters(Map<String, INDArray> params) { params.get(GAIN).assign(1); params.get(BIAS).assign(0); } public int getNOut() { return nOut; } public void setNOut(int nOut) { this.nOut = nOut; } public int getTimeStep() { return timeStep; } public void setTimeStep(int timeStep) { this.timeStep = timeStep; } }
5、實戰的結果
就用RNN作文本分類而言,加上LN,收斂會更平穩,但準確率大大降低了。
在deeplearning的世界裏,任何一種方法被提出來,只是在解當前的問題,對於每一種具體的問題,確定是case by case。
快樂源於分享。
此博客乃做者原創, 轉載請註明出處