mirror of
https://github.com/jneug/zeichenmaschine.git
synced 2026-04-14 14:43:33 +02:00
Biases im NeuronLayer eingeführt
This commit is contained in:
@@ -145,6 +145,37 @@ public final class MLMath {
|
|||||||
return -sum / batch_size;
|
return -sum / batch_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static double[][] biasAdd( double[][] A, double[] V ) {
|
||||||
|
if( A[0].length != V.length ) {
|
||||||
|
throw new IllegalArgumentException("Can't add bias vector to matrix with wrong column count");
|
||||||
|
}
|
||||||
|
|
||||||
|
double[][] result = new double[A.length][A[0].length];
|
||||||
|
for( int j = 0; j < A[0].length; j++ ) {
|
||||||
|
for( int i = 0; i < A.length; i++ ) {
|
||||||
|
result[i][j] = A[i][j] + V[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double[] biasAdjust( double[] biases, double[][] delta ) {
|
||||||
|
if( biases.length != delta[0].length ) {
|
||||||
|
throw new IllegalArgumentException("Can't add adjust bias vector by delta with wrong column count");
|
||||||
|
}
|
||||||
|
|
||||||
|
double[] result = new double[biases.length];
|
||||||
|
for( int j = 0; j < delta[0].length; j++ ) {
|
||||||
|
for( int i = 0; i < delta.length; i++ ) {
|
||||||
|
result[j] += biases[j] - delta[i][j];
|
||||||
|
}
|
||||||
|
result[j] /= delta.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private MLMath() {
|
private MLMath() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
package schule.ngb.zm.ml;
|
package schule.ngb.zm.ml;
|
||||||
|
|
||||||
|
import schule.ngb.zm.Constants;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
// TODO: Move Math into Matrix class
|
||||||
|
// TODO: Implement support for optional sci libs
|
||||||
public class Matrix {
|
public class Matrix {
|
||||||
|
|
||||||
private int columns, rows;
|
private int columns, rows;
|
||||||
@@ -37,11 +41,11 @@ public class Matrix {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void initializeRandom() {
|
public void initializeRandom() {
|
||||||
coefficients = MLMath.matrixApply(coefficients, (d) -> Math.random());
|
coefficients = MLMath.matrixApply(coefficients, (d) -> Constants.randomGaussian());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initializeRandom( double lower, double upper ) {
|
public void initializeRandom( double lower, double upper ) {
|
||||||
coefficients = MLMath.matrixApply(coefficients, (d) -> ((upper-lower) * Math.random()) + lower);
|
coefficients = MLMath.matrixApply(coefficients, (d) -> ((upper-lower) * (Constants.randomGaussian()+1) * .5) + lower);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initializeIdentity() {
|
public void initializeIdentity() {
|
||||||
|
|||||||
@@ -1,12 +1,38 @@
|
|||||||
package schule.ngb.zm.ml;
|
package schule.ngb.zm.ml;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.function.DoubleUnaryOperator;
|
import java.util.function.DoubleUnaryOperator;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
public class NeuronLayer implements Function<double[][], double[][]> {
|
public class NeuronLayer implements Function<double[][], double[][]> {
|
||||||
|
|
||||||
|
public static NeuronLayer fromArray( double[][] weights ) {
|
||||||
|
NeuronLayer layer = new NeuronLayer(weights[0].length, weights.length);
|
||||||
|
for( int i = 0; i < weights[0].length; i++ ) {
|
||||||
|
for( int j = 0; j < weights.length; j++ ) {
|
||||||
|
layer.weights.coefficients[i][j] = weights[i][j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return layer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static NeuronLayer fromArray( double[][] weights, double[] biases ) {
|
||||||
|
NeuronLayer layer = new NeuronLayer(weights[0].length, weights.length);
|
||||||
|
for( int i = 0; i < weights[0].length; i++ ) {
|
||||||
|
for( int j = 0; j < weights.length; j++ ) {
|
||||||
|
layer.weights.coefficients[i][j] = weights[i][j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for( int j = 0; j < biases.length; j++ ) {
|
||||||
|
layer.biases[j] = biases[j];
|
||||||
|
}
|
||||||
|
return layer;
|
||||||
|
}
|
||||||
|
|
||||||
Matrix weights;
|
Matrix weights;
|
||||||
|
|
||||||
|
double[] biases;
|
||||||
|
|
||||||
NeuronLayer previous, next;
|
NeuronLayer previous, next;
|
||||||
|
|
||||||
DoubleUnaryOperator activationFunction, activationFunctionDerivative;
|
DoubleUnaryOperator activationFunction, activationFunctionDerivative;
|
||||||
@@ -17,6 +43,9 @@ public class NeuronLayer implements Function<double[][], double[][]> {
|
|||||||
weights = new Matrix(inputs, neurons);
|
weights = new Matrix(inputs, neurons);
|
||||||
weights.initializeRandom(-1, 1);
|
weights.initializeRandom(-1, 1);
|
||||||
|
|
||||||
|
biases = new double[neurons];
|
||||||
|
Arrays.fill(biases, 0.0); // TODO: Random?
|
||||||
|
|
||||||
activationFunction = MLMath::sigmoid;
|
activationFunction = MLMath::sigmoid;
|
||||||
activationFunctionDerivative = MLMath::sigmoidDerivative;
|
activationFunctionDerivative = MLMath::sigmoidDerivative;
|
||||||
}
|
}
|
||||||
@@ -82,13 +111,19 @@ public class NeuronLayer implements Function<double[][], double[][]> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return weights.toString();
|
return weights.toString() + "\n" + Arrays.toString(biases);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public double[][] apply( double[][] inputs ) {
|
public double[][] apply( double[][] inputs ) {
|
||||||
lastInput = inputs;
|
lastInput = inputs;
|
||||||
lastOutput = MLMath.matrixApply(MLMath.matrixMultiply(inputs, weights.coefficients), activationFunction);
|
lastOutput = MLMath.matrixApply(
|
||||||
|
MLMath.biasAdd(
|
||||||
|
MLMath.matrixMultiply(inputs, weights.coefficients),
|
||||||
|
biases
|
||||||
|
),
|
||||||
|
activationFunction
|
||||||
|
);
|
||||||
if( next != null ) {
|
if( next != null ) {
|
||||||
return next.apply(lastOutput);
|
return next.apply(lastOutput);
|
||||||
} else {
|
} else {
|
||||||
@@ -114,11 +149,16 @@ public class NeuronLayer implements Function<double[][], double[][]> {
|
|||||||
error = MLMath.matrixMultiply(expected, MLMath.matrixTranspose(next.weights.coefficients));
|
error = MLMath.matrixMultiply(expected, MLMath.matrixTranspose(next.weights.coefficients));
|
||||||
}
|
}
|
||||||
|
|
||||||
delta = MLMath.matrixScale(error, MLMath.matrixApply(this.lastOutput,this.activationFunctionDerivative));
|
delta = MLMath.matrixScale(error, MLMath.matrixApply(this.lastOutput, this.activationFunctionDerivative));
|
||||||
|
// Hier schon leraningRate anwenden?
|
||||||
|
// See https://towardsdatascience.com/understanding-and-implementing-neural-networks-in-java-from-scratch-61421bb6352c
|
||||||
|
//delta = MLMath.matrixApply(delta, ( x ) -> learningRate * x);
|
||||||
if( previous != null ) {
|
if( previous != null ) {
|
||||||
previous.backprop(delta, learningRate);
|
previous.backprop(delta, learningRate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
biases = MLMath.biasAdjust(biases, MLMath.matrixApply(delta, ( x ) -> learningRate * x));
|
||||||
|
|
||||||
adjustment = MLMath.matrixMultiply(MLMath.matrixTranspose(lastInput), delta);
|
adjustment = MLMath.matrixMultiply(MLMath.matrixTranspose(lastInput), delta);
|
||||||
adjustment = MLMath.matrixApply(adjustment, ( x ) -> learningRate * x);
|
adjustment = MLMath.matrixApply(adjustment, ( x ) -> learningRate * x);
|
||||||
this.adjustWeights(adjustment);
|
this.adjustWeights(adjustment);
|
||||||
|
|||||||
Reference in New Issue
Block a user