EDITOR: KJ021320

BLOG: http://blog.csdn.net/kj021320

TEAM: I.S.T.O

好久没写东西了,随便记一下~~如果不记录忘记了真是很浪费啊~

下面贴的这个是JAVA写的反向传播神经网络,面向对象,把神经元和连结都抽象成对象。

其实这个已经不是什么新奇的玩意了,对于分类 回归而言 神经网络是一个选择但并不一定是最好的选择。

类似很多进化计算都存在同样的问题,如GA遗传算法。

NN迭代学习过后,每个神经元权重的含义很难被理解,所以才有人提出神经网络的规则抽取,如何对网络的神经元进行裁剪

接下来就是NN 的学习过程中,最具有价值的

1. 计算 delta规则 ,一般采用梯度下降法等等(有本书说得不错的《最优化理论与方法》讲了很多牛顿法 最速下降法等等)

2. 激活函数,其实这个最终目的就是让数据2值化,神经网络设计一书上标准的方式,其实你也可以通过这个思想自己搞一个

3. 当然是NN的整个数据结构模型,模拟了大脑神经的信息传递过程。

以下代码 main函数是使用DEMO

package cn.isto.ai.algorithm.nn;
import java.util.HashMap;
import java.util.Random;
import java.util.Set;
import java.util.Map.Entry;

/**
 * JAVA 反向传输神经网络
 * @author kj021320  , codeby 2008.12.10
 *
 */
public class JavaBackPropagationNeuralNetwork {
    /**
     * 神经元
     */
    public class Neuron {
        HashMap<Integer, Link> target = new HashMap<Integer, Link>();// 连接其他神经元的
        HashMap<Integer, Link> source = new HashMap<Integer, Link>();// 被其他神经元连接的
        double data = 0.0;
        public Link sourceGet(int index) {
            return source.get(index);
        }
        public Link targetGet(int index) {
            return target.get(index);
        }
        public boolean targetContains(Link l) {
            return target.containsValue(l);
        }
        public boolean sourceContains(Link l) {
            return source.containsValue(l);
        }
        public Link sourceLink(int index, Link l) {
            if (l.linker != this) {
                l.setLinker(this);
            }
            return source.put(index, l);
        }
        public Link targetLink(int index, Link l) {
            if (l.owner != this) {
                l.setOwner(this);
            }
            return target.put(index, l);
        }
    }

/**
     * 神经链
     */
    public class Link {
        Neuron owner;
        public void setOwner(Neuron o) {
            owner = o;
            if (!o.targetContains(this)) {
                o.targetLink(o.target.size(), this);
            }
        }
        public Link() {
            weight = rand(-1, 1);
        }
        public void setLinker(Neuron o) {
            linker = o;
            if (!o.sourceContains(this)) {
                o.sourceLink(o.source.size(), this);
            }
        }
        @Override
        public String toString(){
            return super.toString()+" weight:"+weight;
        }
        Neuron linker;
        double weight;
    }

Random random = new Random();
    {
        random.setSeed(System.nanoTime());
    }
    Neuron[] inputnode;    //输入层神经元
    Neuron[] hiddennode;    //隐含层神经元
    Neuron[] outputnode;    //输出层神经元
    double learnrate;// 学习速度
    double threshold;// 阀值,误差允许度

private final int inputCount;
    private final int hiddenCount;
    private final int outputCount;
    /**
     *
     * @param input        输入层的神经元个数
     * @param hidden    隐含层的神经元个数
     * @param output    输出层的神经元的个数
     */
    public JavaBackPropagationNeuralNetwork(int input, int hidden, int output) {
        inputCount = input;
        hiddenCount = hidden;
        outputCount = output;
        build();
    }
    public void reBuildNeuralNetwork(){
        build();
    }
    private void build(){
        inputnode = new Neuron[inputCount+1];
        hiddennode = new Neuron[hiddenCount];
        outputnode = new Neuron[outputCount];
        initNeurons(inputnode);
        initNeurons(hiddennode);
        initNeurons(outputnode);
        makeLink(inputnode, hiddennode);
        makeLink(hiddennode, outputnode);
    }
    /**
     * 思考方法
     * @param inputs    前馈层神经个数相符的浮点数    -1~1之间
     * @return            思考后的结果,个数与后端的神经个数相符,每个浮点为-1~1之间
     */
    public double[] thinking(double[] inputs) {
        /**把数据映射到前馈层的神经元里面*/
        makeNeuron(inputnode, inputs);
        /**通过每个神经链的权重 从隐藏层计算到最终输出层的值*/
        thinking();
        /**把输出层的值映为return的double数组*/
        return makeMatrix();
    }
    public double[][] batchThinking(double[][] inputs){
        double[][] ret = new double[inputs.length][];
        for(int i = 0; i< inputs.length ; i++){
            makeNeuron(inputnode, inputs[i]);
            thinking();
            ret[i]=makeMatrix();
        }
        return ret;
    }
    /**
     * 总体训练
     * @param inputs       
     * @param outputs       
     * @param learnrate        学习精细度
     * @param error            容许误差
     * @param maxlearn        最大学习次数
     * @return 是否完成训练
     */
    public boolean train(double[][] inputs, double[][] outputs, double learnrate,
            double error,int maxlearn) {
        this.learnrate = learnrate;
        this.threshold = error;
        boolean complete = false;
        int count = 0;
        double e =0;
        while (!complete) {
            count++;
            e = 0;
            complete = true;
            for (int size = 0; size < inputs.length; size++) {
                e += learn(inputs[size], outputs[size]);
                if (e > threshold) {
                    complete = false;
                }
            }
            if(count>=maxlearn){
                System.err.println("convergence fail  error:"+e);
                return false;
            }
        }
        System.out.println("convergence success    error:"+e);
        return true;
    }

/**
     * 单次学习
     *
     * @param input
     * @param output
     * @return 误差
     */
    private double learn(double[] input, double[] output) {
        /**把数据映射到前馈层的神经元里面*/
        makeNeuron(inputnode, input);
        /**通过每个神经链的权重 从隐藏层计算到最终输出层的值*/
        thinking();
        /**误差计算*/
        return evolutionComputing(output);
    }

private void thinking() {
        transmitComputing(hiddennode);
        transmitComputing(outputnode);
    }

/**
     * 神经元传输计算
     *
     * @param ns
     */
    private void transmitComputing(Neuron[] ns) {
        for (Neuron ne : ns) {
            double sum = 0.0;
            Set<Entry<Integer, Link>> linkset = ne.source.entrySet();
            for (Entry<Integer, Link> ent : linkset) {
                Link l = ent.getValue();
                Neuron n = l.owner;
                // 这里是重点,计算神经元*神经权重
                sum += n.data * l.weight;
            }
            // 计算完毕后通过 S型激活函数把数据存储在隐藏层的神经节点上
            ne.data = sigmoid(sum);
        }
    }
    /**
     * 最速梯度下降法 来计算 delta规则
     * @param datas
     * @return
     */
    private double evolutionComputing(double[] datas) {
        double[] output_deltaDatas = new double[outputnode.length];
        double totalError = 0.0;
        for (int i = 0; i < outputnode.length; i++) {
            /**
             * Erri = Ti – Oi O is the predicted output T is the correct output
             * Δi = Erri * g’(ini) g’ is the derivative of the activation
             * function g
             */
            output_deltaDatas[i] = (datas[i] - outputnode[i].data)
                    * sigmoidDerivative(datas[i]);
        }

double[] hidden_deltaDatas = new double[hiddennode.length];
        for (int i = 0; i < hiddennode.length; i++) {
            /**
             * Δj = g’(inj) * Σi(Wj,i * Δi)
             */
            double error = 0.0;
            Set<Entry<Integer, Link>> linkSet = hiddennode[i].target.entrySet();
            for (Entry<Integer, Link> ent : linkSet) {
                error += output_deltaDatas[ent.getKey()]
                        * ent.getValue().weight;
            }
            hidden_deltaDatas[i] = sigmoidDerivative(hiddennode[i].data)
                    * error;
        }
        /**
         * Wj,i = Wj,i + α * Hj * Δi    Hj is the activation of the hidden unit
         */
        for (int i = 0; i < hiddennode.length; i++) {
            Set<Entry<Integer, Link>> linkSet = hiddennode[i].target.entrySet();
            for (Entry<Integer, Link> ent : linkSet) {
                Link hidden2output = ent.getValue();
                hidden2output.weight += output_deltaDatas[ent.getKey()]
                        * hiddennode[ent.getKey()].data * learnrate;
                //System.out.println("hidden2output:"+hidden2output);
            }
        }
        //System.out.println();
        /**
         * Wk,j = Wk,j + α * Ik * Δj Ik is the activation of the input unit
         */
        for (int i = 0; i < inputnode.length; i++) {
            Set<Entry<Integer, Link>> linkSet = inputnode[i].target.entrySet();
            for (Entry<Integer, Link> ent : linkSet) {
                Link input2hidden = ent.getValue();
                input2hidden.weight += hidden_deltaDatas[ent.getKey()]
                        * inputnode[i].data * learnrate;
                //System.out.println("inputnode[i].data:"+inputnode[i].data+"input2hidden:"+input2hidden);
            }
        }
        //System.out.println();
        /**
         * E = 1/2 Σi((Ti – Oi)^2)
         */
        for (int i = 0; i < outputnode.length; i++) {
            double temp = outputnode[i].data - datas[i];
            totalError +=  temp * temp;
        }
        return totalError * 0.5;
    }

/**
     * 把数据映射到每个神经元里面
     *
     * @param neurons
     * @param datas
     */
    private void makeNeuron(Neuron[] neurons, double[] datas) {
        for (int len = 0; len < neurons.length; len++) {
            if(len >= datas.length){
                neurons[len].data = 1.0;
            }else{
                neurons[len].data = datas[len];
            }
        }
    }

/**
     * 把output的神经元数据映射为矩阵
     *
     * @return
     */
    private double[] makeMatrix() {
        double[] temp = new double[outputnode.length];
        for (int i = 0; i < outputnode.length; i++) {
            temp[i] = outputnode[i].data;
        }
        return temp;
    }

private void initNeurons(Neuron[] startns) {
        for (int lenN = 0; lenN < startns.length; lenN++) {
            if (startns[lenN] == null) {
                startns[lenN] = new Neuron();
            }
        }
    }

/**
     * 这里是互相交叉连接
     *
     * @param startns
     * @param endns
     */
    private void makeLink(Neuron[] startns, Neuron[] endns) {
        for (int lenN = 0; lenN < startns.length; lenN++) {
            for (int len = 0; len < endns.length; len++) {
                Link target = startns[lenN].targetGet(len);
                if (target == null) {
                    target = new Link();
                    startns[lenN].targetLink(len, target);
                }
                target.setLinker(endns[len]);
            }
        }
    }

/**
     * 这里是S型激活函数.最终目的是把所有数据都2值化
     *
     * @param x
     * @return
     */
    private double sigmoid(double x) {
        return Math.tanh(x);
    }

/*
     * calculate a random number where: a <= rand < b def rand(a, b): return
     * (b-a)*random.random() + a
     */
    private double rand(double min, double max) {
        return (max - min) * random.nextDouble() + min;
    }

// derivative of our sigmoid function
    private double sigmoidDerivative(double y) {
        // return (1.0 - sigmoid(y)) * sigmoid(y);
        // return 1.0-y*y;
        return 1.0 - sigmoid(y) * y;
    }

/**
     * @param args
     * @throws Throwable
     */
    public static void main(String[] args) throws Throwable {
        //创建一个 反向传输神经网络
        JavaBackPropagationNeuralNetwork jbpn = new JavaBackPropagationNeuralNetwork(2, 4, 1);
       
        //训练XOR
        while(!jbpn.train(
                new double[][] { new double[] { -1, -1 },new double[] { 1, 1 }, new double[] { -1, 1 },new double[] { 1, -1 } },//这个为输入值
                new double[][] { new double[] {-1},new double[] {-1},new double[] {1},new double[] {1} },//这个是监督指导结果
                0.3, 0.05,1000)){
            jbpn.reBuildNeuralNetwork();
        }
        //思考
        double[] res = jbpn.thinking(new double[] { -1, -1 });
        for(double s:res){
            System.out.println("thinking:"+s);
        }
        //批量思考
        double[][] ress = jbpn.batchThinking(new double[][] { new double[] { -0.8, -0.9 },new double[] { 0.7, 0.3 }, new double[] { -.6, .85 },new double[] { 1, -1 } });
        for(double[] s:ress){
            for(double d:s){
                System.out.print("batchThinking:"+d+"    ");
            }
            System.out.println();
        }
       
    }

}

Java Back Propagation Neural Network(JAVA反向传播神经网络)相关推荐

  1. Back-Propagation Neural Network BP反向传播网络算法

    01 网络描述 BP网络由大量简单处理单元广泛互联而成,是一种对非线性函数进行权值训练的多层映射网络.具有优良的非线性映射能力,理论上它能够以任意精度逼近任意非线性函数.本文采用BP神经网络解决下列函 ...

  2. BP神经网络(Back Propagation Neural Network)Matlab简单实现

    BP神经网络(Back Propagation Neural Network)Matlab简单实现 前言 简单了解反向传播(Backwarod Propagation)机制(链式法则) 实例分析 前向 ...

  3. 图片1---前馈神经网络+反向传播神经网络

    声明:  记录自己认为好的图片------以方便后续的使用或者是改进 来源论文:  <一种金融市场预测的深度学习模型: FEPA> (1)前馈神经网络 (2)反向传播神经网络的大致的架构- ...

  4. 反向传播神经网络 demo源码

    反向传播神经网络(有代码) 找了很多资料,觉得就这篇博客讲的最好,原文如下,有非常详细的推导过程.http://www.hankcs.com/ml/back-propagation-neural-ne ...

  5. Arduino前馈反向传播神经网络

    本文介绍了为Arduino Uno微控制器板开发的人工神经网络. 这里描述的网络是前馈反向传播网络,可能是最常见的类型. 它被认为是有监督或无监督学习的良好通用网络. 该项目的代码以Arduino S ...

  6. 反向传播神经网络(BPNN)的实现(Python,附源码及数据集)

    文章目录 一.理论基础 1.前向传播 2.反向传播 3.激活函数 4.神经网络结构 二.BP神经网络的实现 1.训练过程(BPNN.py) 2.测试过程(test.py) 3.测试结果 4.参考源码及 ...

  7. cs231n笔记5—反向传播/神经网络

    反向传播 神经网络 反向传播 问题陈述:这节的核心问题是,给定函数f(x),其中x是输入数据的向量,需要计算函数f关于x的梯度,也就是∇f(x). 反向传播是利用链式法则递归计算表达式的梯度的方法.理 ...

  8. 反向传播神经网络 BPNN

    回顾感知器学习算法,其核心思想是梯度下降法,即以训练样本被错分的程度为目标函数,训练中每次出现错误时便使权系数朝着目标函数相对于权系数负梯度方向更新,知道目标中没有被错分的样本为止. 而多层感知器模型 ...

  9. Heterogeneous Graph Neural Network(异质图神经网络)

    Heterogeneous Information Network 传统的同构图(Homogeneous Graph)中只存在一种类型的节点和边,当图中的节点和边存在多种类型和各种复杂的关系时,再采用 ...

最新文章

  1. 34岁,外企倒闭成功上岸大厂,50K,附面试秘籍
  2. 【LeetCode】13. Roman to Integer
  3. Spring5源码 - 07 Spring Bean 生命周期流程 源码解读02
  4. linux常用关机、重启、注销命令
  5. Skyscrapers (easy version)CodeForces - 1313C1(暴力)
  6. 测试驱动开发 测试前移_测试驱动开发–双赢策略
  7. 平板电脑安装软件_下载适用于华为和荣耀手机平板电脑的Googlefier GMS安装程序...
  8. 飞行姿态角度表示: heading pitch roll
  9. python发音模块-python 利用pyttsx3文字转语音过程详解
  10. 2017-2018-1 20155339 《信息安全系统设计基础》第8周学习总结
  11. LinkedIn领英帐号被封(被限制登录)的解决办法
  12. 乾颐堂军哥华为HCNP真题讲解(2017至2018版)真题更新版到来
  13. STM32官方USB库下载指南
  14. 华为面试题--字符串重排
  15. HTML教程(看完这篇就够了)
  16. 【CV】ShuffleNet:通过 GroupConv 和 ChannelShuffle 实现轻量化 CNN 架构
  17. EXcel中如何做一个组合统计图?
  18. ubuntu固定内网ip_Ubuntu14设置局域网固定IP
  19. CKEditor富文本编辑器使用
  20. ckplayer 播放视频

热门文章

  1. 数据分析-数据规范化的一些方法
  2. 24时区,GMT,UTC,DST,CST时间详解 ISO8601
  3. 开源中国 开源世界2019_2019年最受欢迎的开源新闻报道
  4. python selenium移动端网页下拉刷新
  5. 查看期刊最近的影响因子
  6. hdu4416[多串后缀自动机]
  7. win10语言栏不见了_当我把电脑的系统语言改成了西班牙语,从此打开了新世界的大门!...
  8. excel表格内容拆分_表格技巧—Excel 多行数据拆分合并的方法
  9. linux中的几种文件类型
  10. Linux终端编程--termios