neural network c++ image-processing machine-learning neural-network gradient

c++ - Neural Network not learning-Datos de MNIST-Reconocimiento de escritura a mano



neural network c++ (1)

Esta respuesta se copia del comentario de OP sobre la pregunta.

Resolví el acertijo. Había cometido el peor error posible. Estaba dando una entrada equivocada. He usado opencv para escanear las imágenes, en lugar de usar reshape , estaba usando el resize y la entrada fue de interpolación lineal de imágenes. Entonces mi entrada fue incorrecta. No había nada de malo con el código. Mi red es 784 - 65 - 10 con un 96.43% de precisión.

He escrito un programa de red neuronal. Funciona para Logic Gates, pero cuando intento usarlo para reconocer dígitos escritos a mano, simplemente no aprende.

Por favor encuentre el código a continuación:

// Esta es una sola neurona; esto podría ser necesario para entender el código restante

typedef struct SingleNeuron { double outputValue; std::vector<double> weight; std::vector<double> deltaWeight; double gradient; double sum; }SingleNeuron;

Entonces inicializo la red. Establecí los pesos para que sean valores aleatorios entre -0.5 a +0.5, suma a 0, deltaWeight a 0

Luego viene FeedForward:

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; }

Mi función de transferencia y su derivada se menciona al final.

Después de esto, intento retroceder usando:

// 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; } } }

Estos son TransferFuntion y su derivado;

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; }

Una cosa que observé Si uso la función sigmoidea estándar para ser mi función de transferencia Y si paso la salida de la neurona a la función de transferencia - El resultado es INFINITO. Pero tanh (x) funciona bien con este valor

Entonces, si estoy usando 1/1 + e ^ (- x) como función de transferencia, tengo que pasar la Sum of Net Inputs y siendo tanh mi función de transferencia, tengo que pasar la output de la neurona actual.

No entiendo completamente por qué es así, puede ser que esto requiera una pregunta diferente.

Pero esta pregunta es realmente sobre otra cosa: LA RED ESTÁ TRABAJANDO PARA LAS PUERTAS LÓGICAS PERO NO PARA EL RECONOCIMIENTO DEL CARÁCTER

He intentado muchas variaciones / combinaciones de Learning Rate de Learning Rate y Acceleration y # hidden layers y their sizes . Encuentre los resultados a continuación:

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

Después de ver los resultados, es posible que sienta que este tipo simplemente está atrapado en los mínimos locales, pero espere y lea lo siguiente:

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

Arriba está la salida de la época # 996, # 997, # 998 y # 999

Entonces, simplemente, la red no está aprendiendo. Para esto, por ejemplo, he usado ALPHA = 0.4, ETA = 0.7, 10 capas ocultas, cada una de 100 neuronas y el promedio es de más de 10 épocas. Si le preocupa que Learning Rate sea de 0,4 o más capas ocultas, ya he probado sus variaciones. Por ejemplo, para una tasa de aprendizaje de 0,1 y 4 capas ocultas, cada una 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

Estoy tan seguro de que me he perdido algo. No soy capaz de resolverlo. He leído el algoritmo de Tom Mitchel muchas veces, pero no sé lo que está mal. Cualquiera que sea el ejemplo que resuelvo a mano, ¡funciona! (Por favor, no me pidas que resuelva imágenes de datos MNIST a mano;)) No sé dónde cambiar el código, qué hacer ... por favor ayuda ...

EDITAR - Carga de más datos según sugerencias en comentarios

1 capa oculta de 32 - todavía no hay aprendizaje.

Salida esperada - La entrada es imágenes entre 0-9, entonces un vector simple que describe cuál es la imagen actual, ese bit es 1 todos los demás son 0. Entonces quisiera que la salida sea tan cercana a 1 para ese bit en particular y que otros estén cerca a 0 Por ejemplo, si la entrada es Input = [0, 0, 0, 0, 0, 0, 1, 0, 0, 0] Me gustaría que la salida fuera algo así como Output = 0.002023, 0.0914957, 0.059178, 0.09339, 0.011851, 0.0842454, 0.924834, 0.049892, 0.0651799, 0.063558 (Esto es vago, generado a mano)

Aquí están los enlaces del trabajo de otros investigadores.

Stanford

SourceForge - Esto es más bien una biblioteca

No solo estos 2, hay tantos sitios que muestran las demostraciones.

Las cosas están funcionando bastante bien para ellos. Si configuro mis parámetros de red (Alpha, ETA) como ellos, no obtengo resultados como estos, así que esto es una garantía de que algo anda mal con mi código.

EDIT 2

Agregar más casos de falla

Accelaration - 0.7, Tasa de aprendizaje 0.1

Accelaration - 0.7, Tasa de aprendizaje 0.6

En los dos casos anteriores, las capas ocultas fueron 3, cada una de 32 neuronas.