back to index

【機器學習2021】類神經網路訓練不起來怎麼辦 (二): 批次 (batch) 與動量 (momentum)


link |
00:01.000
好,今天我們要講Batch跟Momentum這兩個訓練的技巧
link |
00:07.000
希望我們在剩下的三十分鐘內可以講完
link |
00:11.000
第一個是Batch
link |
00:13.000
好多同學都問我說
link |
00:15.000
為什麼我要用Batch?
link |
00:17.000
為什麼Training的時候要用Batch?
link |
00:20.000
我本來第一週的時候是不打算講這個東西的
link |
00:23.000
因為我相信講了以後大家就會有好多好多的問題
link |
00:26.000
因為這好像不是一個一般常理會想要採取的方式
link |
00:30.000
但是因為助教的程式裡面有這一段
link |
00:32.000
所以我決定先告訴大家用Batch這個東西
link |
00:36.000
那Batch是怎麼做的呢?
link |
00:38.000
上次我們有講說我們實際上在算微分的時候
link |
00:41.000
你還不是真的對所有Data算出來的L做微分呢
link |
00:46.000
你是把所有的Data分成一個一個的Batch
link |
00:50.000
那有的人是叫做MiniBatch啦
link |
00:52.000
那我這邊叫做Batch其實指的是一樣的東西
link |
00:55.000
助教封篇裡面是寫MiniBatch
link |
00:58.000
這邊每一個Batch的大小就是大B比資料
link |
01:02.000
我們每次在Update參數的時候
link |
01:04.000
我們是拿大B比資料出來算個Loss
link |
01:07.000
算個GradientUpdate參數
link |
01:10.000
拿另外B比資料再算個Loss
link |
01:13.000
再算個Gradient再Update參數
link |
01:16.000
以此類推
link |
01:17.000
所以我們不會拿所有的資料一起去算出Loss
link |
01:21.000
我們會拿一個Batch的資料拿出來算Loss
link |
01:25.000
那我們說所有的Batch看過一遍
link |
01:28.000
叫做一個APOC
link |
01:31.000
那事實上啊
link |
01:32.000
你今天在做這些Batch的時候
link |
01:35.000
在把你所有的資料分成一個一個Batch的時候
link |
01:38.000
你會做一件事情叫做Shuffle
link |
01:41.000
Shuffle有很多不同的做法
link |
01:43.000
但一個常見的做法就是
link |
01:44.000
我們在每一個APOC開始之前
link |
01:48.000
會分一次Batch
link |
01:50.000
然後呢
link |
01:51.000
每一個APOC的Batch都不一樣
link |
01:54.000
就是第一個APOC
link |
01:55.000
我們分這樣子的Batch
link |
01:57.000
第二個APOC會重新再分一次Batch
link |
01:59.000
所以哪些資料在同一個Batch裡面
link |
02:02.000
每一個APOC都不一樣的這件事情
link |
02:04.000
叫做Shuffle
link |
02:06.000
那剛才助教程式裡面
link |
02:07.000
其實也有提到Shuffle這件事情
link |
02:11.000
好,再來的問題就是
link |
02:13.000
為什麼要用Batch呢
link |
02:14.000
我們先解釋為什麼要用Batch
link |
02:16.000
再說Batch的Training帶來了什麼樣的幫助
link |
02:21.000
為什麼要用Batch呢
link |
02:22.000
我們來比較左右兩邊這兩個Case
link |
02:26.000
那假設現在我們有20筆訓練資料
link |
02:30.000
然後呢
link |
02:31.000
左邊的Case就是沒有用Batch
link |
02:34.000
或者是說我的Batch Size
link |
02:36.000
直接設的跟我訓練資料一樣多
link |
02:38.000
這種狀況啊
link |
02:39.000
叫做All Batch
link |
02:41.000
或者是沒有用Batch的意思啦
link |
02:44.000
那右邊的Case就是Batch Size等於1
link |
02:47.000
這是兩個最極端的狀況
link |
02:50.000
我們先來看左邊的Case
link |
02:52.000
在左邊的Case裡面
link |
02:53.000
因為沒有用Batch
link |
02:54.000
我們有20筆訓練資料
link |
02:56.000
我們的Model
link |
02:57.000
我們的程式必須把20筆訓練資料都看完
link |
03:00.000
才能夠計算Loss
link |
03:03.000
才能夠計算Gradient
link |
03:06.000
所以我們必須要把所有的Example
link |
03:09.000
也就是20筆Example都看完以後
link |
03:11.000
我們的Model參數才能夠Update一次
link |
03:15.000
就假設開始的地方在這邊
link |
03:16.000
把所有資料都看完以後
link |
03:18.000
Update參數就從這裡移動到這裡
link |
03:22.000
那如果是一個Batch的話會怎麼樣呢
link |
03:25.000
如果是一個Batch
link |
03:26.000
如果Batch Size等於1的話
link |
03:28.000
代表我們每次Update參數的時候
link |
03:30.000
我們只要看一筆資料就好
link |
03:32.000
Batch Size等於1
link |
03:33.000
代表我們只需要拿一筆資料出來算Loss
link |
03:36.000
我們就可以Update我們的參數
link |
03:39.000
所以每次我們Update參數的時候
link |
03:41.000
看一筆資料就好
link |
03:43.000
所以我們開始的點在這邊
link |
03:45.000
看一筆資料就Update一次參數
link |
03:47.000
再看一筆資料就Update一次參數
link |
03:49.000
再看一筆資料就Update一次參數
link |
03:51.000
如果今天總共有20筆資料的話
link |
03:54.000
那在一個Apple裡面
link |
03:56.000
我們的參數會Update20次
link |
04:00.000
那不過因為我們現在是只看一筆資料
link |
04:03.000
就Update一次參數
link |
04:05.000
所以用一筆資料算出來的Loss
link |
04:07.000
顯然是比較Noisy的
link |
04:09.000
所以我們今天Update的方向
link |
04:11.000
你會發現它是曲曲折折的
link |
04:14.000
所以如果我們比較左邊跟右邊
link |
04:16.000
哪一個比較好呢
link |
04:18.000
它們有什麼差別呢
link |
04:20.000
你會發現左邊這種方式
link |
04:22.000
沒有用Batch的方式
link |
04:24.000
它蓄力的時間比較長
link |
04:27.000
它技能冷卻的時間比較長
link |
04:30.000
你要把所有的資料都看過一遍
link |
04:32.000
才能夠Update一次參數
link |
04:34.000
而右邊的這個方法
link |
04:36.000
Batch Size等於1的時候
link |
04:38.000
蓄力的時間比較短
link |
04:39.000
每次看到一筆參數
link |
04:41.000
每次看到一筆資料
link |
04:43.000
你就會更新一次你的參數
link |
04:46.000
所以今天假設2筆至10筆資料
link |
04:48.000
看完所有資料看過一遍
link |
04:50.000
你已經更新了20次的參數
link |
04:53.000
但是左邊這樣子的方法有一個優點
link |
04:56.000
就是它這一步走的是穩的
link |
04:58.000
那右邊這個方法它的缺點
link |
05:00.000
就是它每一步走的是不穩的
link |
05:03.000
左邊跟右邊到底哪邊比較好呢
link |
05:06.000
看起來左邊的方法跟右邊的方法
link |
05:08.000
它們各自都有擅長跟不擅長的東西
link |
05:12.000
左邊是蓄力時間長
link |
05:15.000
但是威力比較大
link |
05:16.000
右邊技能冷卻時間短
link |
05:19.000
但是它是比較不準的
link |
05:21.000
它是亂槍打鳥型的
link |
05:23.000
到底誰比較好呢
link |
05:25.000
看起來各自有各自的優缺點
link |
05:29.000
但是你會覺得說
link |
05:31.000
左邊的方法技能冷卻時間長
link |
05:34.000
右邊的方法技能冷卻時間短
link |
05:37.000
那只是你沒有考慮平行運算而已
link |
05:40.000
實際上考慮平行運算的話
link |
05:43.000
左邊這個並不一定時間比較長
link |
05:48.000
怎麼說呢
link |
05:50.000
這邊是真正的實驗結果
link |
05:54.000
事實上比較大的Batch Size
link |
05:57.000
你要算Loss
link |
05:59.000
再進而算Gradient
link |
06:01.000
所需要的時間
link |
06:02.000
不一定比小的Batch Size
link |
06:05.000
要花的時間長
link |
06:07.000
以下是做在一個
link |
06:09.000
叫做Amnesty的Compass上面
link |
06:11.000
Amnesty是手寫數字辨識的Compass
link |
06:15.000
就是機器要做的事情
link |
06:16.000
就是給它一張圖片
link |
06:17.000
然後判斷這張圖片
link |
06:18.000
是0到9的哪一個數字
link |
06:21.000
才要做數字的分類
link |
06:24.000
Amnesty是機器學習的果蠅
link |
06:27.000
假設你今天
link |
06:29.000
從來沒有做過機器學習的任務
link |
06:31.000
一般大家第一個會嘗試的
link |
06:32.000
機器學習的任務
link |
06:33.000
往往就是做Amnesty
link |
06:34.000
做手寫數字辨識
link |
06:36.000
這邊我們就是做了一個實驗
link |
06:38.000
我們想要知道說
link |
06:40.000
給機器一個Batch
link |
06:42.000
它要計算出Gradient進了Update參數
link |
06:45.000
到底需要花多少的時間
link |
06:48.000
這邊列出了Batch Size
link |
06:50.000
等於1 等於10 等於100 等於1000
link |
06:53.000
所需要耗費的時間
link |
06:55.000
你會發現說Batch Size
link |
06:58.000
從1到1000
link |
07:00.000
需要耗費的時間
link |
07:02.000
幾乎是一樣的
link |
07:04.000
為什麼呢
link |
07:05.000
你可能會說直覺上有1000筆資料
link |
07:07.000
那需要計算Loss
link |
07:09.000
然後計算Gradient花的時間
link |
07:10.000
不會是一筆資料的1000倍嗎
link |
07:12.000
但是實際上並不是這樣的
link |
07:14.000
因為在實際上做運算的時候
link |
07:16.000
我們有GPU
link |
07:18.000
你可以做平行運算
link |
07:20.000
所以因為你可以做平行運算的關係
link |
07:22.000
這1000筆資料是平行處理的
link |
07:25.000
所以1000筆資料所花的時間
link |
07:27.000
並不是一筆資料的1000倍
link |
07:30.000
當然GPU平行運算的能力
link |
07:33.000
還是有它的極限
link |
07:35.000
當你的Batch Size
link |
07:36.000
真的非常非常巨大的時候
link |
07:38.000
GPU在跑完一個Batch
link |
07:41.000
計算出Gradient所花費的時間
link |
07:43.000
還是會隨著Batch Size的增加
link |
07:46.000
而逐漸增長
link |
07:48.000
所以今天如果Batch Size
link |
07:50.000
是從1到1000
link |
07:52.000
所需要的時間幾乎是一樣的
link |
07:54.000
但是當你的Batch Size增加到1萬
link |
07:57.000
乃至增加到6萬的時候
link |
07:59.000
你就會發現
link |
08:00.000
GPU要算完一個Batch
link |
08:02.000
把這個Batch裡面的資料都拿出來
link |
08:04.000
算Loss再進而算Gradient
link |
08:06.000
所要耗費的時間
link |
08:07.000
確實有隨著Batch Size的增加
link |
08:10.000
而逐漸增長
link |
08:12.000
但你會發現這邊用的是V100
link |
08:14.000
所以它挺厲害的
link |
08:16.000
給它6萬筆資料
link |
08:18.000
Batch裡面塞了6萬筆資料
link |
08:21.000
它在10秒鐘之內
link |
08:22.000
也是把Gradient就算出來
link |
08:25.000
Batch Size的大小跟時間的關係
link |
08:28.000
其實每年都會做這個實驗
link |
08:30.000
我特別把舊的投影片放在這邊
link |
08:32.000
如果你有興趣的話可以看一下
link |
08:34.000
可以看到什麼呢
link |
08:35.000
可以看到時代的演進
link |
08:38.000
17年的時候用的是980
link |
08:41.000
2015年的時候用的是760
link |
08:44.000
980要跑6萬個Batch
link |
08:46.000
跑幾分鐘才跑得完
link |
08:48.000
現在只要10秒鐘就可以跑得完了
link |
08:50.000
可以看到這個時代的演進
link |
08:54.000
所以GPU雖然有平行運算的能力
link |
08:56.000
但它平行運算能力終究是有個極限
link |
08:58.000
所以你Batch Size真的很大的時候
link |
09:00.000
時間還是會增加的
link |
09:04.000
但是因為有平行運算的能力
link |
09:06.000
因此實際上
link |
09:08.000
當你的Batch Size小的時候
link |
09:10.000
你要跑完一個Apple
link |
09:12.000
花的時間是大的Batch Size
link |
09:15.000
是比大的Batch Size還要多的
link |
09:17.000
怎麼說呢
link |
09:19.000
如果今天假設我們的訓練資料
link |
09:21.000
只有6萬筆
link |
09:23.000
Batch Size1
link |
09:25.000
那你要6萬個Update才能跑完一個Apple
link |
09:27.000
如果今天是Batch Size等於1000
link |
09:30.000
你要60個Update才能跑完一個Apple
link |
09:33.000
假設今天一個Batch Size等於1000
link |
09:37.000
要算規定的時間根本差不多
link |
09:39.000
那6萬次Update跟60次Update比起來
link |
09:43.000
它的時間的差距量就非常可觀
link |
09:46.000
所以左邊這個圖是Update一次參數
link |
09:50.000
拿一個Batch出來計算一個規定
link |
09:52.000
Update一次參數所需要的時間
link |
09:54.000
右邊這個圖是
link |
09:56.000
跑完一個完整的Apple
link |
09:59.000
需要花的時間
link |
10:00.000
你會發現左邊的圖跟右邊的圖
link |
10:02.000
它的趨勢正好是相反的
link |
10:04.000
假設你Batch Size1
link |
10:06.000
跑完一個Apple
link |
10:08.000
你要Update6萬次參數
link |
10:09.000
它的時間是非常可觀的
link |
10:11.000
但是假設你的Batch Size1000
link |
10:14.000
你只要跑60次Update
link |
10:16.000
60次參數就會跑完一個Apple
link |
10:18.000
所以你跑完一個Apple
link |
10:19.000
看完所有資料的時間
link |
10:21.000
如果你的Batch Size1000
link |
10:23.000
其實是比較短的
link |
10:24.000
比Batch Size1000的時候
link |
10:26.000
把所有資料看過一遍
link |
10:27.000
其實是比Batch Size1還要更快
link |
10:31.000
所以如果我們看右邊這個圖的話
link |
10:33.000
看完一個Batch
link |
10:34.000
把所有資料看過一次這件事情
link |
10:37.000
大的Batch Size反而是比較有效率的
link |
10:41.000
是不是跟你直覺想的不太一樣
link |
10:43.000
在沒有考慮平行運算的時候
link |
10:45.000
你覺得大的Batch比較慢
link |
10:47.000
但實際上在有考慮平行運算的時候
link |
10:50.000
一個Apple大的Batch花的時間
link |
10:53.000
反而是比較少的
link |
10:56.000
所以這邊我們如果要比較
link |
10:59.000
這個Batch Size大小的差異的話
link |
11:02.000
看起來直接用技能時間冷卻的長短
link |
11:05.000
並不是一個精確的描述
link |
11:08.000
看起來在技能時間上面
link |
11:11.000
大的Batch並沒有比較吃虧
link |
11:13.000
甚至還佔到優勢了
link |
11:17.000
所以事實上呢
link |
11:18.000
這邊Update一次的時間
link |
11:20.000
20筆資料Update一次的時間
link |
11:22.000
跟這邊看1筆資料Update一次的時間
link |
11:24.000
如果你用GPU的話
link |
11:26.000
其實可能根本就是一樣的
link |
11:28.000
所以大的Batch它的技能時間
link |
11:30.000
它的技能冷卻的時間
link |
11:32.000
並沒有比較長
link |
11:34.000
所以這時候你可能就會說
link |
11:36.000
那個大的Batch的劣勢消失了
link |
11:39.000
難道它真的就這樣看起來
link |
11:41.000
大的Batch應該比較好了喔
link |
11:42.000
你不是說大的Batch
link |
11:43.000
這個Update比較穩定
link |
11:45.000
小的Batch
link |
11:46.000
它的Gradient的方向比較Noisy嗎
link |
11:49.000
那這樣看起來
link |
11:50.000
大的Batch好像應該比較好喔
link |
11:52.000
小的Batch應該比較差喔
link |
11:54.000
因為現在大的Batch的劣勢
link |
11:55.000
已經因為平行運算被拿掉了
link |
11:57.000
它好像只剩下優勢而已
link |
12:00.000
那神奇的地方是
link |
12:02.000
Noisy的Gradient
link |
12:04.000
反而可以幫助全體
link |
12:07.000
這個也是跟直覺正好相反的
link |
12:10.000
如果你今天拿不同的Batch
link |
12:12.000
來訓練你的模型
link |
12:14.000
你可能會得到這樣子的結果
link |
12:17.000
左邊是坐在Amnesty上
link |
12:19.000
右邊是坐在Cypher10上
link |
12:22.000
不管是Amnesty還是Cypher10
link |
12:24.000
都是影像辨識的問題
link |
12:27.000
那橫軸代表的是Batch Size
link |
12:31.000
從左到右越來越大
link |
12:33.000
縱軸代表的是正確率
link |
12:35.000
越上面正確率越高
link |
12:37.000
當然正確率越高越好
link |
12:39.000
如果你今天看Validation Set上的結果
link |
12:42.000
如果你今天看Validation Set上的結果
link |
12:47.000
會發現說Batch Size越大
link |
12:50.000
Validation Set上的結果越差
link |
12:52.000
但這個是Overfitting嗎
link |
12:55.000
這個不是Overfitting
link |
12:58.000
因為如果你看你的Trending的話
link |
13:00.000
會發現Batch Size越大
link |
13:02.000
Trending的結果也是越差的
link |
13:06.000
而我們現在用的是同一個模型
link |
13:09.000
同一個模型同一個Network
link |
13:11.000
照理說他們可以表示的Function
link |
13:13.000
就是一模一樣的
link |
13:15.000
但神奇的事情是大的Batch Size
link |
13:18.000
往往在Trending的時候
link |
13:20.000
會給你帶來比較差的結果
link |
13:23.000
所以這個是什麼樣的問題
link |
13:26.000
同樣的Model
link |
13:28.000
所以這個不是Model Bias的問題
link |
13:31.000
這個是Optimization的問題
link |
13:34.000
代表當你用大的Batch Size的時候
link |
13:36.000
你的Optimization可能會有問題
link |
13:39.000
小的Batch Size
link |
13:40.000
Optimization的結果反而是比較好的
link |
13:44.000
為什麼會這樣子呢
link |
13:46.000
為什麼小的Batch Size
link |
13:48.000
在Trending Set上會得到比較好的結果
link |
13:50.000
為什麼Noisy的Update
link |
13:52.000
Noisy的Gradient
link |
13:53.000
會在Trending的時候
link |
13:55.000
給我們比較好的結果呢
link |
13:57.000
一個可能的解釋是這樣子的
link |
13:59.000
假設你是Full Batch
link |
14:01.000
那你今天在Update你的參數的時候
link |
14:04.000
你就是沿著一個Loss Function
link |
14:06.000
來Update參數
link |
14:08.000
那今天Update參數的時候
link |
14:09.000
走到一個Local Minimum
link |
14:10.000
走到一個Settle Point
link |
14:12.000
顯然就停下來了
link |
14:13.000
Gradient這裡
link |
14:14.000
如果你不特別去看Hessian的話
link |
14:15.000
那你用Gradient Descent的方法
link |
14:17.000
你就沒有辦法再更新你的參數了
link |
14:21.000
但是假如是Small Batch的話
link |
14:23.000
假如沒有用Batch的話
link |
14:24.000
會發生什麼事呢
link |
14:26.000
因為我們每次是挑一個Batch出來
link |
14:28.000
算它的Loss
link |
14:29.000
所以等於你每次Update
link |
14:31.000
你的參數的時候
link |
14:32.000
你用的Loss Function
link |
14:34.000
都是略有差異的
link |
14:36.000
你選到第一個Batch的時候
link |
14:38.000
你是用L1來算你的Gradient
link |
14:41.000
你選到第二個Batch的時候
link |
14:43.000
你是用L2來算你的Gradient
link |
14:45.000
假設你用L1算Gradient的時候
link |
14:47.000
發現Gradient是零
link |
14:48.000
卡住了
link |
14:49.000
但L2它的Function跟L1又不一樣
link |
14:53.000
所以L1卡住了
link |
14:54.000
L2不一定會卡住啊
link |
14:56.000
所以L1卡住了
link |
14:57.000
沒關係
link |
14:58.000
換下一個Batch來
link |
14:59.000
L2再算Gradient
link |
15:01.000
你還是有辦法Train你的Model
link |
15:03.000
你可能還是有辦法
link |
15:04.000
讓你的Loss變小
link |
15:06.000
所以今天這種Noisy的Update方式
link |
15:09.000
結果反而對Training
link |
15:11.000
其實是有幫助的
link |
15:15.000
那這邊還有另外一個
link |
15:17.000
更神奇的事情
link |
15:19.000
那這個神奇的事情是什麼呢
link |
15:21.000
這個神奇的事情是
link |
15:23.000
其實小的Batch
link |
15:25.000
也對Testing有幫助
link |
15:29.000
假設我們今天在Training的時候
link |
15:32.000
不管是大的Batch還是小的Batch
link |
15:34.000
都Train到一樣好
link |
15:35.000
剛才的Case是Training的時候
link |
15:36.000
就已經Train不好了
link |
15:37.000
那假設你有一些方法
link |
15:39.000
你努力的調大的Batch的Learning Rate
link |
15:42.000
然後想辦法把大的Batch
link |
15:44.000
跟小的BatchTrain得一樣好
link |
15:46.000
結果你會發現
link |
15:47.000
小的Batch居然在Testing的時候
link |
15:49.000
會是比較好的
link |
15:51.000
那以下這個實驗結果
link |
15:53.000
是引用自
link |
15:54.000
On Large Batch Training for Deep Learning Durization Gap
link |
15:57.000
and Sharp Minimum
link |
15:58.000
這篇Paper的實驗結果
link |
16:00.000
那這篇Paper裡面呢
link |
16:01.000
作者Train了六個Network
link |
16:04.000
裡面有CNN的
link |
16:05.000
有Fully Connected Feedforward Network的
link |
16:08.000
然後做在不同Codec上
link |
16:09.000
來代表說
link |
16:10.000
這個實驗是很泛用的
link |
16:13.000
在很多不同的Case
link |
16:15.000
都觀察到一樣的結果
link |
16:16.000
那它有小的Batch
link |
16:18.000
一個Batch裡面有256名Sample
link |
16:20.000
大的Batch就是Dataset乘0.1
link |
16:24.000
Dataset乘0.1
link |
16:26.000
Dataset有6萬筆
link |
16:27.000
就是一個Batch
link |
16:28.000
裡面有6000筆資料
link |
16:30.000
然後他想辦法
link |
16:32.000
在大的Batch跟小的Batch
link |
16:34.000
都Train到差不多的
link |
16:36.000
Training Accuracy
link |
16:38.000
所以剛才我們看到的結果是
link |
16:40.000
Batch Size大的時候
link |
16:41.000
Training Accuracy就已經差掉了
link |
16:43.000
跟不是
link |
16:44.000
想辦法Train到大的Batch的時候
link |
16:46.000
Training Accuracy跟小的Batch
link |
16:48.000
其實是差不多的
link |
16:51.000
但是就算是在Training的時候
link |
16:53.000
結果差不多
link |
16:54.000
Testing的時候
link |
16:55.000
你還是看到了
link |
16:57.000
小的Batch居然比大的Batch差
link |
17:00.000
Training的時候都很好
link |
17:02.000
Testing的時候
link |
17:03.000
小的Batch差
link |
17:04.000
那代表什麼
link |
17:05.000
代表Overfitting
link |
17:07.000
這個才是Overfitting
link |
17:10.000
對不對
link |
17:12.000
link |
17:13.000
那為什麼會有這樣子的現象呢
link |
17:16.000
在這篇文章裡面
link |
17:18.000
也給出了一個解釋
link |
17:20.000
他的解釋是這個樣子的
link |
17:22.000
假設這個是我們的Training Loss
link |
17:25.000
那在這個Training Loss上面
link |
17:27.000
可能有很多個Local Minima
link |
17:31.000
有不止一個Local Minima
link |
17:33.000
那這些Local Minima
link |
17:34.000
他們的Loss都很低
link |
17:36.000
他們Loss可能都趨近於0
link |
17:38.000
但是這個Local Minima
link |
17:40.000
還是有好Minima跟壞Minima之分
link |
17:43.000
什麼叫做好Minima跟壞Minima呢
link |
17:46.000
我們會認為
link |
17:48.000
如果一個Local Minima
link |
17:49.000
他在一個峽谷裡面
link |
17:51.000
他是壞的Minima
link |
17:54.000
然後他在一個平原上
link |
17:57.000
他是好的Minima
link |
17:59.000
為什麼會有這樣的差異呢
link |
18:01.000
因為假設現在Training跟Testing中間
link |
18:04.000
有一個MixMatch
link |
18:06.000
Training的Loss跟Testing的Loss
link |
18:08.000
他們那個Function不一樣
link |
18:09.000
為什麼會不一樣呢
link |
18:10.000
有可能是
link |
18:12.000
本來Training跟Testing的Distribution
link |
18:14.000
就不一樣
link |
18:15.000
也有可能是
link |
18:16.000
因為Training跟Testing
link |
18:18.000
你都是從Sample的Data算出來的
link |
18:21.000
也許Training跟Testing
link |
18:22.000
Sample到的Data不一樣
link |
18:24.000
所以他們算出來的Loss
link |
18:26.000
當然是有一點差距
link |
18:28.000
那我們就假設
link |
18:29.000
這個Training跟Testing
link |
18:30.000
他的差距就是
link |
18:31.000
把Training的Loss這個Function
link |
18:33.000
往右比一點
link |
18:35.000
這個時候你會發現
link |
18:36.000
對左邊這個Minima來說
link |
18:39.000
對這個在一個盆地裡面的Minima來說
link |
18:42.000
他的
link |
18:44.000
在Training跟Testing上面的結果
link |
18:45.000
不會差太多
link |
18:46.000
只差了一點點
link |
18:48.000
但是對右邊這個
link |
18:49.000
在峽谷裡面的Minima來說
link |
18:51.000
一差就可以天差地遠
link |
18:54.000
他在這個Training Set上
link |
18:57.000
算出來的Loss很低
link |
18:58.000
但是因為Training跟Testing之間的不一樣
link |
19:01.000
所以Testing的時候
link |
19:02.000
這個Error Surface一變
link |
19:05.000
他算出來的Loss就變得很大
link |
19:08.000
而很多人相信說
link |
19:12.000
大的Batch Size
link |
19:14.000
會讓我們傾向於走到峽谷裡面
link |
19:18.000
而小的Batch Size
link |
19:19.000
傾向於讓我們走到盆地裡面
link |
19:23.000
他直覺上的想法是這樣
link |
19:25.000
就是小的Batch
link |
19:27.000
他有很多的Noise
link |
19:30.000
他每次Update的方向都不太一樣
link |
19:32.000
所以如果今天這個峽谷非常的窄
link |
19:35.000
他可能一個不小心就跳出去了
link |
19:38.000
因為每次Update的方向都不太一樣
link |
19:40.000
他的Update的方向有些隨機性
link |
19:42.000
所以一個很小的峽谷
link |
19:43.000
沒有辦法困住小的Batch
link |
19:46.000
如果峽谷很小
link |
19:47.000
他可能動一下就跳出去了
link |
19:49.000
之後停下來
link |
19:50.000
如果有一個非常寬的盆地
link |
19:52.000
他才會停下來
link |
19:54.000
那對於大的Batch Size
link |
19:56.000
反正他就是順著Gradient Update
link |
19:58.000
他就很有可能走到一個
link |
20:00.000
比較小的峽谷裡面
link |
20:04.000
但這只是一個解釋啦
link |
20:06.000
也不是每個人都相信這個解釋
link |
20:11.000
那這個其實還是一個
link |
20:12.000
上一代可以研究的問題
link |
20:17.000
那這邊就是比較了一下
link |
20:18.000
大的Batch跟小的Batch
link |
20:21.000
左邊這個是第一個Column
link |
20:22.000
是小的Batch
link |
20:23.000
第二個Column是大的Batch
link |
20:25.000
如果在沒有平行預設的情況下
link |
20:27.000
我們會覺得小的Batch比較有效
link |
20:30.000
大的Batch
link |
20:31.000
一個Batch的時間要算得比較長
link |
20:33.000
但是在有平行運算的情況下
link |
20:35.000
小的Batch跟大的Batch
link |
20:36.000
其實運算的時間
link |
20:38.000
並沒有太大的差距
link |
20:40.000
除非你的大的Batch
link |
20:41.000
那個大是真的非常大
link |
20:43.000
才會顯示出差距來
link |
20:45.000
但是一個APOC需要的時間
link |
20:48.000
小的Batch比較長
link |
20:49.000
大的Batch反而是比較快的
link |
20:52.000
所以從一個APOC需要的時間來看
link |
20:55.000
大的Batch其實是占到優勢的
link |
20:58.000
而小的Batch
link |
20:59.000
你會Update的方向比較Noisy
link |
21:02.000
大的BatchUpdate的方向比較穩定
link |
21:05.000
但是Noisy的Update的方向
link |
21:07.000
反而在Optimization的時候
link |
21:10.000
會占到優勢
link |
21:11.000
而且在Testing的時候
link |
21:14.000
也會占到優勢
link |
21:16.000
所以大的Batch跟小的Batch
link |
21:18.000
他們各自有他們擅長的地方
link |
21:21.000
所以Batch Size
link |
21:22.000
變成另外一個Hyperparameter
link |
21:24.000
這個Hyperparameter
link |
21:26.000
是你需要去調它的
link |
21:29.000
這個也是一個你需要去調整的
link |
21:32.000
Hyperparameter
link |
21:34.000
講到這邊有人就會想說
link |
21:35.000
那我們能不能夠魚與熊掌兼得呢
link |
21:39.000
我們能不能夠
link |
21:40.000
擷取大的Batch的優點
link |
21:42.000
跟小的Batch的優點
link |
21:44.000
我們用大的Batch Size來做訓練
link |
21:47.000
用平行運算的能力
link |
21:48.000
來增加訓練的效率
link |
21:50.000
但是訓練出來的結果
link |
21:51.000
同時又得到好的結果呢
link |
21:54.000
又得到好的訓練結果呢
link |
21:56.000
這是有可能的
link |
21:58.000
有很多文章都在探討這個問題
link |
22:01.000
那今天我們就不細講
link |
22:03.000
我們把一些Reference
link |
22:04.000
列在這邊給大家參考
link |
22:05.000
大家發現這些Paper
link |
22:06.000
往往他想要做的事情
link |
22:07.000
就是什麼
link |
22:08.000
76分鐘Train Bird
link |
22:10.000
15分鐘Train ResNet
link |
22:11.000
1分鐘Train ImageNet等等
link |
22:13.000
為什麼他們可以做到那麼快
link |
22:15.000
就是因為他們Batch Size
link |
22:16.000
是真的開很大
link |
22:18.000
比如說在第一篇Paper裡面
link |
22:20.000
Batch Size裡面有3萬筆
link |
22:22.000
Example這樣
link |
22:23.000
Batch Size開很大
link |
22:24.000
Batch Size太大
link |
22:25.000
你真的就可以算很快
link |
22:27.000
你可以在很短的時間內
link |
22:28.000
看到大量的資料
link |
22:29.000
那他們需要有一些特別的方法
link |
22:32.000
來解決Batch Size
link |
22:34.000
可能會帶來的劣勢
link |
22:38.000
那最後想要跟大家
link |
22:39.000
在下課前想要跟大家分享的
link |
22:41.000
另外一個技術是Momentum
link |
22:44.000
這也是另外一個
link |
22:45.000
有可能可以對抗Satellite Point
link |
22:48.000
或Local Minima的技術
link |
22:50.000
這個Momentum是怎麼運作的呢
link |
22:52.000
Momentum的運作是這個樣子的
link |
22:54.000
它的概念
link |
22:56.000
你可以想像成
link |
22:57.000
在物理的世界裡面
link |
22:59.000
假設Aero Surface
link |
23:01.000
就是真正的斜坡
link |
23:03.000
而我們的參數是一個球
link |
23:05.000
你把球從斜坡上滾下來
link |
23:07.000
如果今天是Gradient Descent
link |
23:09.000
它走到Local Minima就停住了
link |
23:11.000
走到Satellite Point就停住了
link |
23:13.000
但是在物理的世界裡面
link |
23:15.000
一個球會這樣子嗎
link |
23:16.000
一個球如果從高處滾下來
link |
23:18.000
從高處滾下來
link |
23:19.000
就算滾到Satellite Point
link |
23:21.000
如果有慣性
link |
23:23.000
它從左邊滾下來
link |
23:24.000
因為慣性的慣性
link |
23:25.000
它還是會繼續往右走
link |
23:27.000
甚至它走到一個Local Minima
link |
23:29.000
如果今天它的動量夠大的話
link |
23:32.000
它還是會繼續往右走
link |
23:34.000
甚至翻過這個小坡
link |
23:35.000
然後繼續往右走
link |
23:37.000
所以今天在物理的世界裡面
link |
23:40.000
一個球從高處滾下來的時候
link |
23:42.000
它並不會被Satellite Point
link |
23:43.000
或Local Minima卡住
link |
23:45.000
不一定會被Satellite Point
link |
23:46.000
或Local Minima卡住
link |
23:48.000
我們有沒有辦法
link |
23:49.000
運用這樣子的概念
link |
23:50.000
到Gradient Descent裡面呢
link |
23:52.000
這個就是我們等一下要講的
link |
23:55.000
Momentum這個技術
link |
23:58.000
那我們先很快的複習一下
link |
24:00.000
原來的Gradient Descent
link |
24:01.000
長的是什麼樣子
link |
24:02.000
這個是Vanilla的Gradient Descent
link |
24:04.000
Vanilla的意思就是
link |
24:06.000
一般的的意思
link |
24:08.000
它直譯是香草的
link |
24:09.000
但就是一般的
link |
24:10.000
一般的Gradient Descent
link |
24:11.000
長什麼樣子呢
link |
24:12.000
一般的Gradient Descent是說
link |
24:14.000
我們有一個初始的參數
link |
24:16.000
叫做Satellite Point
link |
24:17.000
我們計算一下Gradient
link |
24:20.000
然後計算完這個Gradient以後呢
link |
24:22.000
我們往Gradient的反方向
link |
24:25.000
去Update參數
link |
24:27.000
我們到了新的參數以後
link |
24:29.000
再計算一次Gradient
link |
24:30.000
再往Gradient的反方向
link |
24:32.000
再Update一次參數
link |
24:33.000
到了新的位置以後
link |
24:34.000
再計算一次Gradient
link |
24:35.000
再往Gradient的反方向
link |
24:36.000
去Update參數
link |
24:37.000
這個Process就一直這樣子下去
link |
24:42.000
那如果加上Momentum的話
link |
24:45.000
會是什麼樣子呢
link |
24:46.000
加上Momentum以後
link |
24:47.000
Gradient Descent變成這個樣子
link |
24:49.000
每一次我們在移動
link |
24:50.000
我們的參數的時候
link |
24:51.000
我們不是只往Gradient Descent
link |
24:54.000
我們不是只往Gradient的
link |
24:56.000
反方向來移動參數
link |
24:58.000
在一般的Gradient Descent裡面
link |
25:00.000
我們都是往Gradient的
link |
25:01.000
反方向去移動參數
link |
25:02.000
但現在不只往Gradient的
link |
25:03.000
反方向去移動參數
link |
25:05.000
我們是Gradient的反方向
link |
25:07.000
加上前一步移動的方向
link |
25:10.000
兩者加起來的結果
link |
25:12.000
去調整去移動我們的參數
link |
25:16.000
那具體說起來是這個樣子
link |
25:18.000
一樣找一個初始的參數
link |
25:21.000
然後我們假設在一開始的時候
link |
25:25.000
前一步的變化量
link |
25:28.000
前一步的參數的Update量
link |
25:31.000
就設為0
link |
25:33.000
那接下來在Theta0的地方
link |
25:36.000
你要計算G0
link |
25:38.000
計算G0
link |
25:39.000
計算Gradient的方向
link |
25:41.000
然後接下來你要決定
link |
25:43.000
下一步要怎麼走
link |
25:45.000
那我們說下一步要怎麼走呢
link |
25:47.000
它是Gradient的方向
link |
25:49.000
加上前一步的方向
link |
25:51.000
不過因為前一步正好是0
link |
25:53.000
現在是剛初始的時候
link |
25:54.000
所以前一步是0
link |
25:56.000
所以Update的方向
link |
25:57.000
跟原來的Gradient Descent是一樣的
link |
26:00.000
這沒有什麼有趣的地方
link |
26:01.000
但從第二步開始
link |
26:02.000
有加上Momentum以後
link |
26:04.000
就不太一樣了
link |
26:06.000
從第二步開始
link |
26:07.000
我們計算G1
link |
26:10.000
然後接下來我們Update的方向
link |
26:12.000
不是G1的反方向
link |
26:14.000
而是根據上一次Update的方向
link |
26:18.000
也就是M1
link |
26:19.000
減掉G1
link |
26:21.000
當作我們新的Update的方向
link |
26:23.000
這邊寫成M2
link |
26:26.000
如果你看數學式子覺得有點模糊的話
link |
26:28.000
那我們就看左邊這個圖
link |
26:30.000
G1告訴我們
link |
26:31.000
Gradient告訴我們要往這邊走
link |
26:34.000
但是我們不是只聽Gradient的話
link |
26:36.000
加上Momentum以後
link |
26:37.000
我們不是只根據Gradient的反方向
link |
26:39.000
來調整我們的參數
link |
26:41.000
我們也會看前一次Update的方向
link |
26:45.000
如果前一次說要往這個方向走
link |
26:47.000
Gradient說要往這個方向走
link |
26:49.000
就把兩者相加起來
link |
26:51.000
走兩者的折衷
link |
26:53.000
也就是往這一個方向走
link |
26:56.000
所以我們就移動了M2
link |
26:59.000
走到Theta2這個地方
link |
27:01.000
接下來就反覆進行同樣的過程
link |
27:05.000
在這個位置我們計算出Gradient
link |
27:07.000
但我們不是只根據Gradient反方向走
link |
27:10.000
我們看前一步怎麼走的
link |
27:12.000
前一步走這個方向
link |
27:13.000
走這個藍色虛線的方向
link |
27:15.000
我們把藍色的虛線加紅色的虛線
link |
27:18.000
前一步指示的方向跟Gradient指示的方向
link |
27:21.000
當作我們下一步要移動的方向
link |
27:23.000
以此類推
link |
27:24.000
反覆進行同樣的操作
link |
27:26.000
Gradient在這個地方說要往這個方向走
link |
27:28.000
然後前一步說要往這個方向走
link |
27:30.000
兩者綜合起來
link |
27:31.000
就往左下走
link |
27:33.000
所以這個跟一般Gradient Design不一樣
link |
27:35.000
我們不是只看Gradient的方向
link |
27:37.000
來調整參數
link |
27:38.000
我們還會考慮之前移動的方向
link |
27:42.000
來調整參數
link |
27:44.000
這邊每一步的移動
link |
27:46.000
我們都用N來表示
link |
27:49.000
這個N其實可以寫成
link |
27:52.000
之前所有算出來的Gradient的Weight Design
link |
27:57.000
怎麼說呢
link |
27:58.000
從右邊的這個式子
link |
27:59.000
其實就可以輕易的看出來
link |
28:01.000
N0我們把它設為0
link |
28:04.000
N1是N0減掉G0
link |
28:08.000
N0為0
link |
28:09.000
所以N1就是G0乘上負的η
link |
28:14.000
N2呢
link |
28:15.000
N2是λ乘上N1
link |
28:17.000
λ就是另外一個參數
link |
28:19.000
就跟Learning Rate一樣是要調的
link |
28:21.000
η是Learning Rate我們要調
link |
28:23.000
λ也是另外一個參數
link |
28:24.000
這個也是需要調的
link |
28:26.000
N2等於λ乘上N1減掉η乘上G1
link |
28:30.000
然後N1在哪裡呢
link |
28:32.000
N1在這邊
link |
28:33.000
你把N1代進來
link |
28:34.000
就知道說N2等於負的λ乘上η乘上G0
link |
28:38.000
減掉η乘上G1
link |
28:41.000
它是G0跟G1的Weight Design
link |
28:43.000
以此類推
link |
28:44.000
所以你會發現說
link |
28:45.000
這個加上Momentum以後
link |
28:48.000
一個解讀是Momentum是
link |
28:50.000
Gradient的負反方向
link |
28:52.000
加上前一次移動的方向
link |
28:55.000
但另外一個解讀方式是
link |
28:56.000
所謂的Momentum
link |
28:58.000
當加上Momentum的時候
link |
29:00.000
我們Update的方向
link |
29:01.000
不是只考慮現在的Gradient
link |
29:03.000
而是考慮過去所有Gradient的綜合
link |
29:09.000
那假設你這邊也沒有聽得很懂的話
link |
29:13.000
那這邊有一個更簡單的例子
link |
29:15.000
希望幫助你了解Momentum是怎麼回事
link |
29:19.000
那我們從這個地方開始Update參數
link |
29:23.000
根據Gradient的方向告訴我們
link |
29:25.000
應該往右Update參數
link |
29:27.000
那現在沒有前一次Update的方向
link |
29:29.000
所以我們就完全按照Gradient
link |
29:30.000
給我們的指示往右移動參數
link |
29:33.000
那我們的參數就往右移動了一點
link |
29:35.000
到這個地方
link |
29:36.000
Gradient變得很小
link |
29:38.000
告訴我們往右移動
link |
29:39.000
但是只有往右移動一點點
link |
29:41.000
那前一步是往右移動的
link |
29:43.000
我們把前一步的方向
link |
29:44.000
用虛線來表示放在這個地方
link |
29:47.000
我們把之前Gradient
link |
29:48.000
告訴我們要走的方向
link |
29:49.000
跟前一步移動的方向加起來
link |
29:51.000
得到往右走的方向
link |
29:53.000
那再往右走
link |
29:54.000
走到一個Local Minimum
link |
29:56.000
照理說走到Local Minimum
link |
29:58.000
一般Gradient Design
link |
29:59.000
無法向前走了
link |
30:00.000
因為已經沒有Gradient的方向
link |
30:03.000
那走到Settle Point也一樣
link |
30:05.000
沒有Gradient的方向
link |
30:06.000
已經無法向前走了
link |
30:08.000
但沒有關係
link |
30:09.000
如果有Momentum的話
link |
30:10.000
你還是有辦法繼續走下去
link |
30:12.000
因為Momentum不是只看Gradient
link |
30:14.000
Gradient就算是0
link |
30:16.000
你還有前一步的方向
link |
30:18.000
前一步的方向告訴我們向右走
link |
30:20.000
我們就繼續向右走
link |
30:22.000
甚至你走到這種地方
link |
30:24.000
Gradient告訴你應該要往左走了
link |
30:26.000
但是假設你前一步的影響力
link |
30:29.000
比Gradient要大的話
link |
30:31.000
你還是有可能繼續往右走
link |
30:33.000
甚至翻過一個小丘
link |
30:35.000
搞不好就可以走到
link |
30:36.000
更好的Local Minimum
link |
30:38.000
這個就是Momentum
link |
30:40.000
有可能帶來的好處
link |
30:44.000
那這個就是今天
link |
30:45.000
想要跟大家說的內容
link |
30:47.000
沒想到就講到6點20了
link |
30:49.000
我們在這邊就只好下課了
link |
30:51.000
謝謝大家 謝謝
link |
30:53.000
謝謝 謝謝