關於如何train出一個一樣的model
在進行深度學習建模時,我們經常會希望能夠重現之前train出來的結果。但由於神經網路的特性,透過不同的初始值會得到不同的結果。於是本篇是在說明如何固定初始值,以得到相同的結果。
Random Seed control
本文會介紹的固定初始值方法,是透過一個seed,也就是一個固定的常數來控制所有的隨機數的產生,進而控制模型的初始值,因為初始值也是一個隨機數。這種方法稱為Random Seed control。
之所以能夠做到Random Seed control,是因為在電腦裡我們說的隨機並不是真正的隨機。這些隨機數都只是透過一個隨機數產生器產生出來的數值,看似隨機的同時,是有跡可循且可以掌控的,控制隨機數產生器的鑰匙就是seed。
控制Keras模型的程式碼如下所示
# Seed value
# Apparently you may use different seed values at each stage
seed_value= 1# 1. Set the `PYTHONHASHSEED` environment variable at a fixed value
import os
os.environ['PYTHONHASHSEED']=str(seed_value)# 2. Set the `python` built-in pseudo-random generator at a fixed value
import random
random.seed(seed_value)# 3. Set the `numpy` pseudo-random generator at a fixed value
import numpy as np
np.random.seed(seed_value)# 4. Set the `tensorflow` pseudo-random generator at a fixed value
import tensorflow as tf
tf.compat.v1.set_random_seed(seed_value)
但是只要用Seed就會讓模型變好嗎?
並不是,seed只能保證實驗的重現性,但不代表實驗的效果會好。當然我們可以不斷的嘗試不同的seed值,直到找到相對好的答案,但他不會讓模型更聰明。如果要讓模型更聰明,可以使用Keras initializers。
Keras initializers和初始值
Keras內建有initializers方法,同樣可以用來固定初始值。但他是用來固定指定神經層的權重(weight)和偏移量(bias),而有些神經層是無法使用initializers的(例如:dropout),所以還是會導致每一次的結果都有不同。
但這並不代表Keras的initializers沒有意義。
Keras的initializers範例如下所示:
model.add(Dense(64, kernel_initializer='random_uniform', bias_initializer='zeros'))
可以看到我們針對一個Dense(標準神經層)的Kernel(其實就是weight)和bias做控制。
針對bias的控制(bias_initializer)相對單純。強迫該神經層所有神經元的bias的初始值為0,簡單而且粗暴,但這可以確保神經元在未受訓練前就有過高的bias進而促成他更容易對結果造成影響。
但我們可以仔細看看對於weight的控制(kernel_initializer),我們給與其的參數值是random_uniform,也就是隨機均勻分布,這是一種資料分布的形式。也就是我們強迫神經元權重的初始值服從於某一種分布。
我們能使用的資料分布當然不只一種,也包括RandomNormal、TruncatedNormal、VarianceScaling…等等。
而我們可以針對一個模型,使用不同的初始化資料分布來對模型進行控制,這能夠讓我們找出更佳的模型表現,這個差異在weight的初始化過程中差異會非常顯著。
下一次不知道模型要調整什麼的時候,可以嘗試不同的資料分布初始化。
Note:我目前還沒有找到一個理論可以說明什麼資料用什麼資料分布來初始化weight是最好的,對於深度學習內部的運作還是一個黑盒子,目前更常用結果反向假設與解釋、而非從理論出發推導解釋。
參考連結: