Perceptron l'apprentissage de l'algorithme ne converge pas vers 0

Voici mon perceptron mise en œuvre de la norme ANSI C:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
float randomFloat()
{
srand(time(NULL));
float r = (float)rand() / (float)RAND_MAX;
return r;
}
int calculateOutput(float weights[], float x, float y)
{
float sum = x * weights[0] + y * weights[1];
return (sum >= 0) ? 1 : -1;
}
int main(int argc, char *argv[])
{
//X, Y coordinates of the training set.
float x[208], y[208];
//Training set outputs.
int outputs[208];
int i = 0; //iterator
FILE *fp;
if ((fp = fopen("test1.txt", "r")) == NULL)
{
printf("Cannot open file.\n");
}
else
{
while (fscanf(fp, "%f %f %d", &x[i], &y[i], &outputs[i]) != EOF)
{
if (outputs[i] == 0)
{
outputs[i] = -1;
}
printf("%f   %f   %d\n", x[i], y[i], outputs[i]);
i++;
}
}
system("PAUSE");
int patternCount = sizeof(x) / sizeof(int);
float weights[2];
weights[0] = randomFloat();
weights[1] = randomFloat();
float learningRate = 0.1;
int iteration = 0;
float globalError;
do {
globalError = 0;
int p = 0; //iterator
for (p = 0; p < patternCount; p++)
{
//Calculate output.
int output = calculateOutput(weights, x[p], y[p]);
//Calculate error.
float localError = outputs[p] - output;
if (localError != 0)
{
//Update weights.
for (i = 0; i < 2; i++)
{
float add = learningRate * localError;
if (i == 0)
{
add *= x[p];
}
else if (i == 1)
{
add *= y[p];
}
weights[i] +=  add;
}
}
//Convert error to absolute value.
globalError += fabs(localError);
printf("Iteration %d Error %.2f %.2f\n", iteration, globalError, localError);
iteration++;
}
system("PAUSE");
} while (globalError != 0);
system("PAUSE");
return 0;
}

L'ensemble de la formation, je suis en utilisant: Ensemble De Données

J'ai supprimé toutes pertinence de code. Fondamentalement, ce qu'il fait maintenant, il lit test1.txt fichier et charges des valeurs pour les trois tableaux: x, y, outputs.

Puis il y a une perceptron algorithme d'apprentissage qui, pour une raison quelconque, ne converge pas vers 0 (globalError devrait converger vers 0) et donc j'obtiens une infinie boucle do while.

Lorsque j'utilise un petit ensemble de formation (5 points), cela fonctionne assez bien. Toute idée d'où pourrait être le problème?

J'ai écrit cet algorithme très similaire à ce C# algorithme du Perceptron:


EDIT:

Voici un exemple avec un plus petit ensemble de formation:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
float randomFloat()
{
float r = (float)rand() / (float)RAND_MAX;
return r;
}
int calculateOutput(float weights[], float x, float y)
{
float sum = x * weights[0] + y * weights[1];
return (sum >= 0) ? 1 : -1;
}
int main(int argc, char *argv[])
{
srand(time(NULL));
//X coordinates of the training set.
float x[] = { -3.2, 1.1, 2.7, -1 };
//Y coordinates of the training set.
float y[] = { 1.5, 3.3, 5.12, 2.1 };
//The training set outputs.
int outputs[] = { 1, -1, -1, 1 };
int i = 0; //iterator
FILE *fp;
system("PAUSE");
int patternCount = sizeof(x) / sizeof(int);
float weights[2];
weights[0] = randomFloat();
weights[1] = randomFloat();
float learningRate = 0.1;
int iteration = 0;
float globalError;
do {
globalError = 0;
int p = 0; //iterator
for (p = 0; p < patternCount; p++)
{
//Calculate output.
int output = calculateOutput(weights, x[p], y[p]);
//Calculate error.
float localError = outputs[p] - output;
if (localError != 0)
{
//Update weights.
for (i = 0; i < 2; i++)
{
float add = learningRate * localError;
if (i == 0)
{
add *= x[p];
}
else if (i == 1)
{
add *= y[p];
}
weights[i] +=  add;
}
}
//Convert error to absolute value.
globalError += fabs(localError);
printf("Iteration %d Error %.2f\n", iteration, globalError);          
}
iteration++;
} while (globalError != 0);
//Display network generalisation.
printf("X       Y     Output\n");
float j, k;
for (j = -1; j <= 1; j += .5)
{
for (j = -1; j <= 1; j += .5)
{
//Calculate output.
int output = calculateOutput(weights, j, k);
printf("%.2f  %.2f  %s\n", j, k, (output == 1) ? "Blue" : "Red");
}
}
//Display modified weights.
printf("Modified weights: %.2f %.2f\n", weights[0], weights[1]);
system("PAUSE");
return 0;
}
  • Petite suggestion: Sortie après "Impossible d'ouvrir le fichier" ou au moins d'initialiser les tableaux avec quelque chose dans ce cas.
  • BTW, le jeu de données semble valide - mis en ligne une rapide n'dirty POV-Ray de visualisation: img175.imageshack.us/img175/7135/pointtest.png
  • Pourquoi voulez-vous assumer l'erreur d'aller à 0? Droit maintenant, le globalError est calculé comme le journal de la perte, qui doit être réduite au minimum, mais pas de zéro. Si vos données est voulu par la conception séparable alors le 0-1 perte pourrait frapper 0 (même si ce n'est de nouveau pas certain à cause de la stochasticité de la descente de gradient).
  • Je ne suis pas vraiment bon en maths, mais il devrait converger vers 0 si les deux ensembles de points sont lineary séparables. J'ai aussi vérifié un article de Wikipédia à propos de Perceptron et mon algorithme semble être correct. J'ai ajouté un exemple avec un petit ensemble de formation ci-dessous, vous pouvez vérifier la façon dont il devrait fonctionner.
  • C/C++ Perceptron: sourceforge.net/projects/ccperceptron
  • La suite lib pourrait vous aider: sourceforge.net/projects/c-c-neural-networks

InformationsquelleAutor Richard Knop | 2009-11-08