http://blog.csdn.net/cxf7394373/article/details/6061372
寫在前面的
接觸神經網絡(ANN)的時間很長了,以前也只是學了學原理,做過一個BPN的練習,沒有系統的總結過,最近看Torch的源碼,對MLP有了更多的了解,寫寫自己學到的東西吧,算是做了一次總結!
ANN的特點
高度的並行性
人工神經網絡是由許多相同的簡單處理單元並聯組合而成,雖然每個單元的功能簡單,但大量簡單單元的並行活動,使其對信息的處理能力與效果驚人。
高度的非線性全局作用
神經網絡系統是由大量簡單神經元構成的,每個神經元接受大量其他神經元的輸入,通過非線性輸入、輸出關系,產生輸出影響其它神經元。網絡就是這樣互相制約相互影響,實現從輸入狀態空間到輸出狀態空間非線性映射的。網絡的演化遵從全局性作用原則,從輸入狀態演化到終態而輸出。從全局觀點來看,網絡整體性能不是網絡局部性能的簡單迭加,而表現某種集體性行為;而電腦遵從串行式局域性操作原則,每一步計算與上一步計算緊密相關,並對下一步產生影響,問題是通過算法逐步進行處理的。
良好的容錯性與聯想記憶功能
人工神經網絡通過自身的網絡結構能夠實現對信息的記憶,而所記憶的信息是存儲在神經元之間的權值中。從單個權值中看不出所儲存的信息內容,因而是分布式的存儲方式。這使得網絡具有良好的容錯性,並能進行聚類分析、特征提取、缺損模式復原等模式信息處理工作。
十分強的自適應、自學習功能人工神經網絡可以通過訓練和學習來獲得網絡的權值與結構,呈現出很強的自學習能力和對環境的自適應能力。
ANN分類
BPN(Back Propagation Net)
在這裡我介紹一下反向傳播網絡BPN---帶動量項的誤差反傳。反向傳播神經網絡是對非線性可微分函數進行權值訓練的多層網絡,是前向神經網絡的一種。BP網絡主要用於:
1)函數逼近與預測分析:用輸入矢量和相應的輸出矢量訓練一個網絡,逼近一個函數或預測未知信息;
2)模式識別:用一個特定的輸出矢量將它與輸入矢量聯系起來;
3)分類:把輸入矢量以所定義的合適方式進行分類;
4)數據壓縮:減少輸出矢量維數以便於傳輸與存儲。
比如,一個三層BPN結構如下:
由輸入層、隱含層和輸出層三層組成。其中每一層的單元與與之相鄰層的所有單元連接,同一層的單元之間沒有連接。當一對學習樣本提供給網絡後,神經元的激活值從輸入層經各中間層向輸出層傳播,在輸出層的各神經元獲得網絡的輸入響應。接下來,按照減少目標輸出與實際誤差的方向,從輸出層經過各中間層逐層修正各連接權值,最後回到輸入層。
感知器(Perception)類型
linear----線性感知器
tanh----雙曲正切函數
sigmoid----雙曲函數
softmax----1/(e(net) * e(wi*xi- shift))
log-softmax---- log(1/(e(net) * e(wi*xi)))
exp----指數函數
softplus----log(1+ e(wi*xi))
梯度下降
Delta學習方法
增量梯度下降
MLP的缺陷
1. 網絡的隱含節點個數選取問題至今仍是一個 世界難題(Google, Elsevier, CNKI);
2. 停止閾值、學習率、動量常數需要采用」trial-and-error」法,極其耗時(動手實驗);
3. 學習速度慢;
4. 容易陷入局部極值,學習不夠充分。
應用舉例
[c-sharp] view plain copy
- static void Main(string[] args)
- {
- int row = 2;//訓練樣例的數目
- int n_in = 2;//輸入值的個數
- int n_out = 1;//輸出值的個數
- int n_hidden = 1;//隱含層單元個個數
-
- double eta = 0.3;//學習速率
- double alfa = 0.9;//動量項
- int [,] t_ex = new int[row,n_in + n_out];//訓練樣例
-
- //賦初值 訓練樣例
- t_ex[0, 0] = 1;
- t_ex[0, 1] = 0;
- t_ex[0, 2] = 1;
- t_ex[1, 0] = 0;
- t_ex[1, 1] = 1;
- t_ex[1, 2] = 0;
-
- double[] Delta_Out = new double[n_out];//輸出單元誤差
- double[] Delta_Hidden = new double[n_hidden];//隱藏單元誤差
-
- double[] O_Out = new double[n_out];//輸出單元的輸出
- double[] O_Hidden = new double[n_hidden];//隱含單元的輸出
-
- double[,] W_Out = new double[n_out,n_hidden + 1];//輸出單元的權值
- double[,] W_Hidden = new double[n_hidden,n_in + 1];//隱含單元的權值
-
- double[,] Delta_W_Out = new double[n_out,n_hidden + 1];//輸出單元的權值差
- double[,] Delta_W_Hidden = new double[n_hidden,n_in + 1];//隱含單元的權值差
- //初始化所有網絡權值為0.1
- for (int i = 0; i < n_out;i++ )
- {
- for (int j = 0;j < n_hidden + 1;j++)
- {
- W_Out[i,j] = 0.1;
- Delta_W_Out[i,j] = 0;
- }
- }
- for (int i = 0; i < n_hidden; i++)
- {
- for (int j = 0; j < n_in + 1;j++ )
- {
- W_Hidden[i,j] = 0.1;
- Delta_W_Hidden[i,j] = 0;
- }
- }
- //迭代進行訓練
- bool over = true;
- int itera_time = 0;//迭代次數
-
- while (over)
- {
- //進行訓練
- for (int i = 0; i < row;i++ )
- {
- //計算隱含層單元的輸出
- double net = 0;
- for (int j = 0; j < n_hidden; j++)
- {
- net = W_Hidden[j, 0];
- //計算輸出值
- for (int r = 1; r < n_in + 1; r++)
- {
- net += W_Hidden[j, r] * t_ex[i, r - 1];
- }
- O_Hidden[j] = 1.0 / (1 + Math.Exp(-net));
- }
- //計算輸出層單元的輸出
- for (int j = 0; j < n_out;j++ )
- {
- net = W_Out[j,0];
- for (int r = 1; r < n_hidden + 1;r++ )
- {
- net += W_Out[j,r] * O_Hidden[r - 1];
- }
- O_Out[j] = 1.0 / (1 + Math.Exp(-net));
- }
- //計算輸出層單元的誤差項
- for (int j = 0; j < n_out;j++ )
- {
- Delta_Out[j] = O_Out[j] * (1 - O_Out[j]) * (t_ex[i,n_in + j] - O_Out[j]);
- }
- //計算隱含層單元的誤差項
- for (int j = 0;j < n_hidden;j++)
- {
- double sum_weight = 0;
- for (int k = 0;k < n_out;k++)
- {
- for (int h = 0;h < n_hidden + 1;h++)
- {
- sum_weight += Delta_Out[k] * W_Out[k,h];
- }
- }
- Delta_Hidden[j] = O_Hidden[j] * (1 - O_Hidden[j]) * sum_weight;
- }
- //更新每個網絡單元的權值
- //更新輸出層的權值
- for (int j = 0;j < n_out;j++)
- {
- Delta_W_Out[j, 0] = eta * Delta_Out[j] + alfa * Delta_W_Out[j, 0];
- W_Out[j, 0] = W_Out[j, 0] + Delta_W_Out[j, 0];
-
- for (int k = 1; k < n_hidden + 1;k++ )
- {
- Delta_W_Out[j, k] = eta * Delta_Out[j] * O_Hidden[k - 1] + alfa * Delta_W_Out[j, k];
- W_Out[j, k] = W_Out[j, k] + Delta_W_Out[j, k];
- }
- }
- //更新隱含層的權值
- for (int j = 0; j < n_hidden; j++)
- {
- Delta_W_Hidden[j, 0] = eta * Delta_Hidden[j] + alfa * Delta_W_Hidden[j, 0];
- W_Hidden[j, 0] = W_Hidden[j, 0] + Delta_W_Hidden[j, 0];
- for (int k = 1; k < n_in + 1;k++ )
- {
- Delta_W_Hidden[j, k] = eta * Delta_Hidden[j] * t_ex[i, k - 1] + alfa * Delta_W_Hidden[j, k];
- W_Hidden[j, k] = W_Hidden[j, k] + Delta_W_Hidden[j, k];
- }
- }
- }
-
- //訓練1000次結束循環
- itera_time++;
- if (itera_time == 1000)over = false;
- }
-
- //輸出訓練後的權值
- Console.WriteLine("輸出層權值:");
- for (int i = 0; i < n_out; i++)
- {
- for (int j = 0; j < n_hidden + 1;j++ )
- {
- Console.WriteLine(W_Out[i,j]);
- }
- }
- Console.WriteLine("隱含層權值:");
- for (int i = 0; i < n_hidden; i++)
- {
- for (int j = 0; j < n_in + 1;j++ )
- {
- Console.WriteLine(W_Hidden[i,j]);
- }
- }
- }
- }