關於神經網絡的一些認識

如果說線性分類器使用直線作爲分類的邊界,那麼神經網絡則是在使用線性分類的基礎上加了非線性的分類,也就是曲線。直接說就是,比如在svm上是權重w與輸入x相乘之後就是計算損失函數(直接使用w權重矩陣對輸入x進行分類,而神經網絡是在使用w權重對輸入x進行分類之前,先用激活函數計算輸入x的值,),而神經網絡裏則不是,它是在權重矩陣w與輸入x相乘之後,再將這個結果輸入到一個名爲激活函數裏面,這個激活函數就好比生物神經元裏面的激勵函數,當輸入信號達到一定閾值後觸發信號輸出。經過激活函數計算後再計算損失函數。

W權重矩陣,對一幅圖像而言,可以說是這幅圖像的特徵表達,w權重的每行數據代表了一個圖像特徵,w權重的列數則表示該圖像有多少個特徵需要去分類。普通的線性分類器比如支持向量機SVM就是使用w特徵矩陣與輸入x矩陣相乘,然後根據損失函數對輸入進行分類,這是直接使用特徵矩陣對輸入去分類。而神經網絡則不同。首先需要明白一件事,就是w特徵矩陣與輸入x相乘的結果是表達了什麼?w是這幅圖像的特徵矩陣,每一行表示了一個特徵,有多少列就有多少個特徵,那w與x矩陣乘法的結果是一個矩陣,這個矩陣的每一行數則表示這幅圖像的某特徵其突出的程度,也就是說某一行的結果越大則這一行所代表的圖像特徵在圖像中佔的比重就越大。而對於一些相似特徵那麼他們的結果也就越相近,這時再使用線性分類器則不好分別,那麼就需要使用一些函數對這些特徵進行抑制或者放大,突出我們想要的特徵。這些函數就是神經網絡裏的激活函數。這些激活函數往往是在輸入層後面,輸出層前面,對於一個兩層的神經網絡來說就是,x->f(w1*x)->w2->loss,其輸入層是x,輸出層是w2->loss。中間隱含層是w1特徵矩陣。
對一個兩層神經網絡的代碼如下

import numpy as np
from numpy.random import randn
import matplotlib.pyplot as plt
# 定義輸入和神經元大小,並初始化
N, D_in, H, D_out = 64,1000,100,10
x, y = randn(N,D_in), randn(N,D_out) # x(64,1000),y(64,10)
w1, w2 = randn(D_in, H), randn(H, D_out) # w1(1000,100),w2(100,10)
# 進行訓練
lossK = []
for t in range(2000):
    # 前向傳播
    h = 1 / (1 + np.exp(np.dot(-x,w1))) # 激活函數,h(64,100)
    y_pred = np.dot(h, w2) # y_pred(64,10)
    loss = np.square(y_pred - y).sum() 
    if(t%100==0):
        print(t, loss)
    lossK.append(loss)
    # 反向傳播
    grad_y_pred = 2 * (y_pred - y) # (64,10)
    grad_w2 = np.dot(h.T, grad_y_pred) # (100,10)
    grad_h = np.dot(grad_y_pred,w2.T) # (64,100)
    grad_w1 = np.dot(x.T,grad_h * h * (np.ones(h.shape) - h)) # (1000,100)
    # 更新w
    w1 -= 1e-4 * grad_w1
    w2 -= 1e-4 * grad_w2
x = np.arange(2000)
y = lossK
plt.plot(x, y)
plt.show()

結果:
可以看見損失函數是在逐漸減少的
可以看見損失函數是在逐漸減少的縱走
縱軸表示損失函數,橫軸表示訓練次數。

當然相比於規範的神經網絡訓練步驟,這段代碼有幾處不足。

(1)對於輸入x沒有做標準化處理,雖然這裏的x和w均是隨機生成的呈正態分佈的數據。所謂標準化處理就是將輸入數據處理呈均值爲0,方差爲1呈標準正態分佈的數據。

(2)沒有增加偏置項b,如果沒有設置偏置項b,對於y=wx分類器一定會經過原點,影響分類效果,如果加了偏置項,b可以大於0可以等於0可以小於0,這樣這個分類器就會更加好用。

常用的激活函數有Sigmoid, tanh, ReLU,Leaky-ReLU,ELU.
在這裏插入圖片描述
缺點:
(1)飽和性會使得梯度消失,就是x過大或者過小時,梯度接近於0;
(2)函數輸出永遠在0-1之間,每個神經元的偏導同號,其梯度值更新的方向都是一樣的,也就是梯度值會出現同時增加或者同時減小的現象,即容易出現鋸齒現象;
(3)涉及指數運算,會佔用較大的計算資源。
在這裏插入圖片描述
雙曲正切函數作爲激活函數,會使得函數輸出有正有負,範圍在[-1,1],其梯度值的變化是可以有正有負的,不會出現鋸齒現象,但是其飽和性的問題依然存在。
在這裏插入圖片描述

ReLU函數可以理解爲整流函數,只對輸入大於0的項做出反應,小於0的項則全部置零。這樣會使得一些神經元出現死亡的現象,也就是梯度不會發生更新,對外界輸入沒有反映,往往加一些偏置項(常取0.01)可以緩解這種情況。總體而言,ReLU激活函數其梯度收斂速度遠遠大於Sigmoid和雙曲正切函數,而且計算簡單不會出現飽和現象,因此ReLU激活函數用的更多。

4.Leaky ReLU:f(x)=max(0.01x,x)

Leaky ReLU函數是爲了解決死亡神經元問題而設計的,繼承了ReLU函數的優點。

5.Maxout ELU:f(x)=max(w1x+b1,w2x+b2)

對輸出使用神經元再進行選擇一次,繼承了ReLU和leaky ReLU的優點,但是參數卻增加了一倍。

面對這幾個激活函數,斯坦福課程給出的推薦是:

(1)不要輕易使用Sigmoid函數;

(2)可以使用ReLU函數,但是要注意學習率不能太大;

(3)可以使用tanh,但是效果不如leaky ReLU或者maxout

(4)可以使用leaky ReLU或者Maxout eLU。

總結自:斯坦福cs231n課程和B站up主同濟子豪兄
推薦一個不錯的B站up主添加鏈接描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章