Я не могу найти, что не так с моей нейронной сетью, несмотря на проверку моей сети на основе этого примера , который предполагает, что мой backprop и forward prop работает нормально.Однако после обучения по XOR моя сеть возвращает около 0,5 для вывода независимо от ввода.Другими словами, сеть, по-видимому, сводит ошибку к минимуму, насколько это возможно, не видя никакой связи между входом и выходом.Поскольку одиночная итерация обратного распространения кажется работает нормально, мой инстинкт подсказывает, что проблема заключается в том, чтобы каким-то образом следовать следующим итерациям.Тем не менее, нет никакой очевидной проблемы, которая могла бы вызвать это, оставив меня в замешательстве.
Я смотрел на другие потоки, где возникли подобные проблемы, но, похоже, большую часть времени их ошибка либо чрезвычайнониша к тому, как они настраивают свою сеть, или их параметры, такие как скорость обучения или эпохи, действительно не соответствуют.Кто-нибудь знаком с таким случаем?
public class Net
{
int[] sizes;
double LEARNING_RATE;
double[][][] weights;
double[][] bias;
Random rand = new Random(); //53489085
public Net(int[] sizes_, double LEARNING_RATE_)
{
LEARNING_RATE = LEARNING_RATE_;
sizes = sizes_;
int numInputs = sizes[0];
double range = 1.0 / Math.sqrt(numInputs);
bias = new double[sizes.length - 1][];
weights = new double[sizes.length - 1][][];
for(int w_layer = 0; w_layer < weights.length; w_layer++)
{
bias[w_layer] = new double[sizes[w_layer+1]];
weights[w_layer] = new double[sizes[w_layer+1]][sizes[w_layer]];
for(int j = 0; j < weights[w_layer].length; j++)
{
bias[w_layer][j] = 2*range*rand.nextDouble() - range;
for(int i = 0; i < weights[w_layer][0].length; i++)
{
weights[w_layer][j][i] = 2*range*rand.nextDouble() - range;
}
}
}
}
public double[] evaluate(double[] image_vector)
{
return forwardPass(image_vector)[sizes.length-1];
}
public double totalError(double[][] expec, double[][] actual)
{
double sum = 0;
for(int i = 0; i < expec.length; i++)
{
sum += error(expec[i], evaluate(actual[i]));
}
return sum / expec.length;
}
private double error(double[] expec, double[] actual)
{
double sum = 0;
for(int i = 0; i < expec.length; i++)
{
double del = expec[i] - actual[i];
sum += 0.5 * del * del;
}
return sum;
}
public void backpropagate(double[][] image_vector, double[][] outputs)
{
double[][][] deltaWeights = new double[weights.length][][];
double[][] deltaBias = new double[weights.length][];
for(int w = 0; w < weights.length; w++)
{
deltaBias[w] = new double[bias[w].length];
deltaWeights[w] = new double[weights[w].length][];
for(int j = 0; j < weights[w].length; j++)
{
deltaWeights[w][j] = new double[weights[w][j].length];
}
}
for(int batch = 0; batch < image_vector.length; batch++)
{
double[][] neuronVals = forwardPass(image_vector[batch]);
/* OUTPUT DELTAS */
int w_layer = weights.length-1;
double[] deltas = new double[weights[w_layer].length];
for(int j = 0; j < weights[w_layer].length; j++)
{
double actual = neuronVals[w_layer + 1][j];
double expec = outputs[batch][j];
double deltaErr = actual - expec;
double deltaSig = actual * (1 - actual);
double delta = deltaErr * deltaSig;
deltas[j] = delta;
deltaBias[w_layer][j] += delta;
for(int i = 0; i < weights[w_layer][0].length; i++)
{
deltaWeights[w_layer][j][i] += delta * neuronVals[w_layer][i];
}
}
w_layer--;
/* REST OF THE DELTAS */
while(w_layer >= 0)
{
double[] nextDeltas = new double[weights[w_layer].length];
for(int j = 0; j < weights[w_layer].length; j++)
{
double outNeur = neuronVals[w_layer+1][j];
double deltaSig = outNeur * (1 - outNeur);
double sum = 0;
for(int i = 0; i < weights[w_layer+1].length; i++)
{
sum += weights[w_layer+1][i][j] * deltas[i];
}
double delta = sum * deltaSig;
nextDeltas[j] = delta;
deltaBias[w_layer][j] += delta;
for(int i = 0; i < weights[w_layer][0].length; i++)
{
deltaWeights[w_layer][j][i] += delta * neuronVals[w_layer][i];
}
}
deltas = nextDeltas;
w_layer--;
}
}
for(int w_layer = 0; w_layer < weights.length; w_layer++)
{
for(int j = 0; j < weights[w_layer].length; j++)
{
deltaBias[w_layer][j] /= (double) image_vector.length;
bias[w_layer][j] -= LEARNING_RATE * deltaBias[w_layer][j];
for(int i = 0; i < weights[w_layer][j].length; i++)
{
deltaWeights[w_layer][j][i] /= (double) image_vector.length; // average of batches
weights[w_layer][j][i] -= LEARNING_RATE * deltaWeights[w_layer][j][i];
}
}
}
}
public double[][] forwardPass(double[] image_vector)
{
double[][] outputs = new double[sizes.length][];
double[] inputs = image_vector;
for(int w = 0; w < weights.length; w++)
{
outputs[w] = inputs;
double[] output = new double[weights[w].length];
for(int j = 0; j < weights[w].length; j++)
{
output[j] = bias[w][j];
for(int i = 0; i < weights[w][j].length; i++)
{
output[j] += weights[w][j][i] * inputs[i];
}
output[j] = sigmoid(output[j]);
}
inputs = output;
}
outputs[outputs.length-1] = inputs.clone();
return outputs;
}
static public double sigmoid(double val)
{
return 1.0 / (1.0 + Math.exp(-val));
}
}
И мой класс XOR выглядит следующим образом.Маловероятно, что ошибка заключается в этой части, учитывая ее простоту, но я подумал, что опубликовать сообщение не повредит, если у меня возникнет какое-то фундаментальное недопонимание того, как работает XOR.Моя сеть настроена на то, чтобы брать примеры в пакетах, но, как вы можете видеть ниже для этого конкретного примера, я отправляю его партиями по одному, или фактически не использую пакеты.что может быть не так?Мои параметры довольно хорошо определены, и я следовал всем советам о том, как следует инициализировать веса, какова должна быть скорость обучения и т. Д. Спасибо!