有了上篇的基本理论之后,我们可以尝试去代码实现基本的一个BPN算法。
具体的算法代码,后面给出。就像前面说过的,有几个东西需要调节注意的,学习率和惯性因,初始权值和阈值,收敛误差界值Emin。这几个问题其实是很多类似算法都遇到的问题,细节这里不多说。下面给出一个简单的java实现,具体的学习过程没有完全写下来。
public class NN { public int inputNum;//输入节点数 public int hiddenNum;//隐层节点数 public int outputNum;//输出节点数 public double inputs[] = new double[inputNum];//输入向量 public double outputs[] = new double[outputNum];//输出结果 public double hiddens_prev[] = null;//隐层计算结果 public double outputs_prev[] = null;//输出计算结果 public double ih_w[][] = null;//输入-隐层权值 public double ho_w[][] = null;//隐层-输出权值 public double hiddens_err[] = null;//隐层误差 public double outputs_err[] = null;//输出误差 public static final double rate = 0.9;//学习速率 public void init() { hiddens_prev = new double[hiddenNum]; outputs_prev = new double[outputNum]; ih_w = new double[inputNum][hiddenNum]; ho_w = new double[hiddenNum][outputNum]; hiddens_err = new double[hiddenNum]; outputs_err = new double[outputNum]; for (int i = 0; i < inputNum; i++) { ih_w[i] = new double[hiddenNum]; for (int h = 0; h < hiddenNum; h++) { hiddens_err[h] = 0; ih_w[i][h] = Math.random() - 0.5; } } for (int h = 0; h < hiddenNum; h++) { ho_w[h] = new double[outputNum]; for (int o = 0; o < outputNum; o++) { outputs_err[o] = 0; ho_w[h][o] = Math.random() - 0.5; } } } public void forward() { for (int h = 0; h < hiddenNum; h++) { double d = 0; for (int i = 0; i < inputNum; i++) { d += ih_w[i][h] * inputs[i]; } hiddens_prev[h] = active(d); } for (int o = 0; o < outputNum; o++) { double d = 0; for (int h = 0; h < hiddenNum; h++) { d += ho_w[h][o] * hiddens_prev[h]; } outputs_prev[o] = active(d); } } public void calcError() { // output error for (int o = 0; o < outputNum; o++) { outputs_err[o] = outputs_prev[o] * (1 - outputs_prev[o]) * (outputs[0] - outputs_prev[o]); } // hidden error for (int h = 0; h < hiddenNum; h++) { double d = 0; for (int o = 0; o < outputNum; o++) { d += outputs_err[0] * ho_w[h][o]; } hiddens_err[h] = hiddens_prev[h] * (1 - hiddens_prev[h]) * d; } } public void updateWeight() { for (int h = 0; h < hiddenNum; h++) { for (int o = 0; o < outputNum; o++) { ho_w[h][o] += rate * outputs_err[o] * hiddens_prev[h]; } } for (int i = 0; i < inputNum; i++) { for (int h = 0; h < hiddenNum; h++) { ih_w[i][h] += rate * hiddens_err[h] * inputs[i]; } } } //激活函数,使用simoid函数 public double active(double d) { return 1 / (1 + Math.exp(-d)); } public static void main(String[] args) { NN n = new NN(); n.inputNum = 2; n.hiddenNum = 3; n.outputNum = 1; n.inputs = new double[] { 1, 1 }; n.outputs = new double[] { 1 }; n.init(); for (int i = 0; i < 100; i++) { n.forward(); n.calcError(); n.updateWeight(); print(n.outputs_prev); } } public static void print(double d[]) { for (double dd : d) { System.out.print(dd + ","); } System.out.println(); } }
整个过程还是比较直接的,关键是有助于理解BP算法的过程,代码只有简单的注释,通过函数名称就知道是干什么的。
除了自己代码实现外,还有很多工具可以帮助我们实现和理解神经网络算法,现在举例说明下。
1.,R神经网络算法分类
2,SPSS神经网络分类