- 第三遍看这个代码了,以前只是根据注释和命名规则去看每条代码是要干嘛,这次读了部分源码,找到了很多疑问的答案,也有还没解决的
- 先上看代码前的基础链接,基础不牢地动山摇啊
java中Set的用法
JAVA 8 :: 关键字
java泛型中<?>和有什么区别?
神经网络的 Delta 学习规则(learning rule)
delta法则(梯度下降) - 对代码的解读都在代码的注释里了
import java.util.Arrays;
import org.junit.Test;
import org.neuroph.core.NeuralNetwork;
import org.neuroph.core.data.DataSet;
import org.neuroph.core.data.DataSetRow;
import org.neuroph.core.events.LearningEvent;
import org.neuroph.core.events.LearningEventListener;
import org.neuroph.core.learning.LearningRule;
import org.neuroph.core.learning.SupervisedLearning;
import org.neuroph.nnet.Perceptron;
public class FirstPerceptron extends NeuralNetwork implements LearningEventListener {
private static final long serialVersionUID = 1L;
@Test
public void test() {
DataSet trainAndSet = new DataSet(2, 1);
trainAndSet.add(new DataSetRow(new double[] { 0, 0 }, new double[] { 0 }));
trainAndSet.add(new DataSetRow(new double[] { 0, 1 }, new double[] { 0 }));
trainAndSet.add(new DataSetRow(new double[] { 1, 0 }, new double[] { 0 }));
trainAndSet.add(new DataSetRow(new double[] { 1, 1 }, new double[] { 1 }));
DataSet trainOrSet = new DataSet(2, 1);
trainOrSet.add(new DataSetRow(new double[] { 0, 0 }, new double[] { 0 }));
trainOrSet.add(new DataSetRow(new double[] { 0, 1 }, new double[] { 1 }));
trainOrSet.add(new DataSetRow(new double[] { 1, 0 }, new double[] { 1 }));
trainOrSet.add(new DataSetRow(new double[] { 1, 1 }, new double[] { 1 }));
DataSet trainXorSet = new DataSet(2, 1);
trainXorSet.add(new DataSetRow(new double[] { 0, 0 }, new double[] { 0 }));
trainXorSet.add(new DataSetRow(new double[] { 0, 1 }, new double[] { 1 }));
trainXorSet.add(new DataSetRow(new double[] { 1, 0 }, new double[] { 1 }));
trainXorSet.add(new DataSetRow(new double[] { 1, 1 }, new double[] { 0 }));
DataSet trainNotSet = new DataSet(1, 1);
trainNotSet.add(new DataSetRow(new double[] { 0 }, new double[] { 1 }));
trainNotSet.add(new DataSetRow(new double[] { 1 }, new double[] { 0 }));
NeuralNetwork myPerceptron = new Perceptron(2, 1);
NeuralNetwork myPerceptron_not = new Perceptron(1, 1);
LearningRule lr = myPerceptron.getLearningRule();
lr.addListener(this);
LearningRule lr_tjw = myPerceptron_not.getLearningRule();
lr_tjw.addListener(this);
myPerceptron.learn(trainAndSet);
System.out.println("测试感知机AND集训练结果:");
testNeuralNetwork(myPerceptron, trainAndSet);
}
public static void testNeuralNetwork(NeuralNetwork<?> nnet, DataSet test) {
for (DataSetRow dataRow : test.getRows()) {
nnet.setInput(dataRow.getInput());
nnet.calculate();
double[] networkOutput = nnet.getOutput();
System.out.print("Input: " + Arrays.toString(dataRow.getInput()));
System.out.println(" Output: " + Arrays.toString(networkOutput));
}
}
@Override
public void handleLearningEvent(LearningEvent event) {
SupervisedLearning bp = (SupervisedLearning) event.getSource();
if (event.getEventType() != LearningEvent.Type.LEARNING_STOPPED) {
System.out.println(bp.getCurrentIteration() + ". iteration : " + bp.getTotalNetworkError());
}
}
}
- 问题1:在Perceptron类中提到了BinaryDeltaRule,百度了一下文章中有这么一段话尽管当训练样例线性可分时,感知器法则可以成功地找到一个权向量,但如果样例不是线性可分时它将不能收敛。因此,人们设计了另一个训练法则来克服这个不足,称为 delta 法则(delta rule)。如果训练样本不是线性可分的,那么 delta 法则会收敛到目标概念的最佳 近似。但是关于XOR的问题又有博客说XOR的结果表现为线性不可分,应采用更多层的网络,但是上文不是说到针对线性不可分时delta可以解决的吗?这个留待以后吧
- 线性不可分是下一节的内容,包含XOR问题的解决
- 问题2:同样是最初提到的基础链接文章里的一句话显然 delta规则要求转移函数可导这里的转移函数应该就是书上说的传输函数(transferFunction)吧,在Perceptron类中找到了下图代码,这些类型还不了解是什么
- 问题3:关于代码中learn()抽象方法的实现也有必要再去源码里找找看
- 代码的流程给我的感觉应该是创建训练集=>创建感知机=>学习规则是配置在感知机上的=>监听是设置在学习规则上个的=>感知机开始学习=>输出监听结果和最后的学习结果
- 补充:针对传输函数问题,这个枚举中的函数,参考吴岸城老师的《神经网络与深度学习》第28页,就会明白了,而且表格十分详细