所謂深度神經網絡就是層次比較多的神經網絡,我們搭建深度神經網絡的過程就是多次添加網絡層次的過程,與搭建回歸模型和預測模型的過程一樣。
下面就看一下使用tf.keras.Sequential構建深度神經網絡模型的完整過程:
1 # 第一步:包導入 2 import numpy as np 3 import pandas as pd 4 import matplotlib as mpl 5 import matplotlib.pyplot as plt 6 import sklearn 7 import tensorflow as tf 8 import tensorflow.keras as keras 9 10 import os 11 import sys 12 import time 13 14 for module in np, pd, mpl, sklearn, tf, keras: 15 print (module.__name__, module.__version__) 16 # 第二步:數據加載 17 from sklearn.datasets import fetch_california_housing 18 housing = fetch_california_housing(data_home='C:/Users/rencm/scikit_learn_data', 19 download_if_missing=True) 20 # 第三步:切分數據集和驗證集 21 from sklearn.model_selection import train_test_split 22 x_train_all, x_test, y_train_all, y_test = train_test_split(housing.data, housing.target, random_state = 7) 23 x_train, x_valid, y_train, y_valid = train_test_split(x_train_all, y_train_all, random_state = 11) 24 print (x_train.shape, x_valid.shape, x_test.shape) 25 # 第四步:輸入歸一化 26 from sklearn.preprocessing import StandardScaler 27 scaler = StandardScaler() 28 x_train_scaled = scaler.fit_transform(x_train) 29 x_valid_scaled = scaler.transform(x_valid) 30 x_test_scaled = scaler.transform(x_test) 31 # 第五步:構建模型(這里構建隱藏層深度為20的深度神經網絡模型) 32 model = keras.models.Sequential() 33 model.add(keras.layers.Input(shape = x_train.shape[1:])) 34 for _ in range(20): 35 model.add(keras.layers.Dense(30, activation = 'relu')) 36 model.add(keras.layers.Dense(1)) 37 38 print (model.summary()) 39 40 model.compile( 41 loss = 'mean_squared_error', 42 optimizer = 'sgd' 43 ) 44 # 第六步:訓練模型 45 history = model.fit( 46 x_train_scaled, y_train, 47 validation_data=(x_valid_scaled, y_valid), 48 epochs=100, 49 callbacks=[ 50 keras.callbacks.EarlyStopping(min_delta = 1e-2, patience=5) 51 ] 52 ) 53 # 第七步:評測模型 54 model.evaluate(x_test_scaled, x_test)
模型的構建是我們已經非常熟悉的一個過程,所以上面我們沒有仔細的講解,我們所要強調是在深度神經網絡模型的構建過程中以下幾個可以優化的方面:
一:批歸一化處理
概念:所謂的批歸一化就是對所有的中間層次的結果都進行歸一化的處理。
作用:可以有效的抑制梯度消失的問題。(梯度消失即損失函數關於靠前層次的導數越來越小,就可能導致前面層次的訓練不充分。導致梯度消失問題出現的原因主要有兩個。一是參數初始化問題,二是不合適的激活函數。批歸一化處理可以使損失函數關於某一參數的導數盡可能均勻的分布,那么就不會出現關於某一參數的導數過小,從而有效的抑制梯度消失問題)
常用歸一化處理的方式:
- min-max歸一化:x = (x-min)/(max - min)
- z-score歸一化:x = (x-u)/std
1 # 第五步:構建模型(這里構建隱藏層深度為20的深度神經網絡模型) 2 model = keras.models.Sequential() 3 model.add(keras.layers.Input(shape = x_train.shape[1:])) 4 for _ in range(20): 5 model.add(keras.layers.Dense(30, activation = 'relu')) 7 model.add(keras.layers.BatchNormalization())#對上一層的輸出進行歸一化處理 8 """10 在歸一化處理的時候,抑制存在一個爭議,應該在激活之后歸一化,還是應該在激活在前歸一化,下面給出在激活之前歸一化的方式: 11 model.add(keras.layers.Dense(30))13 model.add(keras.layers.BatchNormalization()) 14 model.add(keras.layers.Activation('relu')) 15 """ 16 model.add(keras.layers.Dense(1)) 17 18 print (model.summary()) 19 20 model.compile( 21 loss = 'mean_squared_error', 22 optimizer = 'sgd' 23 )
二:激活函數的重要性
首先介紹幾個比較常用的激活函數:
- sigmoid:1/(1+e^(-x))
- relu:max(0,x)
- tanh:tanh(x)
- leaky relu:max(0.1x, x)
- maxout
- elu
這里我們測試一下selu激活函數,這個激活函數的特殊點是自帶批歸一化處理,而且運行的速度較快:
1 # 第五步:構建模型(這里構建隱藏層深度為20的深度神經網絡模型) 2 model = keras.models.Sequential() 3 model.add(keras.layers.Input(shape = x_train.shape[1:])) 4 for _ in range(20): 5 model.add(keras.layers.Dense(30, activation = 'selu')) 6 model.add(keras.layers.Dense(1)) 7 8 print (model.summary()) 9 10 model.compile( 11 loss = 'mean_squared_error', 12 optimizer = 'sgd' 13 )
三:dropout
概念:在模型訓練的每一輪次,隨機的選擇若干個神經元,使其不再發生作用,即拋棄神經元。
作用:可以有效抑制過擬合。(dropout可以防止模型過分的依賴於某一個或幾個神經元,從而有效的抑制過擬合現象的發生)
1 # 第五步:構建模型(這里構建隱藏層深度為20的深度神經網絡模型) 2 model = keras.models.Sequential() 3 model.add(keras.layers.Input(shape = x_train.shape[1:])) 4 for _ in range(20): 5 model.add(keras.layers.Dense(30, activation = 'selu')) 6 model.add(keras.layers.Dropout(0.5)) 7 # 在批歸一化處理的時候,我們一般不會對所以的層次都進行歸一化處理,影響程序運行效率,我們只對某幾層進行歸一化處理。 8 model.add(keras.layers.Dense(1)) 9 10 print (model.summary()) 11 12 model.compile( 13 loss = 'mean_squared_error', 14 optimizer = 'sgd' 15 )