代码实现第一个感知机心得

1.代码参照吴岸城老师所著的《神经网络与深度学习》第二章内容(与书中代码稍有不同,如果代码报错,请参考另一篇文章[对代码实现第一个感知机心得的再一次解读]
2.我也是写这篇博客时才发现书的前言有吴老师的GitHub,里边有
Book_Neural_network_and_deep_learning仓库,说是有部分书中代码,不过我现在怀疑买了本盗版书,书中链接都是错的
3.书中代码截图都是某个方法的片段,所以照着敲的时候会碰上各种缺失的方法或者this关键字的异常,可以百度去比较一下,这里我将提供我的可运行代码,并写一写自己从建Demo到运行中的一些体会
4.可运行代码如下:

package bzu.tjw;

import org.neuroph.core.Layer;
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;
import org.neuroph.nnet.comp.neuron.ThresholdNeuron;
import org.neuroph.nnet.learning.BinaryDeltaRule;
import org.neuroph.util.*;

import java.util.Arrays;

public class FirstPerceptron extends NeuralNetwork {

    public static void main(String[] args){
        //建立AND训练集,有两个输入和一个输出
        DataSet trainAndSet = new DataSet(2, 1);
        trainAndSet.addRow(new DataSetRow(new double[]{0, 0}, new double[]{0}));
        trainAndSet.addRow(new DataSetRow(new double[]{0, 1}, new double[]{0}));
        trainAndSet.addRow(new DataSetRow(new double[]{1, 0}, new double[]{0}));
        trainAndSet.addRow(new DataSetRow(new double[]{1, 1}, new double[]{1}));

//        建立OR训练集
        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}));

//        建立XOR训练集
        DataSet trainXorSet = new DataSet(2, 1);
        trainXorSet.addRow(new DataSetRow(new double[]{0, 0}, new double[]{0}));
        trainXorSet.addRow(new DataSetRow(new double[]{0, 1}, new double[]{1}));
        trainXorSet.addRow(new DataSetRow(new double[]{1, 0}, new double[]{1}));
        trainXorSet.addRow(new DataSetRow(new double[]{1, 1}, new double[]{0}));

//        建立感知机
        NeuralNetwork myPerceptron = new Perceptron(2, 1);

        LearningRule lr = myPerceptron.getLearningRule();
        lr.addListener(new LearningEventListener() {
            @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());
                }
            }
        });
//        训练AND集
        myPerceptron.learn(trainAndSet);
        System.out.println("测试感知机AND集训练结果:");
        testNeuralNetwork(myPerceptron, trainAndSet);

//        训练OR集
//        myPerceptron.learn(trainOrSet);
//        System.out.println("测试感知机Or集训练结果:");
//        testNeuralNetwork(myPerceptron, trainOrSet);

//        训练XOR集
//        由于XOR输入输出情况线性不可分,将无法完成训练
//        myPerceptron.learn(trainXorSet);
//        System.out.println("测试感知机Xor集训练结果:");
//        testNeuralNetwork(myPerceptron, trainXorSet);

    }

    /**
     * 感知机代码实现
     */
    private void createNetwork(int inputNeuronsCount, int outputNeuronsCount, TransferFunctionType transferFunctionType){
        //设置神经网络类型,这里我们将类型设置为感知器
        this.setNetworkType(NeuralNetworkType.PERCEPTRON);

        //初始化神经元输入刺激设置
        NeuronProperties inputNeuronProperties = new NeuronProperties();
        inputNeuronProperties.setProperty("transferFunction",TransferFunctionType.LINEAR);

        //创建输入刺激
        Layer inputLayer = LayerFactory.createLayer(inputNeuronsCount,inputNeuronProperties);
        this.addLayer(inputLayer);

        NeuronProperties outputNeuronProperties = new NeuronProperties();
        outputNeuronProperties.setProperty("neuronType", ThresholdNeuron.class);
        outputNeuronProperties.setProperty("thresh",new Double(Math.abs(Math.random())));
        outputNeuronProperties.setProperty("transferFunction",transferFunctionType);

        //为TransferFunctionType.LINEAR传输函数设置倾斜属性
        outputNeuronProperties.setProperty("transferFunction.slop",new Double(1));

        //create一个神经元的输出
        Layer outputLayer = LayerFactory.createLayer(outputNeuronsCount,outputNeuronProperties);
        this.addLayer(outputLayer);

        //在输入和输出层中建立全连接
        ConnectionFactory.fullConnect(inputLayer,outputLayer);

        //为神经网络设置默认输入输出
        NeuralNetworkFactory.setDefaultIO(this);
        this.setLearningRule(new BinaryDeltaRule());
    }

    public static void testNeuralNetwork(NeuralNetwork nnet, DataSet tset) {

        for (DataSetRow dataRow : tset.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) );
        }
    }

}

在这里插入图片描述5.这段代码将课本的AND、OR、XOR学习放到了一起,为了结果明显建议运行时单独对某一个规则进行测试,可以看到经过四条训练数据的训练,感知机可以无误地对AND和OR运算训练集中的输入做出响应但是XOR运算的学习却无法完成,迭代不止。这与运算本身性质有关,XOR的结果表现为线性不可分,用简单的感知机模型是无法完成训练的,当采用更多层的网络。
6.项目构建时,直接把所有neuroph-2.94的包和doc导入就好了,13M也不大,以避免项目中可能出现的包缺失
7.如果只导入neuroph-2.94相关的包,项目运行时会报错

Exception in thread "main" java.lang.NoClassDefFoundError: org/slf4j/LoggerFactory at org.ap

还需要导入需要 log4j 和slf4 两个JAR包
自己导包的时候如果报

java.lang.NoClassDefFoundError: org/apache/log4j/Level

可能是多导入了slf4j-log4j12-1.7.26.jar包
8.至于里边涉及到的方法,字面意思比较容易理解,去官方的开发手册查了查,但是介绍写的都很简洁,一般就只是一句话的描述,跟踪到源码里脑子就直接炸了
在这里插入图片描述
9.实现后的心得感悟:根据书中的代码注释和讲解,感觉代码的思路比较清晰,但是对代码为什么要这么写,结果又是怎么得出的就比较迷惑了,而且既然是逻辑运算,举一反三就仿照着加了个NOT试了试
在这里插入图片描述
改后的代码如下,采用Junit测试

package bzu.tjw;

import org.junit.Test;
import org.neuroph.core.Layer;
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;
import org.neuroph.nnet.comp.neuron.ThresholdNeuron;
import org.neuroph.nnet.learning.BinaryDeltaRule;
import org.neuroph.util.*;

import java.util.Arrays;

public class FirstPerceptron extends NeuralNetwork implements LearningEventListener{

    @Test
    public void test(){
        //建立AND训练集,有两个输入和一个输出
        DataSet trainAndSet = new DataSet(2, 1);
        trainAndSet.addRow(new DataSetRow(new double[]{0, 0}, new double[]{0}));
        trainAndSet.addRow(new DataSetRow(new double[]{0, 1}, new double[]{0}));
        trainAndSet.addRow(new DataSetRow(new double[]{1, 0}, new double[]{0}));
        trainAndSet.addRow(new DataSetRow(new double[]{1, 1}, new double[]{1}));

//        建立OR训练集
        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}));

//        建立XOR训练集
        DataSet trainXorSet = new DataSet(2, 1);
        trainXorSet.addRow(new DataSetRow(new double[]{0, 0}, new double[]{0}));
        trainXorSet.addRow(new DataSetRow(new double[]{0, 1}, new double[]{1}));
        trainXorSet.addRow(new DataSetRow(new double[]{1, 0}, new double[]{1}));
        trainXorSet.addRow(new DataSetRow(new double[]{1, 1}, new double[]{0}));

        //        建立NOT训练集
        DataSet trainNotSet = new DataSet(1, 1);
        trainNotSet.addRow(new DataSetRow(new double[]{0}, new double[]{1}));
        trainNotSet.addRow(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);
//        训练AND集
//        myPerceptron.learn(trainAndSet);
//        System.out.println("测试感知机AND集训练结果:");
//        testNeuralNetwork(myPerceptron, trainAndSet);

//        训练OR集
//        myPerceptron.learn(trainOrSet);
//        System.out.println("测试感知机Or集训练结果:");
//        testNeuralNetwork(myPerceptron, trainOrSet);

//        训练XOR集
//        由于XOR输入输出情况线性不可分,将无法完成训练
//        myPerceptron.learn(trainXorSet);
//        System.out.println("测试感知机Xor集训练结果:");
//        testNeuralNetwork(myPerceptron, trainXorSet);

//        训练NOT集
        myPerceptron_not.learn(trainNotSet);
        System.out.println("测试感知机Not集训练结果:");
        testNeuralNetwork(myPerceptron_not, trainNotSet);

    }

    /**
     * 感知机代码实现
     */
    private void createNetwork(int inputNeuronsCount, int outputNeuronsCount, TransferFunctionType transferFunctionType){
        //设置神经网络类型,这里我们将类型设置为感知器
        this.setNetworkType(NeuralNetworkType.PERCEPTRON);

        //初始化神经元输入刺激设置
        NeuronProperties inputNeuronProperties = new NeuronProperties();
        inputNeuronProperties.setProperty("transferFunction",TransferFunctionType.LINEAR);

        //创建输入刺激
        Layer inputLayer = LayerFactory.createLayer(inputNeuronsCount,inputNeuronProperties);
        this.addLayer(inputLayer);

        NeuronProperties outputNeuronProperties = new NeuronProperties();
        outputNeuronProperties.setProperty("neuronType", ThresholdNeuron.class);
        outputNeuronProperties.setProperty("thresh",new Double(Math.abs(Math.random())));
        outputNeuronProperties.setProperty("transferFunction",transferFunctionType);

        //为TransferFunctionType.LINEAR传输函数设置倾斜属性
        outputNeuronProperties.setProperty("transferFunction.slop",new Double(1));

        //create一个神经元的输出
        Layer outputLayer = LayerFactory.createLayer(outputNeuronsCount,outputNeuronProperties);
        this.addLayer(outputLayer);

        //在输入和输出层中建立全连接
        ConnectionFactory.fullConnect(inputLayer,outputLayer);

        //为神经网络设置默认输入输出
        NeuralNetworkFactory.setDefaultIO(this);
        this.setLearningRule(new BinaryDeltaRule());
    }

    public static void testNeuralNetwork(NeuralNetwork nnet, DataSet tset) {

        for (DataSetRow dataRow : tset.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());
        }
    }
}

10.文章参照:
Neuroph训练简单逻辑运算感知机
另附:
Neuroph多层感知机训练XOR

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值