1.什么是神經網絡
神經網絡中信息只向一個方向移動,即從輸入節點向前移動,通過隱藏節點,再向輸出節點移
動,網絡中沒有循環或者環。其中的基本構件是:
輸入層:即輸入x的那一層
輸出層:即輸出y的那一層
隱藏層:輸入層和輸出層之間都是隱藏層
特點是:
同一層的神經元之間沒有連接。
第N層的每個神經元和第N-1層的所有神經元相連(這就是full connected的含義),第N-1層神
經元的輸出就是第N層神經元的輸入。
每個連接都有一個權值。
2.神經元是如何工作的
人工神經元接收到一個或多個輸入,對他們進行加權并相加,總和通過一個非線性函數產生輸
出。
3.激活函數
在神經元中引入了激活函數,它的本質是向神經網絡中引入非線性因素的,通過激活函數,神經
網絡就可以擬合各種曲線。
如果不用激活函數,每一層輸出都是上層輸入的線性函數,無論神經網絡有多少層,輸出都是輸入的線性組合,引入非線性函數作為激活函數,那輸出不再是輸入的線性組合,可以逼近任意函數。
常用的激活函數有:
3.1 Sigmoid/logistics函數
sigmoid 在定義域內處處可導,且兩側導數逐漸趨近于0。如果X的值很大或者很小的時候,那么
函數的梯度(函數的斜率)會非常小,在反向傳播的過程中,導致了向低層傳遞的梯度也變得非
常小。此時,網絡參數很難得到有效訓練。這種現象被稱為梯度消失。
一般來說, sigmoid 網絡在 5 層之內就會產生梯度消失現象。而且,該激活函數并不是以0為中心的,所以在實踐中這種激活函數使用的很少。sigmoid函數一般只用于二分類的輸出層。
3.2 tanh(雙曲正切曲線)
tanh也是一種非常常見的激活函數。與sigmoid相比,它是以0為中心的,使得其收斂速度要比
sigmoid快,減少迭代次數。然而,從圖中可以看出,tanh兩側的導數也為0,同樣會造成梯度消
失。
若使用時可在隱藏層使用tanh函數,在輸出層使用sigmoid函數。
3.3 ReLu
ReLU是目前最常用的激活函數。 從圖中可以看到,當x<0時,ReLU導數為0,而當x>0時,則不存在飽和問題。所以,ReLU 能夠在x>0時保持梯度不衰減,從而緩解梯度消失問題。
然而,隨著訓練的推進,部分輸入會落入小于0區域,導致對應權重無法更新。這種現象被稱為“神經元死亡”。
與sigmoid相比,RELU的優勢是:
- 采用sigmoid函數,計算量大(指數運算),反向傳播求誤差梯度時,求導涉及除法,計算
量相對大,而采用Relu激活函數,整個過程的計算量節省很多。 - sigmoid函數反向傳播時,很容易就會出現梯度消失的情況,從而無法完成深層網絡的訓
練。 - Relu會使一部分神經元的輸出為0,這樣就造成了網絡的稀疏性,并且減少了參數的相互依
存關系,緩解了過擬合問題的發生。
3.3 LeakReLu
3.5 SoftMax
softmax用于多分類過程中,它是二分類函數sigmoid在多分類上的推廣,目的是將多分類的結果以概率的形式展現出來。
softmax直白來說就是將網絡輸出的logits通過softmax函數,就映射成為(0,1)的值,而這些值的累和為1(滿足概率的性質),那么我們將它理解成概率,選取概率最大(也就是值對應最大的)接點,作為我們的預測目標類別。
3.6 其他激活函數
3.7 如何選擇激活函數
隱藏層
- 優先選擇RELU激活函數
- 如果ReLu效果不好,那么嘗試其他激活,如Leaky ReLu等
- 如果你使用了Relu, 需要注意一下Dead Relu問題, 避免出現大的梯度從而導致過多的神經元死亡
- 不要使用sigmoid激活函數,可以嘗試使用tanh激活函數
輸出層
- 二分類問題選擇sigmoid激活函數
- 多分類問題選擇softmax激活函數
- 回歸問題選擇identity激活函數
4. 神經網絡的優缺點
1.優點
- 精度高,性能優于其他的機器學習方法,甚至在某些領域超過了人類
- 可以近似任意的非線性函數
- 隨之計算機硬件的發展,近年來在學界和業界受到了熱捧,有大量的框架和庫可供調用
2.缺點 - 黑箱,很難解釋模型是怎么工作的
- 訓練時間長,需要大量的計算力
- 網絡結構復雜,需要調整超參數
- 小數據集上表現不佳,容易發生過擬合
5.神經網絡案例
手寫數字的識別
# 導入相應的工具包
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['figure.figsize'] = (7,7) # Make the figures a bit bigger
import tensorflow as tf
# 數據集
from tensorflow.keras.datasets import mnist
# 構建序列模型
from tensorflow.keras.models import Sequential
# 導入需要的層
from tensorflow.keras.layers import Dense, Dropout,
Activation,BatchNormalization
# 導入輔助工具包
from tensorflow.keras import utils
# 正則化
from tensorflow.keras import regularizers# 類別總數
nb_classes = 10
# 加載數據集
(X_train, y_train), (X_test, y_test) = mnist.load_data()
# 打印輸出數據集的維度
print("訓練樣本初始維度", X_train.shape)
print("訓練樣本目標值初始維度", y_train.shape)# 數據展示:將數據集的前九個數據集進行展示
for i in range(9):
plt.subplot(3,3,i+1)
# 以灰度圖顯示,不進行插值
plt.imshow(X_train[i], cmap='gray', interpolation='none')
# 設置圖片的標題:對應的類別
plt.title("數字{}".format(y_train[i]))# 數據處理
# 神經網絡中的每個訓練樣本是一個向量,因此需要對輸入進行重塑,使每個28x28的圖像成為一個的784維向量。另外,將輸入數據進行歸一化處理,從0-255調整到0-1# 調整數據維度:每一個數字轉換成一個向量
X_train = X_train.reshape(60000, 784)
X_test = X_test.reshape(10000, 784)
# 格式轉換
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
# 歸一化
X_train /= 255
X_test /= 255
# 維度調整后的結果
print("訓練集:", X_train.shape)
print("測試集:", X_test.shape)# 將目標值轉換為熱編碼的形式
Y_train = utils.to_categorical(y_train, nb_classes)
Y_test = utils.to_categorical(y_test, nb_classes)# 利用序列模型來構建模型
model = Sequential()
# 全連接層,共512個神經元,輸入維度大小為784
model.add(Dense(512, input_shape=(784,)))
# 激活函數使用relu
model.add(Activation('relu'))
# 使用正則化方法drouout
model.add(Dropout(0.2))
# 全連接層,共512個神經元,并加入L2正則化
model.add(Dense(512,kernel_regularizer=regularizers.l2(0.001)))
# BN層
model.add(BatchNormalization())
# 激活函數
model.add(Activation('relu'))
model.add(Dropout(0.2))
# 全連接層,輸出層共10個神經元
model.add(Dense(10))
# softmax將神經網絡輸出的score轉換為概率值
model.add(Activation('softmax'))# 模型編譯,指明損失函數和優化器,評估指標
model.compile(loss='categorical_crossentropy', optimizer='adam',metrics=
['accuracy'])# batch_size是每次送入模型中樣本個數,epochs是所有樣本的迭代次數,并指明驗證數據集
history = model.fit(X_train, Y_train,
batch_size=128, epochs=4,verbose=1,
validation_data=(X_test, Y_test))
Q1: 為什么要對數據進行歸一化
Q2:為什么要對數據進行熱編碼