多层感知器的测试方法

时间:2015-12-16 11:01:08

标签: java neural-network backpropagation

这是使用反向传播算法的多层感知器。我在codetidy.com上找到了这个代码,我想测试它。

“mlp.java”

/*****  This ANN assumes a fully connected network  *****/


import java.util.*;
import java.io.*;

public class MLP {

 static   ArrayList<Neuron> input, hidden, output;
    ArrayList<Pattern> pattern;
   static double bias;
   double learningRate;
    Random random;

    public MLP(int numInput, int numHidden, int numOutput, int rangeMin, int rangeMax, double learningRate, Random random, File f) {
        this.learningRate = learningRate;
        this.random = random;
        input = new ArrayList<Neuron>();
        hidden = new ArrayList<Neuron>();
        output = new ArrayList<Neuron>();
        pattern = readPattern(f);

        int i;

        // bias is random value between [rangeMin, rangeMax]  -->  [-1, 1]
        bias = 1;//randomDouble(rangeMin, rangeMax);

        // initialize inputs
        for (i = 0; i < numInput; i++) {
            input.add(new Neuron("x"+(i+1), 0, randomDoubleArray(numHidden, rangeMin, rangeMax)));  // set initial values to 0
        }
        // initialize hidden
        for (i = 0; i < numHidden; i++) {
            hidden.add(new Neuron("h"+(i+1), randomDoubleArray(numOutput, rangeMin, rangeMax)));
        }
        // initialize output
        for (i = 0; i < numOutput; i++) {
            output.add(new Neuron("y"+(i+1)));
        }
        // link inputs forward to hidden
        for (Neuron x : input) {
            x.connect(hidden, 1);
        }
        // link hidden
        for (Neuron h : hidden) {
            // back to inputs
            h.connect(input, 0);
            // forward to output
            h.connect(output, 1);
        }
        // link output back to hidden
        for (Neuron y : output) {
            y.connect(hidden, 0);
        }
    }

   void train() {
        int i;
        double[] error = new double[pattern.size()];
        boolean done = false;


        // main training loop
        while(!done) {

            // loop through input patterns, save error for each
            for (i = 0; i < pattern.size(); i++) {

                /*** Set new pattern ***/
                setInput(pattern.get(i).values);

                /*** Feed-forward computation ***/
                forwardPass();

                /*** Backpropagation with weight updates ***/
                error[i] = backwardPass();
            }

           boolean pass = true;
            // check if error for all runs is <= 0.05
            for (i = 0; i < error.length; i++) {
                if (error[i] > 0.05)
                    pass = false;
            }

            if (pass)  // if all cases <= 0.05, convergence reached
                done = true;
        }


    }

    void setInput(int[] values) {
        for (int i = 0; i < values.length; i++) {
            input.get(i).value = values[i];
        }
    }

    double backwardPass() {
        int i;
        double[] outputError = new double[output.size()];
        double[] outputDelta = new double[output.size()];
        double[] hiddenError = new double[hidden.size()];
        double[] hiddenDelta = new double[hidden.size()];

        /*** Backpropagation to the output layer ***/

        // calculate delta for output layer: d = error * sigmoid derivative
        for (i = 0; i < output.size(); i++) {
            // error = desired - y
            outputError[i] = getOutputError(output.get(i));

            // using sigmoid derivative = sigmoid(v) * [1 - sigmoid(v)]
            outputDelta[i] = outputError[i] * output.get(i).value * (1.0 - output.get(i).value);
        }

        /*** Backpropagation to the hidden layer ***/

        // calculate delta for hidden layer: d = error * sigmoid derivative
        for (i = 0; i < hidden.size(); i++) {
            // error(i) = sum[outputDelta(k) * w(kj)]
            hiddenError[i] = getHiddenError(hidden.get(i), outputDelta);

            // using sigmoid derivative
            hiddenDelta[i] = hiddenError[i] * hidden.get(i).value * (1.0 - hidden.get(i).value);
        }

        /*** Weight updates ***/

        // update weights connecting hidden neurons to output layer
        for (i = 0; i < output.size(); i++) {
            for (Neuron h : output.get(i).left) {
                h.weights[i] = learningRate * outputDelta[i] * h.value;
            }
        }

        // update weights connecting input neurons to hidden layer
        for (i = 0; i < hidden.size(); i++) {
            for (Neuron x : hidden.get(i).left) {
                x.weights[i] = learningRate * hiddenDelta[i] * x.value;
            }
        }

        // return outputError to be used when testing for convergence?
        return outputError[0];
    }

    void forwardPass() {
        int i;
        double v, y;

        // loop through hidden layers, determine current value
        for (i = 0; i < hidden.size(); i++) {
            v = 0;

            // get v(n) for hidden layer i
            for (Neuron x : input) {
                v += x.weights[i] * x.value;
            }

            // add bias
            v += bias;

            // calculate f(v(n))
            y = activate(v);

            hidden.get(i).value = y;
        }

        // calculate output?
        for (i = 0; i < output.size(); i++) {
            v = 0;

            // get v(n) for output layer
            for (Neuron h : hidden) {
                v += h.weights[i] * h.value;
            }

            // add bias
            v += bias;

            // calculate f(v(n))
            y = activate(v);

            output.get(i).value = y;
        }
    }

    double activate(double v) {
        return (1 / (1 + Math.exp(-v)));  // sigmoid function
    }

    double getHiddenError(Neuron j, double[] outputDelta) {
        // calculate error sum[outputDelta * w(kj)]
        double sum = 0;

        for (int i = 0; i < j.right.size(); i++) {
            sum += outputDelta[i] * j.weights[i];
        }

        return sum;
    }

    double getOutputError(Neuron k) {
        // calculate error (d - y)
        // note: desired is 1 if input contains odd # of 1's and 0 otherwise
        int sum = 0;
        double d;
        for (Neuron x : input) {
            sum += x.value;
        }

        if (sum % 2 != 0)
            d = 1.0;
        else
            d = 0.0;

        return Math.abs(d - k.value);
    }



   double[] randomDoubleArray(int n, double rangeMin, double rangeMax) {
        double[] a = new double[n];
        for (int i = 0; i < n; i++) {
            a[i] = randomDouble(rangeMin, rangeMax);
        }
        return a;
    }

    double randomDouble(double rangeMin, double rangeMax) {
        return (rangeMin + (rangeMax - rangeMin) * random.nextDouble());
    }



    ArrayList<Pattern> readPattern(File f) {
        ArrayList<Pattern> p = new ArrayList<Pattern>();

        try {

            BufferedReader r = new BufferedReader(new FileReader(f));
            String s = "";

            while ((s = r.readLine()) != null) {
                String[] columns = s.split(" ");
                int[] values = new int[columns.length];
                for (int i = 0; i < values.length; i++) {
                    values[i] = Integer.parseInt(columns[i]);
                }
                p.add(new Pattern(values));

            }
            r.close();
        }
        catch (IOException e) { }

        return p;
    }




    public static void main(String[] args) {
        Random random = new Random(1234);
        File file = new File("input.txt");
        MLP mlp = new MLP(4, 4, 1, -1, 1, 0.1, random, file);
        mlp.train();
        }
}

“neuron.java”

import java.util.ArrayList;

public class Neuron {

    String name;
    double value;
    double[] weights;
    ArrayList<Neuron> left, right;

    public Neuron(String name, double value, double[] weights) {  // constructor for input neurons
        this.name = name;
        this.value = value;
        this.weights = weights;
        right = new ArrayList<Neuron>();
    }

    public Neuron(String name, double[] weights) {  // constructor for hidden neurons
        this.name = name;
        this.weights = weights;
        value = 0;  // default initial value
        left = new ArrayList<Neuron>();
        right = new ArrayList<Neuron>();
    }

    public Neuron(String name) {  // constructor for output neurons
        this.name = name;
        value = 0;  // default initial value
        left = new ArrayList<Neuron>();
    }

    public void connect(ArrayList<Neuron> ns, int direction) {  // 0 is left, 1 is right
        for (Neuron n : ns) {
            if (direction == 0)
                left.add(n);
            else 
                right.add(n);
        }
    }
}

“pattern.java”

public class Pattern {
int [] values;

public Pattern (int [] Values)
{
    this.values=Values;
}
}

我如何计算正确和错误的分类样本?

0 个答案:

没有答案