我正在尝试用Java编写一个简单的反向传播ANN实现,我的输出非常奇怪。人工神经网络有一个输入层,有两个节点(输入向量中每个值一个),一个隐藏层有4个节点(我已经尝试了更多无效)和一个输出层有3个节点。三个输出节点代表三种可能的数据分类,采用“一热”编码。
ANN的一些输入格式如下:
0.020055 0.40759 2
0.020117 0.14934 3
0.020117 0.25128 3
0.020262 1.6068 1
以2位小数作为2个输入,整数是所需的分类(1-3)。
使用列表中的每个可能的数据组合训练ANN后,我得到的所有输出都是这样的,小数作为三个输出节点的输出
0.11237534579646044 0.15172262242962917 0.7906017313009316 2
0.13686775670201043 0.1774606939461421 0.7656339988150088 3
0.13554918638846133 0.1761024282314506 0.766924262279491 3
0.06185317503169881 0.09410559150503017 0.8516964148498476 1
我写的方式,每一行应该显示一个“高”值(由于S形函数接近0.95),其余的应该是“低”(接近0.05)。
以下是我为计算最终输出值而编写的方法:
public static double [] testANN(double [] input, List<BPNode> hiddenLayer, List <BPNode> outputLayer){
double [] outInputs = new double[hiddenLayer.size()];
double [] results = new double[outputLayer.size()];
for(int i = 0; i<hiddenLayer.size(); i++){
BPNode node = hiddenLayer.get(i);
node.inputs = input.clone();
outInputs[i] = node.getOutput();
}
for(int i = 0; i<outputLayer.size(); i++){
BPNode node = outputLayer.get(i);
node.inputs = outInputs.clone();
results[i] = node.getOutput();
}
return results;
}
以下是使用反向传播算法训练ANN的方法:
public static void trainANN(double [] input, int desired, List<BPNode> hiddenLayer, List <BPNode> outputLayer){
double [] d = new double[outputLayer.size()];
d[0] = desired==1 ? 0.95 :0.05;
d[1] = desired==2 ? 0.95 :0.05;
d[2] = desired==3 ? 0.95 :0.05;
double [] [] weights = new double[outputLayer.size()][hiddenLayer.size()];
double [] output = testANN(input,hiddenLayer,outputLayer);
double [] del = new double[outputLayer.size()];
for(int i = 0; i<outputLayer.size(); i++){
del[i] = (d[i]-output[i])*output[i]*(1-output[i]);
for (int j = 0; j<outputLayer.get(i).weights.length; j++){
weights[i][j] = outputLayer.get(i).weights[j];
outputLayer.get(i).weights[j]+=0.2*del[i]*outputLayer.get(i).inputs[j];
}
}
for(int i = 0; i<hiddenLayer.size(); i++){
double hiddenDel = 0.0;
for(int j = 0; j<outputLayer.size(); j++){
hiddenDel+=(del[j]*weights[j][i]*hiddenLayer.get(i).getOutput()*(1-hiddenLayer.get(i).getOutput()));
}
for(int j = 0; j<hiddenLayer.get(i).weights.length; j++){
hiddenLayer.get(i).weights[j]+=0.2*hiddenDel*input[j];
}
}
}
最后,这是我用来实现ANN的Node类:
public class BPNode {
public double [] inputs = new double[10];
public double [] weights = new double[10];
public BPNode(double [] w){
weights = w;
}
public double getOutput() {
double a = 0;
for(int j = 0; j<inputs.length; j++){
a += (inputs[j] * weights[j]);
}
return sigmoid(a,10.0);
}
private static double sigmoid(double x, double m)
{
return 1 / (1 + Math.exp(-x*m));
}
}
所有权重都已初始化为0.1,并且节点已放置在数组列表中。非常感谢你的帮助。
答案 0 :(得分:1)
对于任何想知道我是如何解决这个问题的人,我尝试在0和1之间随机改变权重。这表现稍好一些,但是一旦我尝试改变1和-1之间的权重,ANN就能够对85%的权重进行分类。数据正确。