Inventar una bicicleta o escribir un perceptrón en C ++. Parte 3

Inventar una bicicleta o escribir un perceptrón en C ++. Parte 3



Implementemos el entrenamiento de un perceptrón multicapa en C ++ usando el método de retropropagación.







Prefacio



¡Hola a todos!) Antes de pasar a la base de este artículo, me gustaría decir algunas palabras sobre las partes anteriores. La implementación que propuse es una burla de la RAM de la computadora, tk. un vector tridimensional viola la memoria con abundancia de celdas vacías, para las que también está reservada la memoria. Por lo tanto, el método está lejos de ser el mejor, pero espero que ayude a los programadores principiantes en esta área a comprender lo que hay "debajo del capó" de las redes neuronales más simples. Esta vez. Al describir la función de activación en la primera parte, cometí un error: la función de activación no tiene que estar limitada en el rango de valores. Todo depende de los objetivos del programador. La única condición es que la función debe definirse en todo el eje numérico. Son dos



Introducción



-, . backpropagation — . , !



: habr.com/ru/post/514372





backpropagation — .



, , , .



:



, , . , , . , , . : dj=f(netj)(1f(netj))kdkwkj (1), j — , , k — , , .. .



, . "O". n6 d6 = (O — y)*( f(in) )*(1 — f(in) ) (2), in —

n6, f(in) — .



(1), . n4 :

d4 = d6 * w46 *( f(in4) ) * (1 — f(in4)), w46 — n4 n6, in4 — n4.



d5 = d6 * w56 *( f(in5) ) * (1 — f(in5)), n5.



d1 = (d4 * w14 + d5 * w15) *( f(in1) ) * (1 — f(in1)), n1, , — .



n2 n3 :



d2 = (d4 * w24 + d5 * w25) *( f(in2) ) * (1 — f(in2))



d3 = (d4 * w34 + d5 * w35) *( f(in3) ) * (1 — f(in3))





, , :



Δw46 = d6 * A * f(in4), w46 — n4 n6 , f(in4) — n4, A — , — , .



Δw56 = d6 * A * f(in5), n5 n6.



:



Δw14 = d4 * A * f(in1)



Δw24 = d4 * A * f(in2)



Δw34 = d4 * A * f(in3)



Δw15 = d4 * A * f(in1)



Δw25 = d4 * A * f(in2)



Δw35 = d4 * A * f(in3)



? . .







void NeuralNet::learnBackpropagation(double* data, double* ans, double acs, double k) {  //data -   , ans -     , k -   , acs-  


, - :




for (uint32_t e = 0; e < k; e++) {
		double* errors = new double[neuronsInLayers[numLayers - 1]]; //      
                // "Do_it"    "Forward"
		Forward(neuronsInLayers[0], data);//    
		getResult(neuronsInLayers[numLayers - 1], errors);//     


:




for (uint16_t n = 0; n < neuronsInLayers[numLayers - 1]; n++) {
			neurons[n][2][numLayers - 1] = (ans[n] - neurons[n][1][numLayers - 1]) * (neurons[n][1][numLayers - 1]) * (1 - neurons[n][1][numLayers - 1]);
		}


, :




for (uint8_t L = numLayers - 2; L > 0; L--) {
			for (uint16_t neu = 0; neu < neuronsInLayers[L]; neu++) {
				for (uint16_t lastN = 0; lastN < neuronsInLayers[L + 1]; lastN++) {
					neurons[neu][2][L] += neurons[lastN][2][L + 1] * weights[neu][lastN][L] * neurons[neu][1][L] * (1 - neurons[neu][1][L]);
					weights[neu][lastN][L] += neurons[neu][1][L] * neurons[lastN][2][L + 1] * acs;
				}
			}
		}


:




void NeuralNet::learnBackpropagation(double* data, double* ans, double acs, double k) {  //k -    acs-  
	for (uint32_t e = 0; e < k; e++) {
		double* errors = new double[neuronsInLayers[numLayers - 1]];
		Forward(neuronsInLayers[0], data);
		getResult(neuronsInLayers[numLayers - 1], errors);
		for (uint16_t n = 0; n < neuronsInLayers[numLayers - 1]; n++) {
			neurons[n][2][numLayers - 1] = (ans[n] - neurons[n][1][numLayers - 1]) * (neurons[n][1][numLayers - 1]) * (1 - neurons[n][1][numLayers - 1]);
		}
		for (uint8_t L = numLayers - 2; L > 0; L--) {
			for (uint16_t neu = 0; neu < neuronsInLayers[L]; neu++) {
				for (uint16_t lastN = 0; lastN < neuronsInLayers[L + 1]; lastN++) {
					neurons[neu][2][L] += neurons[lastN][2][L + 1] * weights[neu][lastN][L] * neurons[neu][1][L] * (1 - neurons[neu][1][L]);
					weights[neu][lastN][L] += neurons[neu][1][L] * neurons[lastN][2][L + 1] * acs;
				}
			}
		}
	}
}




. :




#include <stdio.h>
#include "neuro.h"
int main()
{
    
    uint16_t neurons[3] = {16, 32, 10}; //        , -       
/*        ""  
        
*/
    NeuralNet net(3, neurons);
    double teach[4 * 4] = {//  ""  "4"  , - : 4*4 = 16
        1,0,1,0,
        1,1,1,0,
        0,0,1,0,
        0,0,1,0,
    };
    double test[4 * 4] = {//  "4",  -
        1,0,0,1,
        1,1,1,1,
        0,0,0,1,
        0,0,0,1,
    };
    double ans[10] = {0, 0, 0, 0, 1, 0, 0, 0, 0, 0,};//       , "1"    ,       "4"
    double output[10] = { 0 };//      
    net.Forward(4*4, teach); //    
    net.getResult(10, output); 
    for (uint8_t i = 0; i < 10; i++) printf("%d: %f \n", i, output[i]*100); //  
    net.learnBackpropagation(teach, ans, 0.50, 1000); //    "test",  : 0.5
    printf("\n");
    net.Forward(4 * 4, test);//     
    net.getResult(10, output);
    for (uint8_t i = 0; i < 10; i++) printf("%d: %f \n", i, output[i]*100);
    return 0;
}


:









( ), , 0 9. . , «4»

, , - , . . . , , .



...



. , .



Gracias por la atención prestada a este artículo y por los comentarios sobre la publicación anterior. Duplicaré el enlace a los archivos de la biblioteca.



Deja tus comentarios, sugerencias. ¡Nos vemos más tarde!




All Articles