back to index
【機器學習2021】類神經網路訓練不起來怎麼辦 (五): 批次標準化 (Batch Normalization) 簡介

link |
這段是想跟大家簡短的介紹一下Batch Normalization的技術。
link |
因為上課的內容想要配合作業的關係,所以我們會先把作業需要的,比如說Self-Tension就先講一講。
link |
我們在比較覺得進度有跟得上的時候,就講一些Training的Tips。
link |
所以這樣可能有點散亂了,就Training的Tips散佈在課程的各個地方。
link |
但Training的Tips這種東西,如果真的想講的話是永遠都講不完的,這個Tips實在是太多了,所以我們有空的時候就講一些Tips。
link |
我們這邊要講的是Batch Normalization。這個時候講Batch Normalization是最合適的,因為Batch Normalization在作業三是用得上的。
link |
而且作業三助教的程式裡面其實就有Batch Normalization。
link |
在做CNN的時候,今天做影像處理的時候,Batch Normalization往往可以帶來蠻大的幫助。
link |
所以我們正好準備要來做作業三了,所以我們來講一下Batch Normalization。
link |
這邊是一個很快的介紹Batch Normalization這個技術。
link |
那你記得我們之前才講過說,我們能不能夠直接改Aero Surface的Landscape。
link |
我們覺得Aero Surface如果很崎嶇的時候,它比較難Train。
link |
那我們能不能夠直接把三產品讓它變得比較好Train呢?
link |
Batch Normalization就是其中一個把三產品的想法。
link |
那我記得我們在講Optimization的時候,我們一開始就跟大家講說,不要小看Optimization這個問題。
link |
有時候就算你的Aero Surface是Convex的,也就是它就是一個腕的形狀,都不見得很好Train。
link |
那我們舉的例子就是,假設你的兩個參數,它們對Loss的斜率差別非常大。
link |
在W1這個方向上面,你的斜率變化很小,在W2這個方向上面,斜率變化很大。
link |
你今天如果是固定的Learning Rate,你可能很難得到好的結果。
link |
所以我們才說,你需要Adaptive的Learning Rate,你需要用Add-On等等比較進階的Optimization的方法,才能夠得到好的結果。
link |
那現在我們要從另外一個方向想,直接把難做的Aero Surface把它改掉,看能不能夠改得好做一點。
link |
那在做這件事之前,也許我們第一個要問的問題就是,有這種狀況,W1跟W2它們的斜率差很多的這種狀況,到底是從什麼地方來的?
link |
那我們這邊就是舉一個例子,假設我現在有一個非常簡單的Model,它的輸入是X1跟X2。
link |
X1跟X2它對應的參數就是W1跟W2,它是一個Linear的Model,沒有Activation Function。
link |
W1乘X1,W2乘X2,加上B以後就得到Y,會計算Y跟Y hat之間的差距,當作1。
link |
把所有Trending Data一加起來就是你的Loss,那你希望去Minimize你的Loss。
link |
那什麼樣的狀況,我們會產生像上面這樣子比較不好Trend的Aero Surface呢?
link |
我們來看一下這個W1,如果今天W1有改變的時候,它對Loss的變化,我們要怎麼看呢?
link |
當我們對W1有一個小小的改變,比如說加上Delta W1的時候,那這個L也會有一個改變。
link |
那這個W1是透過W1改變的時候,你就改變了Y,Y改變的時候你就改變了E,然後接下來就改變了L。
link |
所以當W1改變的時候,L就跟著改變。
link |
那什麼時候W1的改變會對L的影響很小呢?
link |
那什麼時候W1這邊的變化,它在Aero Surface上的斜率會很小呢?
link |
一個可能性是當你的Input很小的時候,假設X1的值都很小。
link |
假設X1的值在不同的Trending Example裡面,它的值都很小,那因為X1是直接乘上W1。
link |
如果X1的值都很小,W1有一個變化的時候,它對Y的影響也是小的,對E的影響也是小的,它對L的影響就會是小的。
link |
所以如果W1接的Input它的值都很小,那就會產生這邊的這樣的case,你在W1上面的變化對大L的影響是小的。
link |
反之呢,如果今天是X2的話,假設X2它的值都很大,當你的W2有一個小小的變化的時候,
link |
雖然W2這個變化可能很小,但是因為它乘上了X2,X2的值很大,那Y的變化就會很大,那E的變化就會很大,那L的變化就會很大。
link |
那就會導致我們在W這個方向上做變化的時候,我們把W改變一點點,那我們的Error Surface就會有很大的變化。
link |
所以你發現說,今天在這個Linear的Model裡面,當我們Input的Feature每一個Dimension的值,它的Scale差距很大的時候,
link |
我們就可能產生像這樣子的Error Surface,就可能產生不同方向,它的斜率非常不同的、它的坡度非常不同的Error Surface。
link |
所以怎麼辦呢?我們有沒有可能給不同的Dimension,Feature裡面不同的Dimension,讓它有同樣的數值的範圍?
link |
如果我們可以給不同的Dimension同樣的數值範圍的話,那我們可能就可以製造比較好的Error Surface,讓Training變得比較容易一點。
link |
那怎麼讓不同的Dimension有類似的、有接近的數值的範圍呢?其實有很多不同的方法。
link |
那這些不同的方法往往就合起來統稱為Feature Normalization。
link |
那我以下所講的方法只是Feature Normalization的一種可能性,它並不是Feature Normalization的全部。
link |
你可以怎麼做呢?你可以說,假設X1到XR是我們所有的訓練資料的Feature Vector。
link |
我們把所有訓練資料的Feature Vector通通都集合起來。
link |
那每一個Vector,X1裡面就有X上標1下標1,代表X1的第一個Element。
link |
X上標2下標1就代表X2的第一個Element,以此類推。
link |
那我們把同一個Dimension,不同筆資料,不同Feature Vector,同一個Dimension裡面的數值,把它取出來。
link |
然後去計算某一個Dimension的Mean。
link |
那我們現在計算的是第i一個Dimension,它的Mean就是ni。
link |
那我們計算第i一個Dimension的Standard Deviation,我們用σi來表示它。
link |
那接下來,我們就可以做一種Normalization。
link |
那這種Normalization其實叫做標準化,其實叫Standardization。
link |
不過我們這邊等一下就統稱Normalization就好了。
link |
那我們怎麼做Normalization呢?
link |
我們就是把這個X,把這邊的某一個數值,減掉這個Dimension算出來的Mean。
link |
再除掉這個Dimension算出來的Standard Deviation。
link |
減掉Mean,除掉Standard Deviation,得到新的數值,叫做XΔ。
link |
那得到新的數值以後,再把新的數值把它塞回去。
link |
我們等一下都用這個Δ來代表有被Normalize以後的數值。
link |
那做完Normalize以後有什麼好處呢?
link |
做完Normalize以後,這個Dimension上面的數值就會平均是0,然後它的Variance就會是1。
link |
所以這一排數值,它的分布網就都會在0上下。
link |
那你對每一個Dimension,每一個Dimension,每一個Dimension都做一樣的事情,都做一樣的Normalization,
link |
把它們變成Mean接近0,Variance是1,
link |
那你就會發現說所有的數值,所有feature不同Dimension的數值都在0上下。
link |
那你可能就可以製造一個比較好的Aerial Surface。
link |
所以像這樣子的Feature Normalization的方式,往往對你的Training有幫助。
link |
它可以讓你在做Gradient Descent的時候,你的Gradient Descent它的Loss收斂更快一點,
link |
可以讓你的Gradient Descent它的訓練更順利一點。
link |
這個是Feature Normalization。
link |
所以當然Deep Learning可以做Feature Normalization,你可能會把Feature做Normalize以後,
link |
其實在助教的Code裡面,我們都有對Feature做Normalization。
link |
那當你得到X tilde以後呢,這個是X tilde代表Normalize的Feature以後呢,
link |
把它丟到Deep Neural裡面去做接下來的計算,去做接下來的訓練。
link |
所以你把X1 tilde通過第一個Layer得到Z1,
link |
那你有可能通過Activation Function,不管是選Signal或Relu都可以,
link |
然後再得到A1,然後再通過下一層等等,那就看你有幾層Neural就做多少的運算。
link |
但是如果我們進一步來想的話,對W2來說,
link |
這邊的A1 A3,這邊的Z1 Z3,其實也是另外一種Input。
link |
如果這邊X tilde,雖然它已經做Normalize,但是通過W1以後它就沒有做Normalize啦,
link |
如果X tilde通過W1得到Z1,而Z1的不同的Dimension間,
link |
它的數值的分布仍然有很大的差異的話,
link |
那我們要Tread W2第二層的參數會不會也有困難呢?
link |
所以這樣想起來,我們也應該要對這邊的A或對這邊的Z做Feature Normalization。
link |
對W2來說,這邊的A或這邊的Z其實也是一種Feature,
link |
我們應該要對這些Feature也做Normalization。
link |
但這邊有人就會問一個問題,應該要在Activation Function之前做Normalization,
link |
還是要在Activation Function之後做Normalization呢?
link |
你可以自己在座位裡面試試看這兩件事情有沒有差異,
link |
所以你對Z做Feature Normalization或對A做Feature Normalization其實都可以啦。
link |
那如果你選擇的是Sigmoid,那可能比較推薦對Z做Feature Normalization,
link |
因為你知道Sigmoid是一個S的形狀嘛,
link |
所以如果你對Z做Feature Normalization把所有的值都挪到0附近,
link |
那你到時候算Gradient的時候算出來的值會比較大。
link |
那不過因為你不見得是選Sigmoid嘛,
link |
所以你也不一定要把Feature Normalization放在Z這個地方,
link |
若是選別的,也許你選A也會有好的結果,也說不定。
link |
這個Normalization要放在Activation Function之前或之後都是可以的,
link |
好,那我們這邊就是對Z做一下Feature Normalization。
link |
那怎麼對Z做Feature Normalization呢?
link |
那你就把Z想成是另外一種Feature嘛,
link |
我們就把Z1、Z2、Z3拿出來算一下它的mean。
link |
我們就把Z1、Z2、Z3這三個vector呢,
link |
把它平均起來得到μ這個vector。
link |
那我們也算一個Standard Deviation,
link |
這個Standard Deviation這邊這個σ代表了一個vector,
link |
這邊的平方這個notation有點abuse,
link |
這邊的平方就是指對每一個element都去做平方,
link |
然後再開根號,這邊開根號指的是對每一個element,
link |
向量裡面的每一個element都去做開根號,得到σ。
link |
就把這三個vector裡面的每一個dimension,
link |
都去把它的μ算出來,把它的σ算出來。
link |
從Z1、Z2、Z3,算出μ、算出σ。
link |
好,接下來呢,你就把這邊的每一個Z啊,
link |
你把Zi減掉μ除以σ,就得到Zi的θ。
link |
所以這邊這個除呢,它的notation有點abuse,
link |
Element wise的相除,就是Zi減μ,它是一個向量。
link |
所以分子的地方是一個向量,分母的地方也是一個向量。
link |
把這個兩個向量,它們對應的element的值相除,
link |
是我這邊這個除號的意思,這邊得到Z的θ。
link |
好,所以我們就是把Z1減μ除以σ,得到Z1θ。
link |
那就把這個Z1、Z2、Z3做feature normalization,
link |
通過activation function得到其他vector,
link |
然後再去通過其他layer等等,這樣就可以了。
link |
這樣你就等於對Z1、Z2、Z3做了feature normalization,
link |
但這邊有一件有趣的事情,這件事情是這樣子的。
link |
這邊的μ跟σ,他們其實都是根據Z1、Z2、Z3算出來的。
link |
所以這邊Z1啊,它本來如果我們沒有做feature normalization的時候,
link |
你改變了Z1的值,你會改變這邊A的值。
link |
但是現在啊,當你改變Z1的值的時候,μ跟σ也會跟著改變。
link |
μ跟σ改變以後,Z2的值、A2的值、Z3的值、A3的值也會跟著改變。
link |
所以之前啊,我們每一個X1θ、X2θ、X3θ,它是獨立分開處理的。
link |
但是我們在做feature normalization以後,
link |
這三個example,他們變得彼此關聯了。
link |
我們這邊Z1只要有改變,接下來Z2、A2、Z3、A3也都會跟著改變。
link |
所以這邊啊,其實你要把當你有做feature normalization的時候,
link |
你要把這一整個process,就是有收集一堆feature,
link |
把這堆feature算出μ跟σ這件事情,當作是network的一部分。
link |
也就是說你現在有一個比較大的network,
link |
你之前的network都只吃一個input得到一個output。
link |
現在呢,你有一個比較大的network,
link |
這個大的network它是吃一堆input,
link |
用這堆input在這個network裡面要算出μ跟σ,
link |
那這個地方比較抽象,不知道大家有沒有,
link |
希望希望你聽得懂,如果你覺得有困惑的話,
link |
你可以等一下詢問或者是在討論板上發問。
link |
那這一段呢,我覺得只可繪衣不可言傳這樣子,
link |
現在不是一個network處理一個example,
link |
而是有一個巨大的network它處理一把example,
link |
用這把example還要算個μ跟σ得到一把output。
link |
因為你的訓練資料裡面你的data非常多啊,
link |
現在一個data set的benchmark topper都上百萬筆資料啊,
link |
你哪有辦法一次把上百萬筆資料丟到一個network裡面,
link |
你這個GPU的memory根本無法,
link |
好,那你那個GPU的memory根本沒有辦法把整個data set的data都漏進去啊,
link |
你不會讓這個network考慮整個training data裡面的所有example,
link |
你只會考慮一個batch裡面的example,
link |
那你這個巨大的network就是把64筆data讀進去,
link |
算這64筆data的μ,算這64筆data的σ,
link |
對這64筆data都去做normalization,
link |
我們只對一個batch裡面的data做normalization,
link |
所以這招叫做batch normalization,
link |
這個就是你常常聽到的batch normalization,
link |
那這個batch normalization顯然有一個問題,
link |
就是你一定要有一個夠大的batch,
link |
所以這個batch normalization是適用於batch size比較大的時候,
link |
那我們因為batch size如果比較大,
link |
也許這個batch size裡面的data就足以表示
link |
本來要對整個Corpus做feature normalization這件事情,
link |
改成只在一個batch做feature normalization,
link |
好,那在做batch normalization的時候,
link |
接下來你會把這個θ再乘上另外一個向量叫做γ,
link |
所以你是把θ跟γ做element wise的相乘,
link |
而β跟γ你要把它想成是network的參數,
link |
如果我們做normalization以後,
link |
那也許這個限制會帶來什麼負面的影響,
link |
然後讓network現在它的hidden layer的output不需要平均是0,
link |
剛才不是說做batch normalization,
link |
就是為了要讓每一個不同的dimension,
link |
我們才做這個normalization嗎?
link |
這樣不會不同dimension的分布,
link |
一開始是一個裡面的值全部都是1的向量,
link |
那β是一個裡面的值全部都是0的向量,
link |
所以γ是一個1 vector都是1的向量,
link |
β是一個0 vector裡面的值都是0的向量,
link |
所以讓你的network在一開始訓練的時候,
link |
每一個dimension的分布是比較接近的,
link |
Aerosurface走到一個比較好的地方以後,
link |
所以加Batch Normalization,
link |
接下來就要講testing的部分了,
link |
剛才講的都是training的部分,
link |
Testing有時候又叫inference,
link |
做個inference,inference指的就是testing。
link |
這個Batch Normalization在inference或是testing的時候,
link |
在testing的時候,當然如果今天你是在做作業,
link |
我們一次會把所有的testing的資料給你,
link |
所以你確實也可以在testing的資料上面,
link |
你是一個真正的線上的application,
link |
比如說你的batch size是64,
link |
你不能等說我累積了一個batch的資料,
link |
但是在做Batch Normalization的時候,
link |
一個normalize過的feature進來,
link |
那這個μ跟σ是用一個batch的資料算出來的,
link |
但如果今天在testing的時候根本就沒有batch,
link |
那我們要怎麼算這個μ跟怎麼算這個σ呢?
link |
Batch Normalization在testing的時候,
link |
PyTorch是怎麼處理這件事的呢?
link |
如果你有在做Batch Normalization的話,
link |
你每一個batch計算出來的μ跟σ,
link |
他都會拿出來算moving average,
link |
你每一次取一個batch出來的時候,
link |
一直到取第一個batch出來的時候,
link |
接下來你會算一個moving average,
link |
也就是你會把你現在算出來的μ的一個平均值,
link |
叫做μbar乘上某一個factor,
link |
這也是一個hyperparameter,
link |
你就不用算batch裡面的μ跟σ了,
link |
得到的moving average,
link |
這個就是batch normalization,
link |
好,那這個是從batch normalization,
link |
batch normalization用在CNN上,
link |
你會告訴你說batch normalization,
link |
代表的是validation state上面的accuracy,
link |
是沒有做batch normalization的結果,
link |
他用的是inception的network,
link |
也是以CNN為基礎的network架構,
link |
代表沒有做batch normalization的結果,
link |
然後如果有做batch normalization,
link |
可能都跑到差不多的accuracy,
link |
代表說這幾個點的accuracy是一樣的啦,
link |
相較於沒有做batch normalization,
link |
粉紅色的線是sigmoid function,
link |
就是sigmoid function一般的認知,
link |
我們是用sigmoid function,
link |
因為sigmoid function他的training是比較困難的,
link |
加batch normalization,
link |
sigmoid沒有做batch normalization的結果,
link |
sigmoid不加batch normalization,
link |
根本連train都train不起來,
link |
是把learning rate設比較大一點,
link |
乘5就是learning rate變原來的5倍,
link |
然後乘30就是learning rate變原來的30倍,
link |
那因為如果你做batch normalization的話,
link |
那你的error surface會比較平滑,
link |
所以你就可以把你的learning rate設大一點,
link |
那這邊有個不好解釋的奇怪的地方就是,
link |
不知道為什麼learning rate設30倍的時候,
link |
你只要做deep learning就是,
link |
batch normalization,
link |
在原始的batch normalization那篇paper裡面,
link |
internal covariate shift,
link |
covariate shift這個詞彙是原來就有的,
link |
internal covariate shift我認為是,
link |
batch normalization的作者自己發明的,
link |
他認為說今天在train network的時候,
link |
那我們今天計算出gradient以後,
link |
把b這一層的參數update成b',
link |
現在我們在把bupdate到b'的時候,
link |
那我們在計算bupdate到b'的gradient的時候,
link |
但是我們計算這個gradient的時候,
link |
那如果做batch normalization的話,
link |
因為我們每次都有做normalization,
link |
How does batch normalization help optimization?
link |
它就打臉了internal covariance shift的觀點,
link |
internal covariance shift,
link |
首先它不一定是training network時候的一個問題,
link |
然後batch normalization它會比較好,
link |
可能不見得是因為它解決了internal covariance shift,
link |
不管有沒有做batch normalization,
link |
對training也沒有太大的傷害,
link |
所以它告訴你說internal covariance shift,
link |
可能不是training network的時候最主要的問題,
link |
它可能也不是batch normalization會好的一個關鍵,
link |
好,那為什麼batch normalization會比較好呢?
link |
在這篇How does batch normalization help optimization這篇論文裡面,
link |
至少支持了batch normalization可以改變error surface,
link |
讓error surface比較不崎嶇這個觀點,
link |
他說他覺得batch normalization的positive impact,
link |
因為他說如果我們要讓network,
link |
這個error surface變得比較不崎嶇,
link |
其實不見得要做batch normalization,
link |
感覺有很多其他的方法都可以讓error surface變得不崎嶇,
link |
發現說跟batch normalization performance差不多,
link |
他覺得說positive impact of batch norm on training,
link |
可能是somewhat serendipitous,
link |
怎麼是serendipitous呢?
link |
但偶然並沒有完全表達這個詞彙的意思,
link |
這篇文章的作者也覺得batch normalization,
link |
也像是盤尼西林一樣是一種偶然的發現,
link |
那其實batch normalization不是唯一的normalization,
link |
normalization的方法有一把啦,
link |
那這邊就是列了幾個比較知名的normalization,