Тема: Потрібно реалізувати користувацький інтерфейс
Є нейромережа Хопфілда в якій реалізовано тільки консольний застосунок
Потрібно створити форму на якій буде два поля для малювання та кілька кнопок:
на першому полі ви малюєте образ для тренування та записуєте його в память, і так кілька образів
на другому полі ви малюєте спотворений образ та натискаєте кнопку "розпізнати" і після цього нейромережа повинна видати результат.
також повинні бути кнопки очищення полів та памяті нейромережі.
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.text.StringCharacterIterator;
import com.za.tutorial.linearalgebra.Matrix;
public class Driver {
static final int NUMB_OF_ROWS_IN_DRAWING_BOARD = 5;
static enum Mode {DEFAULT, VERBOSE};
static Driver.Mode mode = Mode.DEFAULT;
public static void main(String[] args) throws Exception {
System.out.println("> Enter # of neurons (must be divisible by 5 - [# of neurons] = [# of columns] X [5 rows]): ");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
int size = Integer.valueOf(bufferedReader.readLine());
NeuralNetwork neuralNetwork = new NeuralNetwork(size);
double[] input = new double[size];
double[] output = new double[size];
boolean flag = true;
while (flag) {
System.out.println("> What do you want to do (train, run, clear, change_mode, exit) ?");
String command = bufferedReader.readLine();
switch (command) {
case "train":
System.out.println("> Provide training pattern: ");
input = getInput(new StringCharacterIterator(bufferedReader.readLine()), size);
neuralNetwork.train(input);
System.out.print(Matrix.getMatrix(input, NUMB_OF_ROWS_IN_DRAWING_BOARD).toPackedString());
System.out.println("done training on above pattern");
break;
case "run":
System.out.println("> Provide input pattern: ");
input = getInput(new StringCharacterIterator(bufferedReader.readLine()), size);
output = neuralNetwork.run(input);
System.out.println("Input pattern:");
System.out.print(Matrix.getMatrix(input, NUMB_OF_ROWS_IN_DRAWING_BOARD).toPackedString());
System.out.println("Output pattern:");
System.out.print(Matrix.getMatrix(output, NUMB_OF_ROWS_IN_DRAWING_BOARD).toPackedString());
break;
case "clear":
neuralNetwork.getWeightMatrix().clear();
break;
case "change_mode":
System.out.println("> Specify running mode (default, verbose) ?");
if (bufferedReader.readLine().equals("verbose")) mode = Mode.VERBOSE;
else mode = Mode.DEFAULT;
break;
case "exit":
flag = false;
break;
}
}
System.exit(0);
}
static double[] getInput(StringCharacterIterator iterator, int size) {
double[] input = new double[size];
while (iterator.getIndex() < iterator.getEndIndex()) {
input[iterator.getIndex()] = Double.parseDouble(String.valueOf(iterator.current()));
iterator.next();
}
return input;
}
}
import java.util.stream.IntStream;
import com.za.tutorial.linearalgebra.Matrix;
import com.za.tutorial.neuralnetworks.hopfield.Driver.Mode;
public class NeuralNetwork {
private Matrix weightMatrix;
public NeuralNetwork(int size) {weightMatrix = new Matrix(size, size);}
public Matrix getWeightMatrix() { return weightMatrix; }
public void train(double[] input) throws Exception {
double[] bipolarInput = toBipolar(input);
Matrix bipolarMatrix = Matrix.toRowMatrix(bipolarInput);
Matrix transposeBipolarMatrix = bipolarMatrix.transpose();
Matrix multiplyMatrix = transposeBipolarMatrix.multiply(bipolarMatrix);
Matrix subtractMatrix = multiplyMatrix.subtract(Matrix.identity(weightMatrix.getData().length));
if (Driver.mode == Mode.VERBOSE) {
System.out.println("<-- Calculate Contribution Matrix -->");
System.out.println("[1] Obtain bipolar matrix for input \n" + bipolarMatrix);
System.out.println("[2] Transpose bipolar matrix:\n"+ transposeBipolarMatrix);
System.out.println("[3] (Transpose bipolar matrix) * (bipolar matrix):\n"+ multiplyMatrix);
System.out.println("[4] Contribution matrix = [3] - (Identity Matrix):\n"+ subtractMatrix);
System.out.println("<-- Update Weight Matrix -->");
System.out.println("current weight matrix:\n" + weightMatrix.toString("N", "N"));
}
weightMatrix = weightMatrix.add(subtractMatrix);
if (Driver.mode == Mode.VERBOSE)
System.out.println("New Weight Matrix = (Contribution Matrix) + (Current Weight Matrix)\n"+ weightMatrix.toString("N","N"));
}
public double[] run(double[] input) {
double[] bipolarInput = toBipolar(input);
double[] output = new double[input.length];
Matrix bipolarMatrix = Matrix.toRowMatrix(bipolarInput);
if (Driver.mode == Mode.VERBOSE) {
System.out.println("<-- run -->");
System.out.println("[1] Weight matrix:\n"+weightMatrix.toString("N", "N"));
System.out.println("[2] Obtain bipolar matrix for input \n" + bipolarMatrix);
System.out.println("[3] dot product bipolar matrix & each of the columns in weight matrix");
}
IntStream.range(0, input.length).forEach(column -> {
try {
Matrix columnMatrix = weightMatrix.getColumnMatrix(column);
double dotProductResult = bipolarMatrix.dotProduct(columnMatrix);
if (Driver.mode == Mode.VERBOSE)
System.out.print("[3."+ String.format("%02d", column) +
"] (bipolar matrix) . (Weight matrix column "+ String.format("%02d", column)+") = ");
if (dotProductResult > 0) {
output[column] = 1.00;
if (Driver.mode == Mode.VERBOSE) System.out.println(" "+dotProductResult + " > 0 ==> 1");
} else {
output[column] = 0;
if (Driver.mode == Mode.VERBOSE) System.out.println(dotProductResult + " <= 0 ==> 0");
}
} catch (Exception e) {e.printStackTrace();}
});
return output;
}
static double[] toBipolar(double[] pattern) {
double[] bipolarPattern = new double[pattern.length];
IntStream.range(0, pattern.length).forEach(row -> {
if (pattern[row] == 0) bipolarPattern[row] = -1.00;
else bipolarPattern[row] = 1.00;
});
return bipolarPattern;
}
static double[] fromBipolar(double[] bipolarPattern) {
double[] pattern = new double[bipolarPattern.length];
IntStream.range(0, bipolarPattern.length).forEach(row -> {
if (bipolarPattern[row] == 1.00) pattern[row] = 1.00;
else pattern[row] = 0.00;
});
return pattern;
}
}
import java.util.stream.IntStream;
public class Matrix {
private double data[][];
enum ScalarOperation {ADD, SUBTRACT, MULTIPLY, DIVIDE};
public Matrix(int rows, int columns) { data = new double[rows][columns]; }
public Matrix(double data[][]) {
this.data = new double[data.length][data[0].length];
IntStream.range(0, this.data.length).forEach(row ->
IntStream.range(0, this.data[0].length).forEach(column -> this.data[row][column] = data[row][column]));
}
public Matrix add(Matrix matrix) throws Exception {
if ((data.length != matrix.data.length) ||
(data[0].length != matrix.data[0].length)) throw new Exception("matrices must have matching size");
double returnData[][] = new double[data.length][data[0].length];
IntStream.range(0, data.length).forEach(row ->
IntStream.range(0, data[0].length).forEach(column ->
returnData[row][column] = data[row][column] + matrix.data[row][column]));
return new Matrix(returnData);
}
public Matrix subtract(Matrix matrix) throws Exception {
return add(matrix.scalarOperation(-1, ScalarOperation.MULTIPLY));
}
public Matrix multiply(Matrix matrix) throws Exception {
if (data[0].length != matrix.data.length) throw new Exception("matrices must have matching inner dimension");
double returnData[][] = new double[data.length][matrix.data[0].length];
IntStream.range(0, data.length).forEach(row ->
IntStream.range(0, matrix.data[0].length).forEach(column -> {
double result = 0;
for (int i = 0; i < data[0].length; i++) result += data[row][i] * matrix.data[i][column];
returnData[row][column] = result;
}));
return new Matrix(returnData);
}
public Matrix scalarOperation(double x, ScalarOperation scalarOperation) {
double returnData[][] = new double[data.length][data[0].length];
IntStream.range(0, data.length).forEach(row ->
IntStream.range(0, data[0].length).forEach(column -> {
switch (scalarOperation) {
case ADD:
returnData[row][column] = data[row][column] + x;
break;
case SUBTRACT:
returnData[row][column] = data[row][column] - x;
break;
case MULTIPLY:
returnData[row][column] = data[row][column] * x;
break;
case DIVIDE:
returnData[row][column] = data[row][column] / x;
break;
}
}));
return new Matrix(returnData);
}
public static Matrix identity(int size) {
Matrix matrix = new Matrix(size, size);
IntStream.range(0, size).forEach(i -> matrix.data[i][i] = 1);
return matrix;
}
public Matrix transpose() {
double[][] returnData = new double[data[0].length][data.length];
IntStream.range(0, data.length).forEach(row ->
IntStream.range(0, data[0].length).forEach(column -> returnData[column][row] = data[row][column]));
return new Matrix(returnData);
}
public double dotProduct(Matrix matrix) throws Exception {
if (!this.isVector() || !matrix.isVector()) throw new Exception("can only dot product 2 vectors");
else if ((this.flatten().length != matrix.flatten().length)) throw new Exception("both vectors must have same size");
double returnValue = 0;
for (int i = 0; i < this.flatten().length; i++) returnValue += this.flatten()[i] * matrix.flatten()[i];
return returnValue;
}
public Matrix clear() {
IntStream.range(0, data.length).forEach(row ->
IntStream.range(0, data[0].length).forEach(column -> data[row][column] = 0));
return this;
}
public static Matrix toRowMatrix(double[] array) {
double[][] data = new double[1][array.length];
System.arraycopy(array, 0, data[0], 0, array.length);
return new Matrix(data);
}
public Matrix getColumnMatrix(int column) {
double[][] data = new double[this.data.length][1];
IntStream.range(0,this.data.length).forEach(row -> data[row][0] = this.data[row][column]);
return new Matrix(data);
}
public boolean isVector() {
boolean flag = false;
if (this.data.length == 1) flag = true;
else if( this.data[0].length == 1) flag = true;
return flag;
}
public double[] flatten() {
double returnValue[] = new double[data.length * data[0].length];
int i = 0;
for (int row = 0; row < data.length; row++)
for (int column = 0; column < data[0].length; column++) returnValue[i++] = data[row][column];
return returnValue;
}
public double[][] getData() { return data; }
public static Matrix getMatrix(double data[], int numbOfRows) throws Exception {
if (data.length % numbOfRows != 0) throw new Exception("size of data not divisible by number of rows");
Matrix drawingMatrix = new Matrix(numbOfRows, data.length / numbOfRows);
int i = 0;
for (int row = 0; row < drawingMatrix.data.length; row++)
for (int column = 0; column < drawingMatrix.data[0].length; column++) drawingMatrix.data[row][column] = data[i++];
return drawingMatrix;
}
public String toPackedString() {
StringBuffer bodySB = new StringBuffer();
IntStream.range(0, data.length).forEach(row -> {
IntStream.range(0, data[0].length).forEach(column ->
bodySB.append((int)data[row][column]));
bodySB.append("\n");
});
return bodySB.toString();
}
public String toString(String columnLabel, String rowLabel) {
StringBuffer headingSB = new StringBuffer();
headingSB.append(" | ");
IntStream.range(0, data[0].length).forEach(x -> headingSB.append(" " + columnLabel + String.format("%02d", x) +""));
headingSB.append("\n");
StringBuffer bodySB = new StringBuffer();
IntStream.range(0, headingSB.length()).forEach(x -> bodySB.append("-"));
bodySB.append("\n");
IntStream.range(0, data.length).forEach(row -> {
bodySB.append(rowLabel + String.format("%02d", row) +" |");
IntStream.range(0, data[0].length).forEach(column -> {
if (data[row][column] >= 0) bodySB.append(" "+ (int)data[row][column]);
else bodySB.append(" "+ (int)data[row][column]);
});
bodySB.append("\n");
});
return headingSB.toString() + bodySB.toString();
}
public String toString() { return toString("C", "R");}
}