Perceptron auf logischem AND trainieren

frager2345

Aktives Mitglied
Hey, wir haben Code bekommen und sollen diesen Ergänzen. Jedoch funktioniert meiner nicht. Ich finde den Fehler einfach nicht.
Hier einmal die Klasse Perceptron:
Java:
public class Perceptron {
    private double THRESHOLD;
    private double alpha;
    private double[] weights;
    private int class_1;
    private int class_2;

    /**
     *
     * @param alpha - learning rate
     * @param threshold - classifier threshold
     * @param num_weights - number of weights
     * @param class_1 - output value for class 1
     * @param class_2 - output value for class 2
     * @param weights - initial weights
     */
    public Perceptron(double alpha, double threshold, int num_weights, int class_1, int class_2, double[] weights) {
        //TODO: Ininitalisieren Sie alle übergebenen Variablen ->  ✅

        this.THRESHOLD = threshold;
        this.alpha = alpha;
        this.class_1 = class_1;
        this.class_2 = class_2;
        this.weights = weights;

    }

    /**
     *
     * @return current threshold to be used
     */
    public double getThreshold() {
        return this.THRESHOLD;
    }
    /**
     *
     * @return current weights for neuron
     */
    public double[] getWeights() {
        return this.weights.clone();
    }

    /**
     * compute weighted sum of input and current weights
     * @param input - input values
     * @return
     */
    public double weightedSum(int[] input) {
        //TODO: Berechnen Sie den Eingabewert des Neurons mit der gewichteten Summe der eingehenden Kanten und der Gewichte ->  ✅

        if (input.length != weights.length) {
            throw new IllegalArgumentException("Die Anzahl der Eingabewerte stimmt nicht mit der Anzahl der Gewichte überein.");
        }

        double sum = 0.0;
        for (int i = 0; i < input.length; i++) {
            sum += input[i] * weights[i] ;
        }


        return sum;
    }

    /**
     * run perceptron and return result
     * @param input - input values
     * @return
     */
    public int run(int[] input) {


        //TODO: Berechnen Sie den Ausgabewert des Perzeptrons, d.h. Berechnen Sie die gewichtete Summe und aktivieren Sie diese ->  ✅

        double weightedSum = weightedSum(input);

        return activate(weightedSum); //TODO: return ->  ✅
    }

    /**
     * update weights with last error
     * @param input - single data entity
     * @param error - last computed error
     * @return new weight vector
     */
    public void adjust(int[] input, double error) {
        //TODO: Berechnen Sie die Updates für alle Gewichte in Abhängigkeit von Alpha, dem Netzfehler und dem Input ->  ✅

        if (input.length != weights.length) {
            throw new IllegalArgumentException("Die Anzahl der Eingabewerte stimmt nicht mit der Anzahl der Gewichte überein.");
        }


        for (int i = 0; i < weights.length; i++) {
            weights[i] = weights[i] + (alpha * input[i] * error);
        }
    }


    /**
     * apply activation function to computed weighted sum
     * @param weightedSum
     * @return
     */
    public int activate(double weightedSum) {
        //TODO: Implementieren Sie die Aktivierung auf Basis der "Step Function" in Abhänggikeit des Threshold ->  ✅
        if(weightedSum >= THRESHOLD){
            return class_1;
        }
        return class_2; //TODO: return ->  ✅
    }
}

Hier einmal die Klasse DriveAND, hier wird das Training durchgeführt:
Code:
public class DriverAnd {
    public static double THRESHOLD = 0.2; // TODO: Verwenden Sie den Threshold aus dem Skript ->  ✅
    public static double alpha = 0.1; // TODO: Verwenden Sie den Alphawert aus dem Skript ->  ✅
    public static double[] weights = new double[] {0.3, -0.1}; // TODO: Verwenden Sie die initialen Gewichte aus dem Skript ->  ✅
    public static int inputs = 2;

    //Training and testing data ->  ✅
    static int[][][] data = new int[][][] {
            {{0, 0}, {0}},
            {{0, 1}, {0}},
            {{1, 0}, {0}},
            {{1, 1}, {1}},
    };
    public static void main(String[] args) {
        //TODO: Initialisieren Sie das Perzeptron
        int num_weights = weights.length;

        Perceptron perceptron = new Perceptron(alpha, THRESHOLD, num_weights, 1, 0, weights);



        //TODO: Implementieren Sie die Trainingschleife. Verwenden Sie "errorFlag", um die Schleife abzubrechen, sobald kein Fehler mehr auftritt, d.h. sobald alle Ausgaben korrekt sind. task done : ->  ✅
        int episode = 0;
        boolean errorFlag = true;
        //training
        while(errorFlag) {
            printHeading(episode++, inputs);
            errorFlag = false;
            for(int i = 0; i < data.length; i++) {

                double[] weightsBeforeAjust = perceptron.getWeights();

                int[] input = data[i][0];

                //TODO: Berechnen Sie die Netzausgabe ->  ✅

                int y = perceptron.run(input);


                //TODO: Berechnen Sie den Netzfehler ->  ✅

                double error = data[i][1][0] - y;

                //TODO: Adjustieren Sie die Gewichte und geben Sie die initialen Gewichte, die Netzausgabe, sowie die adjustierten Gewichte aus
                //printVector(data[i], initiale Gewichte vor Adjustierung, Netzausgabe, Netzfehler, adjustierte Gewichte);  ->  ✅

                perceptron.adjust(input, error);
                printVector(data[i],  weightsBeforeAjust , y, error, perceptron.getWeights());

                if ( data[i][1][0] != y ){
                    errorFlag = true;
                }
            }
        }
    }

    /**
     * Use this function to print header information for each episode
     * @param episode - episode counter
     * @param numOfWeights - number of weights used
     */
    public static void printHeading(int episode, int numOfWeights) {
        System.out.print("\n");
        IntStream.range(0,  16+3*numOfWeights*6).forEach(i -> System.out.print("="));
        System.out.print(String.format("Episode %s", episode));
        IntStream.range(0,  16+18*numOfWeights).forEach(i -> System.out.print("="));
        System.out.println();
        IntStream.range(0,  numOfWeights).forEach(i -> System.out.print(String.format("   w%s   |", i++)));
        IntStream.range(0,  numOfWeights).forEach(i -> System.out.print(String.format("   x%s   |", i++)));
        System.out.print("target result   |   result   |   error   |");
        IntStream.range(0,  numOfWeights).forEach(i -> System.out.print(String.format("   adjusted w%s   |", i++)));
        System.out.println();
        IntStream.range(0,  41+36*numOfWeights).forEach(i -> System.out.print("-"));
        System.out.println();
    }

    /**
     * Use this function to print learning information
     * @param data - current used training data
     * @param weights - weights before applying the training step
     * @param result - output of the neural network
     * @param error - error of the neural network
     * @param adjusted - new adjusted weights (after applying the training step)
     */
    public static void printVector(int[][] data, double[] weights, int result, double error, double[] adjusted) {

        IntStream.range(0,  weights.length).forEach(i -> System.out.print(String.format(" %s%.2f  |", weights[i] >= 0 ? " " : "", weights[i])));
        IntStream.range(0,  data[0].length).forEach(i -> System.out.print(String.format("  %s%s    |", data[0][i] >= 0 ? " " : "", data[0][i])));
        System.out.print(String.format("       %s%s       |     %s%s     |    %s%.2f  |", data[1][0] >= 0 ? " " : "", data[1][0], result >= 0 ? " " : "", result, error >= 0 ? " " : "", error));
        IntStream.range(0,  adjusted.length).forEach(i -> System.out.print(String.format("      %s%.2f      |", adjusted[i] >= 0 ? " " : "", adjusted[i])));
        System.out.println();
    }
}

Die grünen Häckchen sollen einfach nur da sein um kenntlich zu machen, was ich schon erledigt hab
 

Oben