【tensorflow】神經網絡的優化:指數衰減學習率、過擬合和欠擬合的解決方法、激活函數&損失函數&優化器的選擇


神經網絡的復雜度

1.空間復雜度

層數 = 隱藏層的層數 + 1個輸出層

總參數 = 總w + 總b

2.時間復雜度

乘加運算次數 = 總w

 

指數衰減學習率

學習率lr表征了參數每次更新的幅度,設置過小,參數更新會很慢,設置過大,參數不容易收斂。

 

 

在實際應用中,可以先使用較大學習率,快速找到較優值,然后逐步減小學習率,使模型找到最優解。

比如,指數衰減學習率。

指數衰減學習率 = 初始學習率 * 學習率衰減率^(當前輪數/多少輪衰減一次)

  • 初始學習率:最初設置的學習率。
  • 學習率衰減率:學習率按照這個比例指數衰減。
  • 當前輪數:可以用 epoch 表示(當前迭代了多少次數據集),也可以用 step 表示(當前迭代了多少次batch)。
  • 多少輪衰減一次:迭代多少次更新一次學習率,決定了學習率更新的頻率。
# 例:
# 數據集迭代次數

epoch = 50
# 初始學習率 lr_base = 0.2
# 學習率衰減率 lr_decay = 0.99
# 多少輪衰減一次 lr_step = 1
for epoch in range(epoch):
# 指數衰減學習率 lr
= lr_base * lr_decay ** (epoch/lr_step)

# 參數求導 with tf.GradientTape()
as tape: loss = tf.square(w + 1)
grads
= tape.gradient(loss, w)

# 參數自更新 w.assign_sub(lr
* grads)

 

激活函數

線性函數表達力不夠,加入非線性函數(激活函數),使得神經網絡可以隨層數的增加提升表達力。

 

優秀的激活函數需要滿足:

  • 非線性:只有當激活函數是非線性時,才不會被單層網絡所替代,使多層網絡有了意義。
  • 可微性:優化器大多使用梯度下降法更新參數,若激活函數不可微(不可求導),就不能更新參數。
  • 單調性:當激活函數是單調的,能保證單層網絡的損失函數是凸函數,更容易收斂。
  • 近似恆等性:f(x) ≈ x,這樣的神經網絡更穩定。

 

激活函數輸出值

  • 如果激活函數的輸出是有限值,權重對特征的影響會更顯著,用梯度下降的方法更新參數會更穩定。
  • 如果激活函數的輸出是無限值,參數的初始值對模型的影響非常大,建議使用更小的學習率。

 

幾種常見的激活函數

Sigmoid 激活函數

tf.nn.sigmoid(x)

Tanh 激活函數

tf.nn.tanh(x)

Relu 激活函數

tf.nn.relu(x)

Leaky Relu 激活函數

tf.nn.leaky_relu(x)

 

對初學者的建議:

  • 首選 relu 激活函數。
  • 學習率設置較小值。
  • 輸入特征標准化,即讓輸入特征滿足以0為均值,1為標准差的正態分布。
  • 初始參數中心化,即讓隨機生成的參數滿足以0為均值,√(2/當前層輸入特征個數) 為標差的正態分布。

 

損失函數loss

損失函數,即前向傳播預測結果 y 與已知標准答案 y_ 的差距。

神經網絡的優化目標就是找到某套參數,使得預測結果與標准答案無限接近,即 loss 值最小。

 

主流loss有三種:

均方誤差

loss = tf.reduce_mean(tf.square(y_ - y))

自定義

loss = tf.reduce_mean(tf.where(條件語句, 真返回A, 假返回B))

交叉熵

交叉熵越大,兩個概率分布越遠

交叉熵越小,兩個概率分布越近

y_pro = y.nn.softmax(y)

tf.losses.categorical_crossentropy(y_, y_pro)

執行分類問題時,通常先用 softmax 函數使輸出結果符合概率分布,再求交叉熵損失函數。

tensorflow給出了同時計算概率分布和交叉熵的函數

tf.nn.softmax_cross_entropy_with_logits(y_, y)

 

欠擬合與過擬合

欠擬合:模型不能有效擬合數據集,對現有數據集學習不夠徹底。

過擬合:模型對數據擬合太好,但對新數據難以做出判斷,缺乏泛化力。

 

 

網絡訓練過程中會遇到的情況:

loss 是訓練集的損失值,val_loss 是測試集的損失值。

loss 不斷下降,val_loss 不斷下降:網絡仍在學習;(最好情況)

loss 不斷下降,val_loss 趨於不變:網絡過擬合;(增大數據集 || 正則化)

loss 趨於不變,val_loss 不斷下降:數據集有問題;(檢查dataset)

loss 趨於不變,val_loss 趨於不變:學習遇到瓶頸;(減少學習率 || 減少批量數目)

loss 不斷上升,val_loss 不斷上升:網絡結構設計或訓練超參數設置不當,數據集經過清洗等問題。(最壞情況)

 

欠擬合的解決方法:

  • 增加輸入特征項
  • 增加網絡參數
  • 減少正則化參數

 

過擬合的解決方法:

  • 數據清洗
  • 增大訓練集
  • 采用正則化
  • 增大正則化參數

 

正則化減少過擬合:

正則化,就是在損失函數中引入模型復雜度指標,給每個參數 w 加上權重,抑制訓練中的噪聲。

正則化通常只對參數 w 使用,不對偏置 b 使用。

loss = loss(y_, y) + regularizer * loss(w)

loss(y_, y):以前求得的 loss 值。

regularizer:參數 w 在總 loss 中的比重.

loss(w)

  • 對所有參數 w 求和(L1正則化:大概率會使很多參數變為0,可用來稀疏參數,降低模型復雜度)
  • 對所有參數 w 的平方求和(L2正則化:會使參數接近0但不等於0,可用來減小參數的數值,有效緩解數據集中因噪聲引起的過擬合)

 

# 例:
with tf.GradientTape() as tape: 
...
# 原始 loss loss_mse = tf.reduce_mean(tf.square(y_ - y)) # 用來寄存所有參數 w L2正則化后的結果 loss_regularization = [] # 將所有參數 w 做 L2正則化處理,並存在loss_regularization中 loss_regularization.append(tf.nn.l2_loss(w1)) loss_regularization.append(tf.nn.l2_loss(w2)) # 計算所有參數 w L2正則化后的總和 loss_regularization = tf.reduce_sum(loss_regularization) # 正則化 loss = loss_mse + 0.03 * loss_regularization # 對各參數求導 grads = tape.gradient(loss, [w1, b1, w2, b2]) # 參數自更新 w1.assign_sub(lr * grads[0]) b1.assign_sub(lr * grads[1]) w2.assign_sub(lr * grads[2]) b2.assign_sub(lr * grads[3])


...

 

優化器更新網絡參數

 

借鑒博客:

https://www.cnblogs.com/niulang/p/11752605.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM