轉載自: http://geek.csdn.net/news/detail/56086java
說明:我這篇博客僅僅是給上邊寫好的代碼添加「註釋」,記錄並幫助學習深度網絡算法的朋友。算法
目的:輸入數據獲得近似現實結果的響應(「深度神經網絡」算法實現:輸入的歷史數據執行邏輯體以後的響應與現實結果的誤差在預期範圍內。)數組
分析:算法計算過程:輸入層開始,從左往右計算,逐層往前直到輸出層產生結果。若是結果值和目標值有差距,再從右往左算,逐層向後計算每一個節點的偏差,而且調整每一個節點的全部權重,反向到達輸入層後,又從新向前計算,重複迭代以上步驟,直到全部權重參數收斂到一個合理值。因爲計算機程序求解方程參數和數學求法不同,通常是先隨機選取參數,而後不斷調整參數減小偏差直到逼近正確值,因此大部分的機器學習都是在不斷迭代訓練,下面咱們從程序上詳細看看該過程實現就清楚了。網絡
實現:神經網絡的算法程序實現分爲初始化、向前計算結果,反向修改權重三個過程。dom
import java.util.Random;
public class BpDeep{
public double[][] layer;//神經網絡各層節點
public double[][] layerErr;//神經網絡各節點偏差
public double[][][] layer_weight;//各層節點權重
public double[][][] layer_weight_delta;//各層節點權重動量
public double mobp;//動量係數
public double rate;//學習係數機器學習
public BpDeep(int[] layernum, double rate, double mobp){
this.mobp = mobp;
this.rate = rate;
layer = new double[layernum.length][]; //layernum.length值表示層數
layerErr = new double[layernum.length][];
layer_weight = new double[layernum.length][][];
layer_weight_delta = new double[layernum.length][][];
Random random = new Random();
for(int l=0;l<layernum.length;l++){
layer[l]=new double[layernum[l]];//初始化「l」層的位置信息
layerErr[l]=new double[layernum[l]];
if(l+1<layernum.length){
layer_weight[l]=new double[layernum[l]+1][layernum[l+1]];//初始化權重的位置信息即「l」層的位置信息,下層節點位置,權重值。
layer_weight_delta[l]=new double[layernum[l]+1][layernum[l+1]];
for(int j=0;j<layernum[l]+1;j++) //遍歷位置個數的次數
for(int i=0;i<layernum[l+1];i++) //遍歷下層節點個數的次數
layer_weight[l][j][i]=random.nextDouble();//隨機初始化權重(l層數;j位置;i下層節點位置;layer_weight[l][j][i]權重值)
}
}
}
//逐層向前計算輸出(根據輸入值初始化不一樣層面不一樣位置的節點值)
public double[] computeOut(double[] in){
for(int l=1;l<layer.length;l++){
/*
* z是截距值,針對不一樣下層節點有不一樣值
* l表示層循環,j表示位置循環,i表示計算下層節點值的循環
*/
for(int j=0;j<layer[l].length;j++){
double z=layer_weight[l-1][layer[l-1].length][j];//第"l-1"層,第"layer[l-1].length"的位置,第"j"個下層節點的權重值,z表示截距項的值
for(int i=0;i<layer[l-1].length;i++){
layer[l-1][i]=l==1?in[i]:layer[l-1][i]; //使用上層節點值(輸入層使用輸入值,隱含層使用上一層的值)
z+=layer_weight[l-1][i][j]*layer[l-1][i];
}
layer[l][j]=1/(1+Math.exp(-z));
}
}
return layer[layer.length-1]; //返回結果值數組
}
//逐層反向計算偏差並修改權重
public void updateWeight(double[] tar){
int l=layer.length-1;
for(int j=0;j<layerErr[l].length;j++)
layerErr[l][j]=layer[l][j]*(1-layer[l][j])*(tar[j]-layer[l][j]);//計算結果值的偏差值學習
while(l-->0){
for(int j=0;j<layerErr[l].length;j++){
double z = 0.0;
for(int i=0;i<layerErr[l+1].length;i++){
z=z+l>0?layerErr[l+1][i]*layer_weight[l][j][i]:0;
layer_weight_delta[l][j][i]= mobp*layer_weight_delta[l][j][i]+rate*layerErr[l+1][i]*layer[l][j];//隱含層動量調整
layer_weight[l][j][i]+=layer_weight_delta[l][j][i];//隱含層權重調整
if(j==layerErr[l].length-1){
layer_weight_delta[l][j+1][i]= mobp*layer_weight_delta[l][j+1][i]+rate*layerErr[l+1][i];//截距動量調整
layer_weight[l][j+1][i]+=layer_weight_delta[l][j+1][i];//截距權重調整
}
}
layerErr[l][j]=z*layer[l][j]*(1-layer[l][j]);//記錄偏差
}
}
}測試
public void train(double[] in, double[] tar){
double[] out = computeOut(in);
updateWeight(tar);
}
}this
下面是這個測試程序BpDeepTest.java的源碼:.net
import java.util.Arrays; public class BpDeepTest{ public static void main(String[] args){ //初始化神經網絡的基本配置 //第一個參數是一個整型數組,表示神經網絡的層數和每層節點數,好比{3,10,10,10,10,2}表示輸入層是3個節點,輸出層是2個節點,中間有4層隱含層,每層10個節點 //第二個參數是學習步長,第三個參數是動量係數 BpDeep bp = new BpDeep(new int[]{2,10,2}, 0.15, 0.8); //設置樣本數據,對應上面的4個二維座標數據 double[][] data = new double[][]{{1,2},{2,2},{1,1},{2,1}}; //設置目標數據,對應4個座標數據的分類 double[][] target = new double[][]{{1,0},{0,1},{0,1},{1,0}}; //迭代訓練5000次 for(int n=0;n<5000;n++) for(int i=0;i<data.length;i++) bp.train(data[i], target[i]); //根據訓練結果來檢驗樣本數據 for(int j=0;j<data.length;j++){ double[] result = bp.computeOut(data[j]); System.out.println(Arrays.toString(data[j])+":"+Arrays.toString(result)); } //根據訓練結果來預測一條新數據的分類 double[] x = new double[]{3,1}; double[] result = bp.computeOut(x); System.out.println(Arrays.toString(x)+":"+Arrays.toString(result)); } }