Menemukan sepeda atau menulis perceptron di C ++. Bagian 1 dan 2

Menemukan sepeda atau menulis perceptron di C ++. Bagian 1



Mari kita tulis perpustakaan sederhana untuk mengimplementasikan perceptron di C ++







pengantar



Halo semuanya, dalam posting ini saya ingin berbagi dengan Anda pengalaman pertama saya dalam menulis jaringan saraf. Ada banyak artikel tentang penerapan jaringan saraf (jaringan saraf di masa depan) di Internet, tetapi saya tidak ingin menggunakan algoritme orang lain tanpa memahami esensi pekerjaan mereka, jadi saya memutuskan untuk membuat kode sendiri dari awal.



Di bagian ini saya akan menjelaskan poin-poin utama jodoh. bagian yang akan berguna bagi kami. Seluruh teori diambil dari berbagai situs, terutama dari Wikipedia.



Tautkan ke bagian ke-3 dengan algoritme pembelajaran: habr.com/ru/post/514626



Jadi, ayo pergi.





Sedikit teori



Mari setuju bahwa saya tidak mengklaim gelar "algoritme pembelajaran mesin terbaik", saya hanya menunjukkan implementasi dan ide saya. Juga, saya selalu terbuka untuk kritik dan saran yang membangun tentang kode, ini penting, untuk itulah komunitas ada.



, .





. .



. :






, (1, 2, 3), u (w1, w2, w3), :

u = x1*w1 + x2*w2 + x3*w3

:







. y(u), u – . , .



, , . , , . , – (, ). :







(0; 1), . y(u) .



, . , .

, , .



, . , , ( ).



, 2 : , .



:









8 ( n1 n8), u, «y(u)» «err», (). «err» .



, , .








, .



. , , , . , .



Nah, saya berhasil menjelaskan prinsip menyimpan nilai yang diperlukan di neuron. Sekarang mari kita cari tahu cara menyimpan bobot koneksi antar neuron.



Ambil jaringan ini misalnya:

...





Setelah mengetahui cara menyusun neuron dalam memori, mari kita buat tabel serupa untuk bobot:









Strukturnya sama sekali tidak rumit: misalnya, nilai bobot antara neuron N1 dan neuron n1 terkandung dalam sel w1-1, demikian pula dengan bobot lain. Tetapi sekali lagi, matriks seperti itu cocok untuk menyimpan bobot hanya di antara dua lapisan pertama, tetapi masih ada bobot di jaringan antara lapisan kedua dan ketiga. Mari gunakan trik yang sudah dikenal - tambahkan dimensi baru ke larik, tetapi dengan peringatan: biarkan nama baris menampilkan lapisan neuron di sebelah kiri relatif terhadap "bundel" bobot, dan lapisan neuron di sebelah kanan cocok dengan nama kolom.



Kemudian kita mendapatkan tabel berikut untuk "bundel" bobot kedua:







:







«», .. , , « » , - , . )).





, .



C++. 2



, .





, . .



, !



header —



, . header — ( «neuro.h»). :





class NeuralNet {
public:
    NeuralNet(uint8_t L, uint16_t *n);
    void Do_it(uint16_t size, double *data);
    void getResult(uint16_t size, double* data);
    void learnBackpropagation(double* data, double* ans, double acs, double k);
private:
    vector<vector<vector<double>>> neurons;
    vector<vector<vector<double>>> weights;
    uint8_t numLayers;
    vector<double> neuronsInLayers;
    double Func(double in);
    double Func_p(double in);
    uint32_t MaxEl(uint16_t size, uint16_t *arr);
    void CreateNeurons(uint8_t L, uint16_t *n);
    void CreateWeights(uint8_t L, uint16_t *n);

};


, , header' ). :






//  ,       ,        
#ifndef NEURO_H
#define NEURO_H

#include <vector> //    
#include <math.h> //    ,     
#include <stdint.h> //       ,            .


:



NeuralNet(uint8_t L, uint16_t *n);


, , - .



void Do_it(uint16_t size, double *data);


)), .



void getResult(uint16_t size, double* data);


.



void learnBackpropagation(double* data, double* ans, double acs, double k);


, .



, :




    vector<vector<vector<double>>> neurons; //   ,    
    vector<vector<vector<double>>> weights; //   ,       
    uint8_t numLayers; //  
    vector<double> neuronsInLayers; //,      
/*
          ,      ,       ,          ,   
*/
    double Func(double in); //    
    double Func_p(double in); //     
    uint32_t MaxEl(uint16_t size, uint16_t *arr);//       
    void CreateNeurons(uint8_t L, uint16_t *n);//             
    void CreateWeights(uint8_t L, uint16_t *n);


header — :

#endif


header . — source — ).



source —



, .



:




NeuralNet::NeuralNet(uint8_t L, uint16_t *n) {
	CreateNeurons(L, n); //  
	CreateWeights(L, n); //  
	this->numLayers = L;
	this->neuronsInLayers.resize(L);
	for (uint8_t l = 0; l < L; l++)this->neuronsInLayers[l] = n[l]; //       
}


, :




void NeuralNet::Do_it(uint16_t size, double *data) {
	for (int n = 0; n < size; n++) { //       
		neurons[n][0][0] = data[n]; //       
		neurons[n][1][0] = Func(neurons[n][0][0]); //           
	}
	for (int L = 1; L < numLayers; L++) { //                
		for (int N = 0; N < neuronsInLayers[L]; N++) { 
			double input = 0;
			for (int lastN = 0; lastN < neuronsInLayers[L - 1]; lastN++) {//             
				input += neurons[lastN][1][L - 1] * weights[lastN][N][L - 1];
			}
			neurons[N][0][L] = input;
			neurons[N][1][L] = Func(input);
		}
	}
}


Dan terakhir, hal terakhir yang ingin saya bicarakan adalah fungsi untuk menampilkan hasilnya. Nah, di sini kita hanya menyalin nilai dari neuron pada lapisan terakhir ke dalam array yang diberikan kepada kita sebagai parameter:




void NeuralNet::getResult(uint16_t size, double* data) {
	for (uint16_t r = 0; r < size; r++) {
		data[r] = neurons[r][1][numLayers - 1];
	}
}


Pergi ke matahari terbenam



Kami akan berhenti di sini, bagian selanjutnya akan dikhususkan untuk satu fungsi tunggal yang memungkinkan Anda untuk melatih jaringan. Karena kerumitan dan kelimpahan matematika, saya memutuskan untuk mengeluarkannya di bagian terpisah, di mana kami juga akan menguji pekerjaan seluruh perpustakaan secara keseluruhan.



Sekali lagi, saya menyambut saran dan komentar Anda di komentar.



Terima kasih atas perhatiannya pada artikel ini, sampai jumpa!



PS: Seperti yang dijanjikan - tautan ke sumber: GitHub








All Articles