神經網路中資料從資料層到最後輸出層的流動過程其實就是資料從一種形態到另一種形態,從乙個維度到另乙個維度的變換過程,例如在minst資料集訓練中,就是把28*28維的影象資料經過變換,對映成0~9之間的乙個數字。完成這種資料變換的乙個重要工具就是啟用函式。
乙個典型的人工神經元的模型可以用下圖表述:
啟用函式的主要作用是改變之前資料的線性關係,如果網路中全部是線性變換,則多層網路可以通過矩陣變換,直接轉換成一層神經網路,所以啟用函式的存在,使得神經網路的「多層」有了實際的意義,使網路更加強大,增加網路的能力,使它可以學習複雜的事物,複雜的資料,以及表示輸入輸出之間非線性的複雜的任意函式對映。
啟用函式的另乙個重要的作用是執行資料的歸一化,將輸入資料對映到某個範圍內,再往下傳遞,這樣做的好處是可以限制資料的擴張,防止資料過大導致的溢位風險。
sigmoid函式的特點是會把輸出限定在0~1之間,如果是非常大的負數,輸出就是0,如果是非常大的正數,輸出就是1,這樣使得資料在傳遞過程中不容易發散。
sigmod有兩個主要缺點,一是sigmoid容易過飽和,丟失梯度。從sigmoid的示意圖上可以看到,神經元的活躍度在0和1處飽和,梯度接近於0,這樣在反向傳播時,很容易出現梯度消失的情況,導致訓練無法完整;二是sigmoid的輸出均值不是0,基於這兩個缺點,sigmoid使用越來越少了。
tanh是sigmoid函式的變形,tanh的均值是0,在實際應用中有比sigmoid更好的效果。
relu是近來比較流行的啟用函式,當輸入訊號小於0時,輸出為0;當輸入訊號大於0時,輸出等於輸入。
relu的優點:
1. relu是部分線性的,並且不會出現過飽和的現象,使用relu得到的隨機梯度下降法(sgd)的收斂速度比sigmodi和tanh都快。
2. relu只需要乙個閾值就可以得到啟用值,不需要像sigmoid一樣需要複雜的指數運算。
relu的缺點:
在訓練的過程中,relu神經元比價脆弱容易失去作用。例如當relu神經元接收到乙個非常大的的梯度資料流之後,這個神經元有可能再也不會對任何輸入的資料有反映了,所以在訓練的時候要設定乙個較小的合適的學習率引數。
相比relu,leaky-relu在輸入為負數時引入了乙個很小的常數,如0.01,這個小的常數修正了資料分布,保留了一些負軸的值,在leaky-relu中,這個常數通常需要通過先驗知識手動賦值。
maxout是在2023年才提出的,是一種激發函式形式,一般情況下如果採用sigmoid函式的話,在前向傳播過程中,隱含層節點的輸出表示式為:
其中w一般是二維的,這裡表示取出的是第i列,下標i前的省略號表示對應第i列中的所有行。而在maxout激發函式中,在每乙個隱含層和輸入層之間又隱式的新增了乙個「隱含層」,這個「隱隱含層」的啟用函式是按常規的sigmoid函式來計算的,而maxout神經元的啟用函式是取得所有這些「隱隱含層」中的最大值,如上圖所示。
maxout的啟用函式表示為:
f(x)=ma
x(wt
1x+b
1,wt
2x+b
2)
可以看到,relu 和 leaky relu 都是它的乙個變形(比如,w1
,b1=
0 的時候,就是 relu)。
maxout的擬合能力是非常強的,它可以擬合任意的的凸函式,優點是計算簡單,不會過飽和,同時又沒有relu的缺點(容易死掉),但maxout的缺點是過程引數相當於多了一倍。
其他一些啟用函式列表:
啟用函式應用
這裡以最簡單的只有乙個神經元(包含啟用函式)的網路為例,說明一下啟用函式的工作過程。
假設神經元的輸入是乙個4維的向量 x=[x1,x2,x3,x4]
,其中xi
的值為0或者1,並且只取4中樣本:
對這一組樣本,採用乙個很小的隨機數來模擬生成20000個樣本,同時,將神經元的4個輸出值對映到[0,1],即4個分類分別是[0.25,0.5,0.75,1]。
**實現如下:
#include #include using namespace std;
vector> inputdata;
vectorweight;
double actual_output; //網路的實際輸出
vectorinput;
//生成numofsample個樣本,一共分為numoflable類,每個樣本的標籤是當前樣本的下標i%numoflable
void getsamplesdata(int numofsamples, int numoflable)
inputdata.push_back(dvect); }}
//初始化初始權重,包括4個節點和1個偏置,隨機設定為0~0.05之間的乙個值
void intialweight()
}//前向計算,輸入時資料層的4維的訓練資料,actual_output是網路當前的輸出
void cmtforward(const vector& invect)
actual_output = 1 / (1 + exp(-1 * dsum)); // s函式的非線性變換
//actual_output = 2 * (1 / (1 + exp(-2 * dsum))) - 1; //t函式的非線性變換
//dsum > 0 ? actual_output = dsum : actual_output = 0; //r函式的非線性變換
}//權重調整,相當於後向計算,輸入時訓練資料和期望的輸出
void updataweight(const vector& invect, const double true_output)
// w0單獨計算
weight[4] += (learnrate*(true_output - actual_output)*actual_output*(1 - actual_output) * 1);
}void main()
} cout << "優化後的權重係數:[ " << weight[0] << "," << weight[1] << "," << weight[2] << "," <<
weight[3] << " ]" << " 偏置: " << weight[4] << endl;
system("pause");
}
在前向計算cmtforward函式中,使用s函式,注釋掉的分別是t函式和r函式。
s函式的迭代實現結果:
t函式的迭代實現結果:
r函式的迭代實現結果:
經過迭代優化,3種啟用函式對輸入的資料的響應基本都對映在0.25,0.5,0.75,0.96左右,分別對應1,2,3,4分類,都可以對輸入正確分類。3種啟用函式迭代後分別生成3組權重係數(加偏置係數),不同啟用函式優化出的權重係數不同。
神經網路常用的啟用函式
1 恒等函式 f z i z z 2 sigmoid 函式 這個函式通常是用在返回0到1之間的值 f z 1 1 exp z 3 tanh 雙曲正切 啟用函式 雙曲正切是一條 1 1的s形曲線 f z tanh z 影象如圖 4 relu 整流線性單元 啟用函式 f z max 0,z python...
神經網路啟用函式
2018,jul 23 學了深度學習也快近一年了,在學deep learning的時候什麼教程都去看,起初學起來也特別的雜亂,前面的基礎沒弄懂還一直往下學,自然導致我學到後面的時候有點崩潰什麼都看不懂,並且因為自己還是一名在校生,平常課程也非常多,沒有乙個連續的學習時間也導致我的學習是斷斷續續,在學...
啟用函式 神經網路
andrew的 neural networks and deep learning 課程學習筆記 如圖所示,是乙個簡單的三層神經網路,如果只使用線性啟用函式或者恒等啟用函式 不使用啟用函式 那麼神經網路的輸出就只是輸入函式的線性變化,因為線性啟用函式的組合依然是線性啟用函式。這種情況下,不管使用多少...