Вот мой код:
Код: Выделить всё
import java.util.ArrayList;
public class Net {
Layer inputLayer;
Layer outputLayer;
ArrayList hiddenLayers;
double learningRate;
public Net(int[] layerDimensions){
this.learningRate = learningRate;
inputLayer = new Layer();
hiddenLayers = new ArrayList();
outputLayer = new Layer();
for(int i = 0; i< layerDimensions[0]; i++){
inputLayer.nodes.add(new Node(new Relu()));
}
for(int i = 1; i < layerDimensions.length-1; i++){
Layer hiddenLayer = new Layer();
for(int j = 0; j< layerDimensions[i]; j++){
hiddenLayer.nodes.add(new Node(new Relu()));
}
hiddenLayers.add(hiddenLayer);
}
for(int i = 0; i < layerDimensions[layerDimensions.length-1]; i++){
outputLayer.nodes.add(new Node(new Relu()));
}
addConnections();
}
public double[] predict(double[] input){
for(int i = 0; i < inputLayer.nodes.size(); i++){
inputLayer.nodes.get(i).output = input[i];
}
for(Layer hiddenLayer : hiddenLayers){
hiddenLayer.calcInput();
}
outputLayer.calcInput();
return outputLayer.getOutput();
}
public double training(double[][] input, double[][] target, double learningRate, int repetitions) {
this.learningRate = learningRate;
double accuracy = 0;
for (int r = 0; r < repetitions; r++) {
accuracy = 0;
for (int i = 0; i < input.length; i++) {
// Forward pass
double[] output = predict(input[i]);
// Calculate error for output layer
for (int j = 0; j < outputLayer.nodes.size(); j++) {
Node outputNode = outputLayer.nodes.get(j);
double error = 0.5* Math.pow(target[i][j] - output[j],2);
outputNode.error = error * outputNode.activationFunction.phiStrich(outputNode.net);
}
// Backpropagate the error to hidden layers
for (int l = hiddenLayers.size() - 1; l >= 0; l--) {
Layer hiddenLayer = hiddenLayers.get(l);
for (Node hiddenNode : hiddenLayer.nodes) {
hiddenNode.error = 0;
for (Edge edge : hiddenNode.outgoing) {
hiddenNode.error += edge.weight * edge.targetNode.error;
}
hiddenNode.error *= hiddenNode.activationFunction.phiStrich(hiddenNode.net);
}
}
// Update weights and biases for output layer
updateWeights(learningRate, outputLayer);
// Update weights and biases for hidden layers
for (Layer hiddenLayer : hiddenLayers) {
updateWeights(learningRate, hiddenLayer);
}
updateWeights(learningRate,inputLayer);
// Calculate accuracy
double mse = 0;
for (int j = 0; j < output.length; j++) {
mse += Math.pow(target[i][j] - output[j], 2);
}
accuracy += mse / output.length;
}
accuracy /= input.length;
}
return accuracy;
}
private void updateWeights(double learningRate, Layer layer) {
for (Node node : layer.nodes) {
for (Edge edge : node.incoming) {
edge.deltaWeight = -learningRate * node.error * edge.targetNode.output;
edge.weight += edge.deltaWeight;
}
node.bias += -learningRate * node.error;
}
}
private void addConnections(){
for(Node inputNode: inputLayer.nodes){
for(Node hiddenNode: hiddenLayers.get(0).nodes){
Edge connection = new Edge(inputNode, hiddenNode);
inputNode.outgoing.add(connection);
hiddenNode.incoming.add(connection);
}
}
for(int i = 1; i < hiddenLayers.size(); i++) {
for(Node hiddenNode : hiddenLayers.get(i).nodes){
for(Node previousNode : hiddenLayers.get(i-1).nodes){
Edge connection = new Edge(previousNode, hiddenNode);
previousNode.outgoing.add(connection);
hiddenNode.incoming.add(connection);
}
}
}
for(Node outputNode: outputLayer.nodes){
for(Node hiddenNode: hiddenLayers.get(hiddenLayers.size()-1).nodes){
Edge connection = new Edge(hiddenNode, outputNode);
hiddenNode.outgoing.add(connection);
outputNode.incoming.add(connection);
}
}
}
}
Код: Выделить всё
import java.util.ArrayList;
public class Layer {
ArrayList nodes;
public Layer(){
nodes = new ArrayList();
}
public void calcInput(){
for(Node node : nodes){
node.net = 0;
for(Edge connection : node.incoming){
node.net += connection.sourceNode.output * connection.weight;
}
node.activate();
}
for (Node node : nodes) {
double net = 0;
for (Edge edge : node.incoming) {
net += edge.weight * edge.sourceNode.output;
}
net += node.bias;
node.net = net;
node.output = node.activationFunction.phi(net);
}
}
public double[] getOutput(){
double[] result = new double[nodes.size()];
for(int i = 0; i < nodes.size(); i++){
result[i] = nodes.get(i).output;
}
return result;
}
}
Код: Выделить всё
import java.util.ArrayList;
public class Node {
ArrayList outgoing;
ArrayList incoming;
double net = 0;
double bias;
double output;
double error;
Aktivierungsfunktion activationFunction;
public Node(Aktivierungsfunktion activationFunction){
outgoing = new ArrayList();
incoming = new ArrayList();
this.activationFunction = activationFunction;
}
public void activate(){
net += bias;
output = activationFunction.phi(net);
}
}
Код: Выделить всё
import java.util.Random;
public class Edge {
Node sourceNode;
Node targetNode;
public Edge(Node source, Node target){
this.sourceNode = source;
this.targetNode = target;
weight = new Random().nextDouble() * 0.5;
}
double weight;
double deltaWeight;
}
Код: Выделить всё
public class Sigmoid extends Aktivierungsfunktion
{
public double phi(double x){
return 1 / (1 + Math.exp(-x));
}
public double phiStrich(double x){
double phiVonX = phi(x);
return phiVonX * (1 - phiVonX);
}
}
public class Relu extends Aktivierungsfunktion
{
private final double alpha = 0.01;
public double phi(double x){
if (x > 0) {
return x;
} else {
return alpha * x;
}
}
public double phiStrich(double x){
if (x > 0) {
return 1;
} else {
return alpha;
}
}
}
Код: Выделить всё
public abstract class Aktivierungsfunktion
{
public abstract double phi(double x);
public abstract double phiStrich(double x);
}
Код: Выделить всё
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
Net net = new Net(new int[] {1,10,10,1});
double[][] input = {
{0.0},
{1.0},
{1.0},
{0.0},
};
double[][] target = {
{0.0},
{1.0},
{1.0},
{0.0}
};
double accuracy = net.training(input,target,0.01, 1000);
System.out.println(accuracy);
for (double[] in : input) {
double[] out = net.predict(in);
System.out.println("Input: " + Arrays.toString(in) + " Output: " + Arrays.toString(out));
}
}
}
Когда я меняю функцию активации на сигмовидную, прогнозируемые значения рядом с постоянным значением, независимым от заданных входных данных.
Как я могу это отладить?
Подробнее здесь: https://stackoverflow.com/questions/788 ... ayer-count
Мобильная версия