今天終於要進入模型建構的部分啦!在 Keras 中建構模型的方法主要有 3 種:序列式模型、函數式 API 和繼承 Model 類別。這系列會使用其中兩種:序列式模型與函數式 API,來進行實作。今天先來介紹序列式模型的寫法,此方法較為容易,也很直觀,很適合初學者使用。本系列使用的模型以 VGG16 為例,VGG16 為 2014 年發表的模型,許多影像分類的問題都可以使用 VGG16 來解決。
序列式模型(Sequential Model)為一種建構模型的方法,特色為一層接著一層,依序的線性模型架構。模型的層與層之間若沒有分支或是跳躍的結構,可以使用這種方法來建構模型,且這種方法對模型的架構一目了然。
首先,先匯入會使用到的模組:
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPool2D, Flatten, Dense
此段程式碼為 VGG16 的模型架構,先以 Sequential()
建立序列式模型,以 add()
的方式來新增神經層:
model = Sequential()
model.add(Conv2D(input_shape=(256,256,3),filters=64,kernel_size=(3,3),padding="same", activation="relu"))
model.add(Conv2D(filters=64,kernel_size=(3,3),padding="same", activation="relu"))
model.add(MaxPool2D(pool_size=(2,2),strides=(2,2)))
model.add(Conv2D(filters=128, kernel_size=(3,3), padding="same", activation="relu"))
model.add(Conv2D(filters=128, kernel_size=(3,3), padding="same", activation="relu"))
model.add(MaxPool2D(pool_size=(2,2),strides=(2,2)))
model.add(Conv2D(filters=256, kernel_size=(3,3), padding="same", activation="relu"))
model.add(Conv2D(filters=256, kernel_size=(3,3), padding="same", activation="relu"))
model.add(Conv2D(filters=256, kernel_size=(3,3), padding="same", activation="relu"))
model.add(MaxPool2D(pool_size=(2,2),strides=(2,2)))
model.add(Conv2D(filters=512, kernel_size=(3,3), padding="same", activation="relu"))
model.add(Conv2D(filters=512, kernel_size=(3,3), padding="same", activation="relu"))
model.add(Conv2D(filters=512, kernel_size=(3,3), padding="same", activation="relu"))
model.add(MaxPool2D(pool_size=(2,2),strides=(2,2)))
model.add(Conv2D(filters=512, kernel_size=(3,3), padding="same", activation="relu"))
model.add(Conv2D(filters=512, kernel_size=(3,3), padding="same", activation="relu"))
model.add(Conv2D(filters=512, kernel_size=(3,3), padding="same", activation="relu"))
model.add(MaxPool2D(pool_size=(2,2),strides=(2,2)))
model.add(Flatten())
model.add(Dense(units=4096,activation="relu"))
model.add(Dense(units=4096,activation="relu"))
model.add(Dense(units=5, activation="softmax"))
使用 summary()
查看模型結構:
model.summary()
以上程式碼執行結果:
Model: "sequential_1"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d_13 (Conv2D) (None, 256, 256, 64) 1792
_________________________________________________________________
conv2d_14 (Conv2D) (None, 256, 256, 64) 36928
_________________________________________________________________
max_pooling2d_5 (MaxPooling2 (None, 128, 128, 64) 0
_________________________________________________________________
conv2d_15 (Conv2D) (None, 128, 128, 128) 73856
_________________________________________________________________
conv2d_16 (Conv2D) (None, 128, 128, 128) 147584
_________________________________________________________________
max_pooling2d_6 (MaxPooling2 (None, 64, 64, 128) 0
_________________________________________________________________
conv2d_17 (Conv2D) (None, 64, 64, 256) 295168
_________________________________________________________________
conv2d_18 (Conv2D) (None, 64, 64, 256) 590080
_________________________________________________________________
conv2d_19 (Conv2D) (None, 64, 64, 256) 590080
_________________________________________________________________
max_pooling2d_7 (MaxPooling2 (None, 32, 32, 256) 0
_________________________________________________________________
conv2d_20 (Conv2D) (None, 32, 32, 512) 1180160
_________________________________________________________________
conv2d_21 (Conv2D) (None, 32, 32, 512) 2359808
_________________________________________________________________
conv2d_22 (Conv2D) (None, 32, 32, 512) 2359808
_________________________________________________________________
max_pooling2d_8 (MaxPooling2 (None, 16, 16, 512) 0
_________________________________________________________________
conv2d_23 (Conv2D) (None, 16, 16, 512) 2359808
_________________________________________________________________
conv2d_24 (Conv2D) (None, 16, 16, 512) 2359808
_________________________________________________________________
conv2d_25 (Conv2D) (None, 16, 16, 512) 2359808
_________________________________________________________________
max_pooling2d_9 (MaxPooling2 (None, 8, 8, 512) 0
_________________________________________________________________
flatten_1 (Flatten) (None, 32768) 0
_________________________________________________________________
dense_3 (Dense) (None, 4096) 134221824
_________________________________________________________________
dense_4 (Dense) (None, 4096) 16781312
_________________________________________________________________
dense_5 (Dense) (None, 5) 20485
=================================================================
Total params: 165,738,309
Trainable params: 165,738,309
Non-trainable params: 0
_________________________________________________________________
可以觀察到序列式模型的特色,使用神經層堆疊的方式來建構模型。
註:Model 和 Layer 的名稱是可以更改的,這裡為執行時預設的名稱及編號。
程式碼也可以改寫為:
model = Sequential([
Conv2D(input_shape=(256,256,3),filters=64,kernel_size=(3,3),padding="same", activation="relu"),
Conv2D(filters=64,kernel_size=(3,3),padding="same", activation="relu"),
MaxPool2D(pool_size=(2,2),strides=(2,2)),
Conv2D(filters=128, kernel_size=(3,3), padding="same", activation="relu"),
Conv2D(filters=128, kernel_size=(3,3), padding="same", activation="relu"),
MaxPool2D(pool_size=(2,2),strides=(2,2)),
Conv2D(filters=256, kernel_size=(3,3), padding="same", activation="relu"),
Conv2D(filters=256, kernel_size=(3,3), padding="same", activation="relu"),
Conv2D(filters=256, kernel_size=(3,3), padding="same", activation="relu"),
MaxPool2D(pool_size=(2,2),strides=(2,2)),
Conv2D(filters=512, kernel_size=(3,3), padding="same", activation="relu"),
Conv2D(filters=512, kernel_size=(3,3), padding="same", activation="relu"),
Conv2D(filters=512, kernel_size=(3,3), padding="same", activation="relu"),
MaxPool2D(pool_size=(2,2),strides=(2,2)),
Conv2D(filters=512, kernel_size=(3,3), padding="same", activation="relu"),
Conv2D(filters=512, kernel_size=(3,3), padding="same", activation="relu"),
Conv2D(filters=512, kernel_size=(3,3), padding="same", activation="relu"),
MaxPool2D(pool_size=(2,2),strides=(2,2)),
Flatten(),
Dense(units=4096,activation="relu"),
Dense(units=4096,activation="relu"),
Dense(units=5, activation="softmax")
])
看起來較為簡潔清晰,不過都可以依照自己喜好去寫是沒問題的!
在機器學習或深度學習中,參數(Parameter)指的是權重(Weight)和偏值(Bias)這些會經過每次訓練去更新的變量,而超參數(Hyperparameter)指的是事先給定的值,包含模型超參數和演算法超參數。這裡的超參數屬於前者模型超參數,可以決定模型的結構,接著一一為大家解釋各個超參數的含意。
Conv2D(input_shape=(256,256,3),filters=64,kernel_size=(3,3),padding="same", activation="relu")
這裡使用了 Conv2D()
,為卷積層(Convolutional Layer),用來提取輸入影像的特徵,在處理影像問題時很常被使用到。input_shape
為輸入影像的大小,(256, 256, 3)
為 256×256 的 RGB(3 channel)影像。filters
為過濾器,指卷積核的數量,卷積核是用來學習影像中不同的特徵,每一個卷積核會產生一個特徵影像。kernel_size
為卷積核大小,用較小的卷積核容易捕捉局部特徵。padding
為指定填充的方式,若設成 same
表示輸入和輸出的大小會一致。activation
為啟動函數,使用啟動函數的原因,最主要是讓模型有非線性的特性,可以處理不同種類的資料集,也可以幫助模型收斂。
MaxPool2D(pool_size=(2,2),strides=(2,2))
這裡使用了 MaxPool2D()
,為池化層(Pooling Layer),用來將特徵影像做降採樣(Downsampling),可以保留關鍵特徵,同時降低計算量。pool_size
為池化窗口大小,將指定大小內的最大值作為池化結果。strides
為池化窗口在輸入影像上滑動的步幅。
Flatten()
Flatten()
為平坦層(Flattern Layer),功能為將高維度的數據轉換成一維度的數據。平坦層常使用於卷積層和池化層之後,將影像這類高維度數據轉換成一維數據,之後輸入到全連接層。
Dense(units=4096,activation="relu")
Dense()
為全連接層(Fully Connected Layer),顧名思義,代表這一層的每一個神經元都與上一層的神經元相連接。units
為神經元的數量,activation
為啟動函數。
註:目前以實作會使用到的超參數舉例,其他超參數種類,可以到 Keras API 文件 查詢。
今天介紹了一種模型建構的方法,明天會介紹另一種,請期待一下吧!