- Inception module :
為 Google 的 Christian Szegedy 與其團隊所開發的網絡架構。Inception 模塊最基本的形式包含3~4 個分支,Inception 的進化可以參考博客Bharath Raj 的簡單介紹,下圖為 Inception V3示意圖。
Christian Szegedy, Wei Liu,. et al. "Going Deeper with Convolutions"
(圖片來源)#分支a branch_a = layers.Conv2D(128, 1,activation='relu', strides=2)(x)
#分支b branch_b = layers.Conv2D(128, 1, activation='relu')(x) branch_b = layers.Conv2D(128, 3, activation='relu', strides=2)(branch_b)
#分支c branch_c = layers.AveragePooling2D(3, strides=2)(x) branch_c = layers.Conv2D(128, 3, activation='relu')(branch_c)
#分支d branch_d = layers.Conv2D(128, 1, activation='relu')(x) branch_d = layers.Conv2D(128, 3, activation='relu')(branch_d) branch_d = layers.Conv2D(128, 3, activation='relu', strides=2)(branch_d)
#將分支輸出連接在一起,得到模塊輸出 output = layers.concatenate([branch_a, branch_b, branch_c, branch_d], axis=-1)
使用Inception module 來測試在Kaggle - Cat & Dog 上的效能
修改改程式碼:#建立模型網絡 from keras.models import Model from keras import layers, Input x = Input( shape =(150,150,3),dtype='float32') #分支a branch_a = layers.Conv2D(32, 1,activation='relu', strides=2)(x) branch_a = layers.Flatten()(branch_a) branch_a = layers.Dense(256, activation='relu')(branch_a) #分支b branch_b = layers.Conv2D(32, 1, activation='relu')(x) branch_b = layers.Conv2D(32, 3, activation='relu', strides=2)(branch_b) branch_b = layers.Flatten()(branch_b) branch_b = layers.Dense(256, activation='relu')(branch_b) #分支c branch_c = layers.AveragePooling2D(3, strides=2)(x) branch_c = layers.Conv2D(32, 3, activation='relu')(branch_c) branch_c = layers.Flatten()(branch_c) branch_c = layers.Dense(256, activation='relu')(branch_c) #分支d branch_d = layers.Conv2D(32, 1, activation='relu')(x) branch_d = layers.Conv2D(32, 3, activation='relu')(branch_d) branch_d = layers.Conv2D(32, 3, activation='relu', strides=2)(branch_d) branch_d = layers.Flatten()(branch_d) branch_d = layers.Dense(256, activation='relu')(branch_d) #將分支輸出連接在一起,得到模塊輸出 output = layers.concatenate([branch_a, branch_b, branch_c, branch_d],axis=-1) #將輸出做加入 sigmoid 分類 output = layers.Dense(1, activation='sigmoid')(output) model = Model(x,output)
非常遺憾,記憶體不夠,無法增加網絡的特徵維度,因此看不出效能。
在此先做一個練習,知道如何使用就好...。
- Residual Connection (殘差連接)
為 Microsoft 的 Kaiming He 與其團隊在 ILSVRC2015 競賽中獲勝所使用的方法。
在大規模深度學習的模型中(幾十層layer以上),通常會遇到兩個問題,梯度消失和表示瓶頸。
梯度消失,在循環神經網絡(RNN)中已經提過,而LSTM則是解決此問題的優化模型,在大規模神經網絡,利用同一概念,允許過去的信息稍後重新進入,從而解決梯度消失問題。將一個純線性的信息攜帶軌道,與主要的層堆疊方向平行,有助於跨越任意深度的層來傳播梯度,解決梯度消失的問題。
表示瓶頸,在大規模深度學習模型中,只要有其中一層的特徵維度過小,則會導致訊息將永遠被截掉(Loss),就好比類比訊號經過一層層的濾波器(filter 3MHz~1GHz),而其中一個濾波器頻寬只有3MHz~300MHz ,那在這之後的濾波器都只能看到3~300MHz 的訊號,而後面的訊號都流失掉了。藉由殘差連接,將過去的特徵再重新輸入到後面的層,以解決表示瓶頸的問題。
HE K, ZHANG X, REN S,. et al. "Deep residual learning for image recognition"from keras import layers,Input #如果特徵圖的尺寸相同,使用恆等殘差連接(identityresidual connection) x = Input(shape=(None,),) y = layers.Conv2D(128, 3, activation='relu', padding='same')(x) y = layers.Conv2D(128, 3, activation='relu', padding='same')(y) y = layers.Conv2D(128, 3, activation='relu', padding='same')(y) y = layers.add([y, x])
#如果特徵圖的尺寸不同,使用線性殘差連接(linear residual connection) x = Input(shape=(None,),) y = layers.Conv2D(128, 3, activation='relu', padding='same')(x) y = layers.Conv2D(128, 3, activation='relu', padding='same')(y) y = layers.MaxPooling2D(2, strides=2)(y) residual = layers.Conv2D(128, 1, strides=2, padding='same')(x) y = layers.add([y, residual])
完整程式碼:#資料夾分類處理後的路徑 original_dataset_dir ='C:\\Users\\Lido_Lee\\Downloads\\kaggle_original_data' base_dir = 'C:\\Users\\Lido_Lee\\Downloads\\cats_and_dogs_small' train_dir = 'C:\\Users\\Lido_Lee\\Downloads\\cats_and_dogs_small\\train' validation_dir = 'C:\\Users\\Lido_Lee\\Downloads\\cats_and_dogs_small\\validation' test_dir = 'C:\\Users\\Lido_Lee\\Downloads\\cats_and_dogs_small\\test'
#使用ImageDataGenerator 數據增強 from keras.preprocessing.image import ImageDataGenerator train_datagen = ImageDataGenerator(rescale=1./255, rotation_range=40, width_shift_range=0.2, height_shift_range=0.2, shear_range=0.2, zoom_range=0.2, horizontal_flip=True, fill_mode='nearest')
#測試數據不可使用數據增強 test_datagen = ImageDataGenerator(rescale=1./255)
train_generator = train_datagen.flow_from_directory(train_dir, target_size=(256, 256), batch_size=20, class_mode='binary') validation_generator = test_datagen.flow_from_directory(validation_dir, target_size=(256, 256), batch_size=20, class_mode='binary')
#建立模型網絡 from keras.models import Model from keras import layers, Input x = Input( shape =(256,256,3),dtype='float32') #線性殘差連接 y = layers.Conv2D(128, 3, activation='relu', padding='same')(x) y = layers.Conv2D(128, 3, activation='relu', padding='same')(y) y = layers.MaxPooling2D(2, strides=2)(y) residual = layers.Conv2D(128, 1, strides=2, padding='same')(x) y = layers.add([y, residual]) z = layers.Conv2D(128, 3, activation='relu', padding='same')(y) z = layers.Conv2D(128, 3, activation='relu', padding='same')(z) z = layers.MaxPooling2D(2, strides=2)(z) w = layers.Conv2D(128, 3, activation='relu', padding='same')(z) w = layers.Conv2D(128, 3, activation='relu', padding='same')(w) w = layers.MaxPooling2D(2, strides=2)(w) residual_w = layers.Conv2D(128, 1, strides=2, padding='same')(z) w = layers.add([w, residual_w])
#將輸出做加入 sigmoid 分類 w = layers.Flatten()(w) output = layers.Dense(256, activation='relu')(w) output = layers.Dense(1, activation='sigmoid')(output) model = Model(x,output)
#選擇優化器RMSprop、損失函數binary_crossentropy、指標acc from keras import optimizers model.compile(loss='binary_crossentropy', optimizer=optimizers.RMSprop(lr=1e-5), metrics=['acc'])
#將訓練&驗證資料丟進fit_generator訓練 history = model.fit_generator(train_generator, steps_per_epoch=100, epochs=20, validation_data=validation_generator, validation_steps=50)
test_generator = test_datagen.flow_from_directory(test_dir, target_size=(256, 256), batch_size=20, class_mode='binary')
#保存訓練模型 model.save('cats_and_dogs_residual_exercise.h5')
#在測試數據集上驗證 test_loss, test_acc = model.evaluate_generator(test_generator, steps=50) print('test acc:', test_acc)
#將訓練過程畫出來 import matplotlib.pyplot as plt acc = history.history['acc'] val_acc = history.history['val_acc'] loss = history.history['loss'] val_loss = history.history['val_loss'] epochs = range(1, len(acc) + 1) plt.plot(epochs, acc, 'bo', label='Training acc') plt.plot(epochs, val_acc, 'b+', label='Validation acc') plt.title('Training and validation accuracy') plt.legend() plt.figure() plt.plot(epochs, loss, 'bo', label='Training loss') plt.plot(epochs, val_loss, 'b+', label='Validation loss') plt.title('Training and validation loss') plt.legend() plt.show()
由於跑太久...只跑了20個 epochs ,可以看到還尚未發生過擬合,有空再來跑個100次看看...
2019年2月11日 星期一
深度學習 - Functional API - Inception & Residual connection
先前練習過多輸入&多輸出的 Functional API,接著來練習由層組成的有向無環的類圖形神經網絡。
訂閱:
張貼留言 (Atom)
沒有留言:
張貼留言