Всем привет.
Визуализация нейронной сети, которую я пытаюсь создать:
Вот что получилось:
private static final int LAYERS = 5;
private static final int INPUT_NEURONS = 3;
private static final int HIDDEN_NEURONS = 4;
private static final int OUTPUT_NEURONS = 3;
private static final Random random = new Random();
// inputNeurons
private static final float[][] weights1 = new float[INPUT_NEURONS][HIDDEN_NEURONS];
private static final float[] hiddenNeurons1 = new float[HIDDEN_NEURONS];
private static final float[][] weights2 = new float[HIDDEN_NEURONS][HIDDEN_NEURONS];
private static final float[] hiddenNeurons2 = new float[HIDDEN_NEURONS];
private static final float[][] weights3 = new float[HIDDEN_NEURONS][HIDDEN_NEURONS];
private static final float[] hiddenNeurons3 = new float[HIDDEN_NEURONS];
private static final float[][] weights4 = new float[HIDDEN_NEURONS][OUTPUT_NEURONS];
private static final float[] outputNeurons = new float[OUTPUT_NEURONS];
// Каждый bias нейрон равен 1, поэтому мы учитываем только вес при подсчете
private static final float[][] biasWeights = new float[LAYERS - 1][];
private static final int MAX_EPOCH = 10000;
private static final float LEARNING_RATE = 0.7F;
public static void main(String[] args) {
initWeights(weights1);
initWeights(weights2);
initWeights(weights3);
initWeights(weights4);
initWeights(biasWeights);
}
private static void initWeights(float[][] weights) {
for (int i = 0; i < weights.length; i++) {
for (int j = 0; j < weights[i].length; j++) {
weights[i][j] = randFloat(0.1F, 0.5F);
}
}
}
public static float randFloat(float min, float max) {
return random.nextFloat() * (max - min) + min;
}
private static void train(float[][] inputs, float[][] outputs) {
for (int i = 0; i < MAX_EPOCH; i++) {
for (int j = 0; j < inputs.length; j++) {
float[] result = getResult(inputs[j]);
float[] errors = new float[result.length];
for (int k = 0; k < result.length; k++) {
float actual = result[k];
float expected = outputs[j][k];
errors[k] = expected - actual;
}
}
}
}
private static float[] getResult(float[] inputNeurons) {
if (inputNeurons.length != INPUT_NEURONS) {
throw new IllegalArgumentException();
}
calculate(inputNeurons, weights1, hiddenNeurons1, biasWeights[0]);
calculate(hiddenNeurons1, weights2, hiddenNeurons2, biasWeights[1]);
calculate(hiddenNeurons2, weights3, hiddenNeurons3, biasWeights[2]);
calculate(hiddenNeurons3, weights4, outputNeurons, biasWeights[3]);
return outputNeurons.clone();
}
private static void calculate(float[] neurons, float[][] weights, float[] nextNeurons, float[] biasWeights) {
for (int i = 0; i < neurons.length; i++) {
for (int w = 0; w < weights[i].length; w++) {
nextNeurons[w] = nextNeurons[w] + neurons[i] * weights[i][w];
}
}
for (int i = 0; i < nextNeurons.length; i++) {
nextNeurons[i] = sigmoid(nextNeurons[i] + biasWeights[i]);
}
}
private static float sigmoid(float value) {
return (float) (1 / (1 + Math.exp(-value)));
}
Моя проблема заключается в том, что я не могу понять как ее правильно обучить используя метод обратного распространения ошибки. Я не нашел понятной мне информации о том как использовать этот метод на нескольких выходящих нейронах, в большинстве случаев все примеры и объяснения показываются на одном выходящем нейроне.
Основываясь на полученной информации об обучении на одном выходящем нейроне, я предположил, что формулы для меня будут выглядеть так:
После вычисления ошибок составлю формулы получения нового веса:
Правильно ли я сделал формулы? Так же я не уверен в правильности текущего кода.
Спасибо!
Ответ
Вообщем, не долго думая я решил перенести мои предположения в код. На мое удивление все начало работать замечательно, я проверил нейронную сеть на нескольких простых задача и результаты не стали себя долго ждать!
Спасибо всем, кто пытался помочь!
Комментариев нет:
Отправить комментарий