neuroph hält beim XOR lernen nicht an

  • Themenstarter Themenstarter BestGoalkeeper
  • Beginndatum Beginndatum
B

BestGoalkeeper

Gast
Versuche gerade, das XOR zu lernen. Ich weiß, dass es mit einem Perceptron nicht möglich ist, aber warum hält neuroph nicht an bzw. wie kann ich die maximalen Trainingsdurchläufe setzen?

Maven:
siehe hier https://github.com/neuroph/NeurophFramework

Code, der nicht anhält:
Java:
import java.util.Arrays;

import org.neuroph.core.NeuralNetwork;
import org.neuroph.core.data.DataSet;
import org.neuroph.core.data.DataSetRow;
import org.neuroph.nnet.MultiLayerPerceptron;

public class XORNN {
	public static void main(String[] args) {
		@SuppressWarnings("rawtypes")
		NeuralNetwork nn = new MultiLayerPerceptron(2, 1, 1);
		DataSet training = new DataSet(2, 1);
		training.add(new DataSetRow(new double[] { 0, 0 }, new double[] { 0 }));
		training.add(new DataSetRow(new double[] { 0, 1 }, new double[] { 1 }));
		training.add(new DataSetRow(new double[] { 1, 0 }, new double[] { 1 }));
		training.add(new DataSetRow(new double[] { 1, 1 }, new double[] { 0 }));
		System.out.println(nn.getNetworkType());
		System.out.println(nn.getLearningRule());
		System.out.println(Arrays.toString(nn.getWeights()));
		nn.learn(training);
		System.out.println(Arrays.toString(nn.getWeights()));

		nn.setInput(new double[] { 1, 0 });
		nn.calculate();
		System.out.println(Math.round(nn.getOutput()[0]));
		nn.setInput(new double[] { 1, 1 });
		nn.calculate();
		System.out.println(Math.round(nn.getOutput()[0]));
	}
}

Code, der anhält: NeuralNetwork nn = new MultiLayerPerceptron(2, 4, 1);.

merci
 
Klappt! Vielen Dank.

Ich hab schon die nächste Frage. Ich möchte die Position einer 1 in einem 3x3 s/w-Bild (man soll ja klein anfangen...) mit einem Convolutional neural network in neuroph finden... Was mache ich falsch, die Ausgabe ist immer 0.5?:
Java:
	public static NeuralNetwork<ConvolutionalBackpropagation> getPositionFindingCNN() {
		int input_width = 3;
		int kernel_width = 5;
		int number_of_neurons = 1;
		int number_of_feature_maps_in_1st_layer = 3;
		int number_of_feature_maps_in_2nd_layer = 3;
		int number_of_feature_maps_in_3rd_layer = 3;
		NeuralNetwork<ConvolutionalBackpropagation> cnn = new ConvolutionalNetwork.Builder()
				.withInputLayer(input_width, input_width, 1)
				.withConvolutionLayer(kernel_width, kernel_width, number_of_feature_maps_in_1st_layer)
				.withPoolingLayer(2, 2)
				.withConvolutionLayer(kernel_width, kernel_width, number_of_feature_maps_in_2nd_layer)
				.withPoolingLayer(2, 2)
				.withConvolutionLayer(kernel_width, kernel_width, number_of_feature_maps_in_3rd_layer)
				.withFullConnectedLayer(number_of_neurons).build();
		System.out.println(cnn.getInputsCount());
		System.out.println(cnn.getOutputsCount());

		DataSet trainSet = new DataSet(9, 1);
		trainSet.add(new DataSetRow(new double[] { 0, 0, 0, 0, 1, 0, 0, 0, 0 }, new double[] { 4 }));
		trainSet.add(new DataSetRow(new double[] { 1, 0, 0, 0, 0, 0, 0, 0, 0 }, new double[] { 0 }));
		trainSet.add(new DataSetRow(new double[] { 0, 0, 0, 0, 0, 0, 0, 1, 0 }, new double[] { 7 }));

		int maxIter = 10000;
		double maxError = 0.01;
		double learningRate = 0.2;
		ConvolutionalBackpropagation backpropagation = new ConvolutionalBackpropagation();
		backpropagation.setLearningRate(learningRate);
		backpropagation.setMaxError(maxError);
		backpropagation.setMaxIterations(maxIter);
		backpropagation.setErrorFunction(new MeanSquaredError());

		cnn.setLearningRule(backpropagation);
		cnn.learn(trainSet);

		return cnn;
	}

	public static void main(String[] args) {
		NeuralNetwork<ConvolutionalBackpropagation> cnn = getPositionFindingCNN();
		cnn.setInput(1, 0, 0, 0, 0, 0, 0, 0, 0);
		cnn.calculate();
		System.out.println(Arrays.toString(cnn.getOutput()));
	}
 
@mihe7 PN an mich bitte. Ich kann dir selber leider nicht schreiben, aber will dich mit dem Thema "Positionserkennung" mittels CNN nerven. 😉
 
Speziell die Frage, was das ConvolutionalNetwork in dem konkreten Fall oben eigentlich berechnet? 🙄
 
Soweit ich CNN verstehe, dienen die CV-Layer der Merkmalsextraxtion und die Pooling-Layer dazu, komplexere Objekte zusammenzubauen, um es mal ganz einfach zu sagen.

Beim CV-Layer finden Faltungen mit verschiedenen Kernel statt. Vereinfacht stelle ich mir vor: Weichzeichner, Schärfung, Kantendetektor usw. Es werden also zig verschiedene Merkmale extrahiert. Anschließend wird eine Reduktion mit Hilfe des Pooling-Layers durchgeführt, der für jeden seiner Bereiche das Maximum auswählt.

Zum Beispiel würde durch einen 2x2-Max-Pooling-Layer aus der Matrix:
22121012897
19810199130
10317414657
19535173190
in jedem Quadranten der maximale Wert gewählt:
221130
195190

Während also am Anfang z. B. im CV-Layer ein Kantendetektor läuft, also Pixel von Kanten entstehen, bastelt der Pooling-Layer komplexere Objekte, wie z. B.: aha, die Kante verläuft schräg von links unten nach rechts oben ([0 1; 1 0]). Danach kommt wieder ein CV-Layer und wieder ein Pooling-Layer usw. so dass mit zunehmender Tiefe immer komplexere Objekte erkannt werden können.

Was Neuroph nun genau aus Deinen Daten macht, weiß ich nicht. Nur frage ich mich, ob bei einem Input von 3x3 überhaupt etwas sinnvolles rauskommen kann. Am Ende dürfte das ganze auf ein 1x1-Bild verkleinert werden oder - noch schlimmer - auf ein 0x0-Bild.
 
Bisher hat man Positionen wohl durch ein Sliding Window bestimmt (lahm). Es gibt aber im Zusammenhang mit CNNs wohl einen neueren Ansatz, über den ich noch keine genaueren Infos habe: im Prinzip geht es wohl darum, dass man das Bild nicht mehr als Ganzes klassifiziert, sondern sich Wahrscheinlichkeiten ausgeben lässt, in welchem Bildbereich sich das gesuchte Objekt befindet. Da müsstest Du mal suchen.
 
Ich glaub, ich hab's... Könnte das stimmen?

- Der Kernel darf nicht größer sein als der Input
- Der Input muss größer gewählt sein
- Man braucht keine Pooling layer

Java:
	public static NeuralNetwork<ConvolutionalBackpropagation> getPositionFindingCNN() {
		int input_width = 4;
		int kernel_width = 2;
		int number_of_neurons = 2;
		int number_of_feature_maps_in_1st_layer = 3;
		int number_of_feature_maps_in_2nd_layer = 3;
		int number_of_feature_maps_in_3rd_layer = 3;
		NeuralNetwork<ConvolutionalBackpropagation> cnn = new ConvolutionalNetwork.Builder()
				.withInputLayer(input_width, input_width, 1)
				.withConvolutionLayer(kernel_width, kernel_width, number_of_feature_maps_in_1st_layer)
				// .withPoolingLayer(2, 2)
				// .withConvolutionLayer(kernel_width, kernel_width,
				// number_of_feature_maps_in_2nd_layer)
				// .withPoolingLayer(2, 2)
				// .withConvolutionLayer(kernel_width, kernel_width,
				// number_of_feature_maps_in_3rd_layer)
				.withFullConnectedLayer(number_of_neurons).build();
		System.out.println(cnn.getInputsCount());
		System.out.println(cnn.getOutputsCount());

		DataSet trainSet = new DataSet(16, 2);
		Random random = new Random(0);
		for (int i = 0; i < 12; i++) {
			int x = random.nextInt(4), y = random.nextInt(4);
			double[] t = new double[16];
			t[x + 4 * y] = 1;
			trainSet.add(new DataSetRow(t, new double[] { x / 3d, y / 3d }));
			System.out.println(x + " " + y + " added with " + x / 3d + " " + y / 3d);
		}

		int maxIter = 100000;
		double maxError = 0.0001;
		double learningRate = 0.01;
		ConvolutionalBackpropagation backpropagation = new ConvolutionalBackpropagation();
		backpropagation.setLearningRate(learningRate);
		backpropagation.setMaxError(maxError);
		backpropagation.setMaxIterations(maxIter);
		backpropagation.setErrorFunction(new MeanSquaredError());

		cnn.setLearningRule(backpropagation);
		cnn.learn(trainSet);

		return cnn;
	}

	public static void main(String[] args) {
		NeuralNetwork<ConvolutionalBackpropagation> cnn = getPositionFindingCNN();
		for (int i = 0; i < 16; i++) {
			double[] input = new double[16];
			input[i] = 1;
			cnn.setInput(input);
			cnn.calculate();
			double[] output = cnn.getOutput();
			System.out.println(i % 4 + " " + i / 4 + " at " + Math.round(output[0] * 3d) + " " + Math.round(output[1] * 3d));
		}
	}
Code:
16
2
2 3 added with 0.6666666666666666 1.0
0 2 added with 0.0 0.6666666666666666
2 1 added with 0.6666666666666666 0.3333333333333333
2 0 added with 0.6666666666666666 0.0
2 3 added with 0.6666666666666666 1.0
1 1 added with 0.3333333333333333 0.3333333333333333
1 2 added with 0.3333333333333333 0.6666666666666666
3 3 added with 1.0 1.0
3 0 added with 1.0 0.0
3 0 added with 1.0 0.0
1 1 added with 0.3333333333333333 0.3333333333333333
0 1 added with 0.0 0.3333333333333333
0 0 at 2 2
1 0 at 1 1
2 0 at 2 0
3 0 at 3 0
0 1 at 0 1
1 1 at 1 1
2 1 at 2 1
3 1 at 3 0
0 2 at 0 2
1 2 at 1 2
2 2 at 1 3
3 2 at 3 3
0 3 at 2 2
1 3 at 1 2
2 3 at 2 3
3 3 at 3 3
 
Hm, ich glaube aber, dass er jetzt einfach nur i % 4 und i / 4 lernt... Ich muss da mit echten Daten ran, nur dann ist der Input 1920x1080 (Full HD)... Deswegen auch CNNs... schlussendlich soll die Position eines beliebigen Schachbretts erkannt werden.

Ich weiß, dass es dafür auch andere Algorithmen gibt, nur ist jedes Schachfeld etwas anders und es soll das charakteristische 8x8-Muster erkannt werden...
 
Wer 15 Min. Zeit hat, kann das mal starten... Ich bin noch beim Debuggen - und habe die Größe auf 192x108 geändert. Als back1.png Bild müsst ihr ein schönes Full HD Bild wählen mit 1920x1080 pixel. Am Besten mit vielen Farben - Blumen oder so. Als Ausgabe sollte die Position und die Länge des Schachfeldmusters herauskommen.

Java:
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.WindowConstants;

import org.neuroph.core.NeuralNetwork;
import org.neuroph.core.data.DataSet;
import org.neuroph.core.data.DataSetRow;
import org.neuroph.core.learning.error.MeanSquaredError;
import org.neuroph.nnet.ConvolutionalNetwork;
import org.neuroph.nnet.learning.ConvolutionalBackpropagation;

public class Schach {
	private static int input_width = 192;
	private static int input_height = 108;
	private static int n1 = input_width * input_height;
	private static double n2 = 0xFFFFFF;
	private static String background_image = ".../back1.png";
	private static String board1_image = ".../brett2.jpg";
	private static String board2_image = ".../brett3.jpg";

	public static BufferedImage resize(BufferedImage img, int newW, int newH) {
		Image tmp = img.getScaledInstance(newW, newH, Image.SCALE_SMOOTH);
		BufferedImage dimg = new BufferedImage(newW, newH, BufferedImage.TYPE_INT_ARGB);

		Graphics2D g2d = dimg.createGraphics();
		g2d.drawImage(tmp, 0, 0, null);
		g2d.dispose();

		return dimg;
	}

	public static BufferedImage deepCopy(BufferedImage img) {
		ColorModel cm = img.getColorModel();
		boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
		WritableRaster raster = img.copyData(null);
		return new BufferedImage(cm, raster, isAlphaPremultiplied, null);
	}

	public static BufferedImage createTestImage(BufferedImage back, BufferedImage board, int x2, int y2) {
		BufferedImage org = deepCopy(back);
		for (int x = 0; x < board.getWidth(); x++) {
			for (int y = 0; y < board.getHeight(); y++) {
				org.setRGB(x + x2, y + y2, board.getRGB(x, y));
			}
		}
		return resize(org, input_width, input_height);
	}

	public static double[] getInput(BufferedImage test) {
		double[] a = new double[test.getWidth() * test.getHeight()];
		for (int i = 0; i < a.length; i++) {
			a[i] = test.getRGB(i % test.getWidth(), i / test.getWidth()) / n2;
		}
		return a;
	}

	public static double[] getOutput(int x, int y, int w, int h) {
		return new double[] { x / 10.0 / input_width, y / 10.0 / input_width, w / 10.0 / input_width };
	}

	public static void evolveOutput(double[] a) {
		a[0] = Math.round(a[0] * 10.0 * input_width);
		a[1] = Math.round(a[1] * 10.0 * input_width);
		a[2] = Math.round(a[2] * 10.0 * input_width);
	}

	public static NeuralNetwork<ConvolutionalBackpropagation> getPositionFindingCNN() throws IOException {
		int kernel_width = 3;
		int number_of_neurons = 3;
		int number_of_feature_maps_in_1st_layer = 8;
		int number_of_feature_maps_in_2nd_layer = 4;
		int number_of_feature_maps_in_3rd_layer = 2;
		NeuralNetwork<ConvolutionalBackpropagation> cnn = new ConvolutionalNetwork.Builder()
				.withInputLayer(input_width, input_height, 1)
				.withConvolutionLayer(kernel_width, kernel_width, number_of_feature_maps_in_1st_layer)
				.withPoolingLayer(2, 2)
				.withConvolutionLayer(kernel_width, kernel_width, number_of_feature_maps_in_2nd_layer)
				.withPoolingLayer(2, 2)
				.withConvolutionLayer(kernel_width, kernel_width, number_of_feature_maps_in_3rd_layer)
				.withFullConnectedLayer(number_of_neurons)
				.build();
		System.out.println(cnn.getInputsCount());
		System.out.println(cnn.getOutputsCount());

		DataSet trainSet = new DataSet(n1, number_of_neurons);
		BufferedImage back = ImageIO.read(new File(background_image));
		BufferedImage board1 = ImageIO.read(new File(board1_image));
		BufferedImage board2 = ImageIO.read(new File(board2_image));
		Random random = new Random(0);
		for (int i = 0; i < 12; i++) {
			int x = random.nextInt(back.getWidth() - board1.getWidth() + 1);
			int y = random.nextInt(back.getHeight() - board1.getHeight() + 1);
			BufferedImage testImg;
			if (random.nextInt(2) == 0) {
				testImg = createTestImage(back, board1, x, y);
			} else {
				testImg = createTestImage(back, board2, x, y);
			}
			double[] input = getInput(testImg);
			double[] output = getOutput(x, y, board1.getWidth(), board1.getHeight());
			DataSetRow dst = new DataSetRow(input, output);
			trainSet.add(dst);
			System.out.println(x + " " + y + " at " + Arrays.toString(dst.getDesiredOutput()) + " added");
		}

		int maxIter = 75;
		double maxError = 0.00001;
		double learningRate = 0.0001;
		ConvolutionalBackpropagation backpropagation = new ConvolutionalBackpropagation();
		backpropagation.setLearningRate(learningRate);
		backpropagation.setMaxError(maxError);
		backpropagation.setMaxIterations(maxIter);
		backpropagation.setErrorFunction(new MeanSquaredError());
		System.out.println("MaxIterations : " + backpropagation.getMaxIterations());
		System.out.println("LearningRate  : " + backpropagation.getLearningRate());
		System.out.println("MaxError      : " + backpropagation.getMaxError());

		cnn.setLearningRule(backpropagation);
		cnn.learn(trainSet);

		return cnn;
	}

	public static void main(String[] args) throws IOException {
		NeuralNetwork<ConvolutionalBackpropagation> cnn = getPositionFindingCNN();
		BufferedImage back = ImageIO.read(new File(background_image));
		BufferedImage board1 = ImageIO.read(new File(board1_image));
		BufferedImage testImg = createTestImage(back, board1, 127, 446);
		double[] input = getInput(testImg);
		cnn.setInput(input);
		cnn.calculate();
		double[] output = cnn.getOutput();
		evolveOutput(output);
		System.out.println(Arrays.toString(output));

		testImg = createTestImage(back, board1, 100, 100);
		input = getInput(testImg);
		cnn.setInput(input);
		cnn.calculate();
		output = cnn.getOutput();
		evolveOutput(output);
		System.out.println(Arrays.toString(output));
	}
}
 

Anhänge

  • brett3.jpg
    brett3.jpg
    46,4 KB · Aufrufe: 27
  • brett2.jpg
    brett2.jpg
    47,2 KB · Aufrufe: 25

Neue Themen


Zurück
Oben