Le réseau neuronal n'apprend pas - données MNIST-reconnaissance de L'écriture
j'ai écrit un programme de réseau neuronal. Il fonctionne pour les portes de logique, mais quand je tente de l'utiliser pour la reconnaissance des chiffres manuscrits - il n'apprend tout simplement pas.
vous trouverez le code ci-dessous:
/ / il s'agit d'un seul neurone; cela pourrait être nécessaire pour comprendre le code restant
typedef struct SingleNeuron
{
double outputValue;
std::vector<double> weight;
std::vector<double> deltaWeight;
double gradient;
double sum;
}SingleNeuron;
puis j'initialise le net. J'ai fixé les poids à une valeur aléatoire de -0,5 à + 0,5, somme à 0, deltaWeight à 0
Puis vient le Anticipation:
for (unsigned i = 0; i < inputValues.size(); ++i)
{
neuralNet[0][i].outputValue = inputValues[i];
neuralNet[0][i].sum = 0.0;
// std::cout << "o/p Val = " << neuralNet[0][i].outputValue << std::endl;
}
for (unsigned i = 1; i < neuralNet.size(); ++i)
{
std::vector<SingleNeuron> prevLayerNeurons = neuralNet[i - 1];
unsigned j = 0;
double thisNeuronOPVal = 0;
// std::cout << std::endl;
for (j = 0; j < neuralNet[i].size() - 1; ++j)
{
double sum = 0;
for (unsigned k = 0; k < prevLayerNeurons.size(); ++k)
{
sum += prevLayerNeurons[k].outputValue * prevLayerNeurons[k].weight[j];
}
neuralNet[i][j].sum = sum;
neuralNet[i][j].outputValue = TransferFunction(sum);
// std::cout << neuralNet[i][j].outputValue << "t";
}
// std::cout << std::endl;
}
ma fonction de transfert et sa dérivée est mentionnée à la fin.
Après ce que j'ai essayer de l'arrière-propager à l'aide de:
// calculate output layer gradients
for (unsigned i = 0; i < outputLayer.size() - 1; ++i)
{
double delta = actualOutput[i] - outputLayer[i].outputValue;
outputLayer[i].gradient = delta * TransferFunctionDerivative(outputLayer[i].sum);
}
// std::cout << "Found Output gradients "<< std::endl;
// calculate hidden layer gradients
for (unsigned i = neuralNet.size() - 2; i > 0; --i)
{
std::vector<SingleNeuron>& hiddenLayer = neuralNet[i];
std::vector<SingleNeuron>& nextLayer = neuralNet[i + 1];
for (unsigned j = 0; j < hiddenLayer.size(); ++j)
{
double dow = 0.0;
for (unsigned k = 0; k < nextLayer.size() - 1; ++k)
{
dow += nextLayer[k].gradient * hiddenLayer[j].weight[k];
}
hiddenLayer[j].gradient = dow * TransferFunctionDerivative(hiddenLayer[j].sum);
}
}
// std::cout << "Found hidden layer gradients "<< std::endl;
// from output to 1st hidden layer, update all weights
for (unsigned i = neuralNet.size() - 1; i > 0; --i)
{
std::vector <SingleNeuron>& currentLayer = neuralNet[i];
std::vector <SingleNeuron>& prevLayer = neuralNet[i - 1];
for (unsigned j = 0; j < currentLayer.size() - 1; ++j)
{
for (unsigned k = 0; k < prevLayer.size(); ++k)
{
SingleNeuron& thisNeueon = prevLayer[k];
double oldDeltaWeight = thisNeueon.deltaWeight[j];
double newDeltaWeight = ETA * thisNeueon.outputValue * currentLayer[j].gradient + (ALPHA * oldDeltaWeight);
thisNeueon.deltaWeight[j] = newDeltaWeight;
thisNeueon.weight[j] += newDeltaWeight;
}
}
}
ce sont les TransferFuntion et de ses dérivés;
double TransferFunction(double x)
{
double val;
//val = tanh(x);
val = 1 / (1 + exp(x * -1));
return val;
}
double TransferFunctionDerivative(double x)
{
//return 1 - x * x;
double val = exp(x * -1) / pow((exp(x * -1) + 1), 2);
return val;
}
une chose que j'ai observée si j'utilise la fonction sigmoïde standard pour être ma fonction de transfert et si je passe la sortie du neurone à la fonction de transfert - résultat est L'infini. Mais tanh (x) fonctionne bien avec cette valeur
donc si je j'utilise 1/1+e^(- x) comme fonction de transfert je dois passer Sum of Net Inputs
et tanh
étant ma fonction de transfert je dois passer output
du neurone actuel.
Je ne comprends pas tout à fait pourquoi c'est ainsi, peut-être que cela appelle une autre question.
Mais cette question est vraiment quelque chose d'autre: LE RÉSEAU FONCTIONNE POUR DES PORTES LOGIQUES MAIS PAS POUR LA RECONNAISSANCE DE CARACTÈRES
j'ai essayé beaucoup de variations/combinaisons de Learning Rate
et Acceleration
et # hidden layers
et their sizes
. Vous trouverez les résultats ci-dessous:
AvgErr: 0.299399 #Pass799
AvgErr : 0.305071 #Pass809
AvgErr : 0.303046 #Pass819
AvgErr : 0.299569 #Pass829
AvgErr : 0.30413 #Pass839
AvgErr : 0.304165 #Pass849
AvgErr : 0.300529 #Pass859
AvgErr : 0.302973 #Pass869
AvgErr : 0.299238 #Pass879
AvgErr : 0.304708 #Pass889
AvgErr : 0.30068 #Pass899
AvgErr : 0.302582 #Pass909
AvgErr : 0.301767 #Pass919
AvgErr : 0.303167 #Pass929
AvgErr : 0.299551 #Pass939
AvgErr : 0.301295 #Pass949
AvgErr : 0.300651 #Pass959
AvgErr : 0.297867 #Pass969
AvgErr : 0.304221 #Pass979
AvgErr : 0.303702 #Pass989
après avoir regardé les résultats, vous pourriez penser que ce gars est simplement coincé dans les minima locaux, mais s'il vous plaît attendre et lire à travers:
Input = [0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
Output = 0.0910903, 0.105674, 0.064575, 0.0864824, 0.128682, 0.0878434, 0.0946296, 0.154405, 0.0678767, 0.0666924
Input = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Output = 0.0916106, 0.105958, 0.0655508, 0.086579, 0.126461, 0.0884082, 0.110953, 0.163343, 0.0689315, 0.0675822
Input = [0, 0, 0, 1, 0, 0, 0, 0, 0, 0]
Output = 0.105344, 0.105021, 0.0659517, 0.0858077, 0.123104, 0.0884107, 0.116917, 0.161911, 0.0693426, 0.0675156
Input = [0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
Output = , 0.107113, 0.101838, 0.0641632, 0.0967766, 0.117149, 0.085271, 0.11469, 0.153649, 0.0672772, 0.0652416
ci-dessus est la sortie de l'époque #996, #997,#998 et #999
Donc simplement de réseau n'est pas l'apprentissage. Pour cela, par exemple, J'ai utilisé ALPHA = 0,4, ETA = 0,7, 10 couches cachées de 100 neurones chacune et la moyenne est supérieure à 10 époques. Si vous sont préoccupés par le taux D'apprentissage étant 0,4 ou tant de couches cachées que j'ai déjà essayé leurs variations. Par exemple pour taux d'apprentissage étant 0,1 et 4 couches cachées - chacune de 16
Input = [0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
Output = 0.0883238, 0.0983253, 0.0613749, 0.0809751, 0.124972, 0.0897194, 0.0911235, 0.179984, 0.0681346, 0.0660039
Input = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Output = 0.0868767, 0.0966924, 0.0612488, 0.0798343, 0.120353, 0.0882381, 0.111925, 0.169309, 0.0676711, 0.0656819
Input = [0, 0, 0, 1, 0, 0, 0, 0, 0, 0]
Output = 0.105252, 0.0943837, 0.0604416, 0.0781779, 0.116231, 0.0858496, 0.108437, 0.1588, 0.0663156, 0.0645477
Input = [0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
Output = 0.102023, 0.0914957, 0.059178, 0.09339, 0.111851, 0.0842454, 0.104834, 0.149892, 0.0651799, 0.063558
je suis tellement sûr que j'ai manqué quelque chose. Je ne suis pas en mesure de le comprendre. J'ai lu L'algorithme de Tom Mitchel tant de fois, mais je ne sais pas ce qui ne va pas. Quel que soit l'exemple que je résous à la main! (Merci de ne pas me demander de résoudre MNIST de données d'images à la main ;) ) je ne sais pas où changer le code, quoi faire.. s'il vous plaît aider..
MODIFIER -- le Téléchargement de plus de données que par des suggestions dans les commentaires
1 couche cachée de 32 -- toujours pas d'apprentissage.
Prévue de Sortie-Entrée est des images entre 0 à 9, de sorte qu'un simple vecteur décrivant ce qui est de l'image courante, que le bit est à 1, tous les autres sont à 0. Donc je voudrais que la sortie soit aussi proche de 1 pour ce bit particulier et que les autres soient proches de 0 pour par exemple si input est Input = [0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
je voudrais la sortie de quelque chose comme Output = 0.002023, 0.0914957, 0.059178, 0.09339, 0.011851, 0.0842454, 0.924834, 0.049892, 0.0651799, 0.063558
(C'est vague, la main-généré)
Voici les liens des travaux d'autres chercheurs.
SourceForge -- C'est plutôt une bibliothèque
non seulement ces deux-là, mais il y a tellement de sites qui montrent les démos.
les choses fonctionnent très bien pour eux. Si je mets mes paramètres réseau (Alpha, ETA) comme eux, je n'obtiens pas de résultats comme eux, donc ceci c'est rassurant que quelque chose ne va pas avec mon code.
EDIT 2
Ajout de plus de cas d'insuffisance
Accelaration - 0.7, L'Apprentissage Des Taux De 0,1
Accelaration - 0.7, L'Apprentissage Des Taux De 0,6
dans les deux cas ci-dessus, les couches cachées étaient de 3, chacune de 32 neurones.
1 réponses
cette réponse est tirée du commentaire de L'OP sur la question.
j'ai résolu le puzzle. J'avais fait la pire erreur possible. Je donnais une mauvaise réponse. J'ai utilisé opencv pour numériser les images, au lieu d'utiliser reshape
j'ai été en utilisant resize
et ainsi l'entrée était l'interpolation linéaire des images. Donc ma contribution était fausse. Il n'y avait rien de mal avec le code. Mon réseau est 784 - 65 - 10
donnant une précision de 96,43%.