深度學習需要建立模型,建立的過程中常常會忽略某些細節以及語法,因此寫了一篇記錄方便自己未來查閱。
資料前處理
zero-padding
為了讓所有輸入序列的長度一致,zero-padding
設定MAX_SEQUENCE_LENGTH
作為容許的最大輸入長度,若長度超過此輸入序列的長度,爾後的資料會被刪掉;若長度不足輸入序列的長度,則在資料前面補零。
Keras內建有sequence.pad_sequences
函式協助我們做到zero-padding的功能
1 | X_train = keras.preprocessing.sequence.pad_sequences(train_data,maxlen=MAX_SEQUENCE_LENGTH) |
One-Hot Encoding
又稱作一位有效編碼,舉例來說,有一個分類長這樣:
1 | 烏龜: 1, 烏賊: 2, 老虎: 3 |
轉換後的好處是更有機率的概念,且特徵能夠擴張。
Keras內建有utils.to_categorical
函式協助我們做到One-Hot Encoding的功能
1 | Y_train = keras.utils.to_categorical(train_labels) |
<p.s> 用DataFrame做One-Hot Encoding
1
df = pd.DataFrame({'gender':['male','female','male','female'],'class':['Lion','Tiger','Fish','Tiger']})
pandas做One-Hot Encoding
1 | pd.get_dummies(df) |
選定某列作One-Hot Encoding
1 | pd.get_dummies(df.gender) |
如果今天資料長這樣,可以看到class
欄位裡有"/"
符號連結各種班級名稱,而我們希望將它切開來做One-Hot Encoding
1 | df['class'].str.get_dummies('/') |
切分訓練與測試資料
1 | from sklearn.model_selection import train_test_split |
模型建立
Define a set of function - Neural Network
Keras中有兩種建立模型的方式:
Sequential Model
:一種簡單的模型,單一輸入、單一輸出,按順序一層一層的由上往下執行。Functional API
:支援多個輸入、多個輸出
1. Sequential Model
1 | from keras.models import Sequential |
2. Functional API
1 | from keras.models import Model |
Input(輸入層)
1 | Input(shape=None, batch_size=None, name=None, dtype=None,...) |
shape
: tuple型態的輸入,不包含batch_size,ex:shape=(32,)
name
: 自己命名dtype
: 預期進入輸入層的資料型態
ex: Input(shape=(100,), dtype='int32', name='main_input')
Embedding(嵌入層)
1 | Embedding(input_dim, output_dim, input_length=None) |
- 詞嵌入,把維度展開,ex: [[4], [20]] -> [[0.25, 0.1], [0.6, -0.2]]
- 只能用在模型的第一層
Dense(全連接層)
1 | Dense(units, activation=None, ...) |
units
: 輸出的維度activation
: 預設None為線性
若Dense是輸入層,則要給定input_dim
or input_shape
,否則就會自動抓上一層的output當作這層的input
1 | model.add(Dense(32, input_dim=784)) |
1 | # Dense作為輸入層,輸入維度128,輸出維度256,活化函數為relu |
LSTM(長短期記憶網路層)
1 | LSTM(units, activation='tanh', recurrent_activation='hard_sigmoid', dropout=0.0 ...) |
units
: 輸出的維度activation
: 活化函數,預設None為線性dropout
: 丟棄比例,0~1
如果想要串接多層的LSTM,則前一層需要加上return_sequences=True
Dropout
1 | Dropout(rate) |
Dropout會在訓練中每次更新時,都以一定比例將輸入的神經元丟棄掉(設置為0),有助於防止over-fitting,尤其是LSTM更需要這個步驟。rate
: 0~1之間
Flatten
1 | Flatten() |
把輸入展開,不影響總神經元數量
模型編譯
Step2. Goodness of function - cross entropy (loss)
值得注意的是,cross entropy在Keras裏頭的寫法是
categorical_crossentropy
Step3. Pick the best function (optimizer、metrics)
其中,optimizer有Adam、RMSprop…,但其實都是Gradien Descent的方法
程式碼:
model.compile(優化器, 損失函數, 衡量標準)
多分類問題
1 | model.compile(optimizer='rmsprop', |
二分類問題
1 | model.compile(optimizer='rmsprop', |
回歸問題
1 | model.compile(optimizer='rmsprop', |
訓練
一般的訓練方法:
1 | history = model.fit(x, y, batch_size=32, epochs=10, verbose=1, validation_split=0.0, shuffle=True, ...) |
x
: inputy
: labelbatch_size
: 每次訓練看幾筆訓練資料epochs
: 模型訓練過程中總共要看幾次verbose
=1 代表輸出進度條紀錄, 0則代表不紀錄
訓練完會返回一個history
物件,紀錄訓練過程中每個epoch的acc
,val
..等資訊
除此之外,訓練完也可以用evaluate
去判斷訓練的好壞
1 | model.evaluate(x, y, batch_size=32, verbose=1...) |
生成器(generate)的訓練方法:
1 | model.fit_generator(generator, steps_per_epoch=None, epochs=1, verbose=1, validation_data=None, validation_steps=None, shuffle=True...) |
使用生成器(generate)逐批生成的數據,按批次訓練模型。生成器與模型並行可以提高效率
generator
: 一個生成器,生成器的輸出應為(inputs, targets)
steps_per_epoch
: 在一個epoch完成並開始下一個epoch之前從generator產生的總步數,即資料數量/batch大小
generator常搭配yield使用,在使用BERT模型時需要使用model.fit_generator()
繪圖觀察loss/acc
1 | import matplotlib.pyplot as plt |
繪圖函式
1 | def plot_fig(epochs,train,val,train_label,val_label,type): |
loss圖
1 | plot_fig(epochs,loss,val_loss,'train loss','validation loss','loss') |
acc圖
1 | plot_fig(epochs,acc,val_acc,'train acc','validation acc','acc') |
預測
1 | model.predict(x, batch_size=32, verbose=0) |
返回預測值的numpy array