J'essaie d'enseigner un réseau neuronal de 2 entrées, 4 nœuds cachés (tous dans la même couche) et 1 nœud de sortie. La représentation binaire fonctionne bien, mais j'ai des problèmes avec le bipolaire. Je ne peux pas comprendre pourquoi, mais l'erreur totale convergera parfois vers le même nombre autour de 2.xx. Mon sigmoïde est 2/(1+ exp (-x)) - 1. Peut-être que je suis en train de stigmatiser au mauvais endroit. Par exemple, pour calculer l'erreur de sortie, dois-je comparer la sortie sigmoided avec la valeur attendue ou avec la valeur attendue sigmoided?Enseigner un réseau neuronal: Bipolar XOR
Je suivais ce site Web ici: http://galaxy.agh.edu.pl/~vlsi/AI/backp_t_en/backprop.html, mais ils utilisent des fonctions différentes que j'ai été chargé d'utiliser. Même lorsque j'ai essayé d'implémenter leurs fonctions, j'ai toujours rencontré le même problème. De toute façon, je suis coincé environ la moitié du temps au même numéro (un nombre différent pour différentes implémentations). S'il vous plaît dites-moi si j'ai fait une erreur dans mon code quelque part ou si c'est normal (je ne vois pas comment cela pourrait être). Momentum est mis à 0. Est-ce un problème d'élan 0 commun? Les fonctions d'erreur que nous sommes censés être à l'aide sont:
si ui est une unité de sortie
Error(i) = (Ci - ui) * f'(Si)
si ui est une unité cachée
Error(i) = Error(Output) * weight(i to output) * f'(Si)
public double sigmoid(double x) {
double fBipolar, fBinary, temp;
temp = (1 + Math.exp(-x));
fBipolar = (2/temp) - 1;
fBinary = 1/temp;
if(bipolar){
return fBipolar;
}else{
return fBinary;
}
}
// Initialize the weights to random values.
private void initializeWeights(double neg, double pos) {
for(int i = 0; i < numInputs + 1; i++){
for(int j = 0; j < numHiddenNeurons; j++){
inputWeights[i][j] = Math.random() - pos;
if(inputWeights[i][j] < neg || inputWeights[i][j] > pos){
print("ERROR ");
print(inputWeights[i][j]);
}
}
}
for(int i = 0; i < numHiddenNeurons + 1; i++){
hiddenWeights[i] = Math.random() - pos;
if(hiddenWeights[i] < neg || hiddenWeights[i] > pos){
print("ERROR ");
print(hiddenWeights[i]);
}
}
}
// Computes output of the NN without training. I.e. a forward pass
public double outputFor (double[] argInputVector) {
for(int i = 0; i < numInputs; i++){
inputs[i] = argInputVector[i];
}
double weightedSum = 0;
for(int i = 0; i < numHiddenNeurons; i++){
weightedSum = 0;
for(int j = 0; j < numInputs + 1; j++){
weightedSum += inputWeights[j][i] * inputs[j];
}
hiddenActivation[i] = sigmoid(weightedSum);
}
weightedSum = 0;
for(int j = 0; j < numHiddenNeurons + 1; j++){
weightedSum += (hiddenActivation[j] * hiddenWeights[j]);
}
return sigmoid(weightedSum);
}
//Computes the derivative of f
public static double fPrime(double u){
double fBipolar, fBinary;
fBipolar = 0.5 * (1 - Math.pow(u,2));
fBinary = u * (1 - u);
if(bipolar){
return fBipolar;
}else{
return fBinary;
}
}
// This method is used to update the weights of the neural net.
public double train (double [] argInputVector, double argTargetOutput){
double output = outputFor(argInputVector);
double lastDelta;
double outputError = (argTargetOutput - output) * fPrime(output);
if(outputError != 0){
for(int i = 0; i < numHiddenNeurons + 1; i++){
hiddenError[i] = hiddenWeights[i] * outputError * fPrime(hiddenActivation[i]);
deltaHiddenWeights[i] = learningRate * outputError * hiddenActivation[i] + (momentum * lastDelta);
hiddenWeights[i] += deltaHiddenWeights[i];
}
for(int in = 0; in < numInputs + 1; in++){
for(int hid = 0; hid < numHiddenNeurons; hid++){
lastDelta = deltaInputWeights[in][hid];
deltaInputWeights[in][hid] = learningRate * hiddenError[hid] * inputs[in] + (momentum * lastDelta);
inputWeights[in][hid] += deltaInputWeights[in][hid];
}
}
}
return 0.5 * (argTargetOutput - output) * (argTargetOutput - output);
}