اختراع دراجة أو كتابة مدبر في C ++. الجزء 1 و 2

اختراع دراجة أو كتابة مدبر في C ++. الجزء 1



دعونا نكتب مكتبة بسيطة لتنفيذ Perceptron في C ++







المقدمة



مرحباً بالجميع ، في هذا المنشور أريد أن أشارككم تجربتي الأولى في كتابة الشبكات العصبية. هناك الكثير من المقالات حول تنفيذ الشبكات العصبية (الشبكات العصبية في المستقبل) على الإنترنت ، لكنني لا أريد استخدام خوارزميات الأشخاص الآخرين دون فهم جوهر عملهم ، لذلك قررت إنشاء الكود الخاص بي من البداية.



في هذا الجزء سوف أصف النقاط الرئيسية للزميل. الأجزاء التي ستكون مفيدة لنا. النظرية كلها مأخوذة من مواقع مختلفة ، بشكل رئيسي من ويكيبيديا.



اربط بالجزء الثالث باستخدام خوارزمية التعلم: habr.com/ru/post/514626



فلنبدأ.





قليلا من النظرية



دعنا نتفق على أنني لا أطالب بلقب "أفضل خوارزمية للتعلم الآلي" ، أنا فقط أعرض تنفيذها وأفكاري. أيضًا ، أنا دائمًا منفتح على النقد البناء والمشورة بشأن الكود ، وهذا أمر مهم ، وهذا ما يوجد من أجله المجتمع.



, .





. .



. :






, (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» .



, , .








, .



. , , , . , .



حسنًا ، لقد تمكنت من شرح مبادئ تخزين القيم الضرورية في الخلايا العصبية. الآن دعنا نتعرف على كيفية تخزين أوزان الوصلات بين الخلايا العصبية.



خذ الشبكة التالية على سبيل المثال:

...





بما أننا نعلم بالفعل كيفية بناء الخلايا العصبية في الذاكرة ، فلنضع جدولًا مشابهًا للأوزان:









هيكلها ليس معقدًا على الإطلاق: على سبيل المثال ، توجد قيمة الوزن بين الخلايا العصبية N1 والخلايا العصبية n1 في الخلية w1-1 ، وبالمثل مع الأوزان الأخرى. لكن مرة أخرى ، هذه المصفوفة مناسبة لتخزين الأوزان فقط بين الطبقتين الأوليين ، ولكن لا تزال هناك أوزان في الشبكة بين الطبقتين الثانية والثالثة. دعنا نستخدم الحيلة المألوفة بالفعل - إضافة بُعد جديد إلى المصفوفة ، ولكن مع تحذير: دع أسماء الخطوط تعرض طبقة الخلايا العصبية على اليسار بالنسبة إلى "حزمة" الأوزان ، وتناسب طبقة الخلايا العصبية الموجودة على اليمين أسماء الأعمدة.



ثم نحصل على الجدول التالي "لحزمة" الأوزان الثانية:







:







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





, .



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


وأخيرًا ، آخر شيء أود التحدث عنه هو وظيفة عرض النتيجة. حسنًا ، نقوم هنا بنسخ القيم من الخلايا العصبية للطبقة الأخيرة إلى المصفوفة التي تم تمريرها إلينا كمعامل:




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


الذهاب إلى غروب الشمس



سنتوقف عند هذا ، سيخصص الجزء التالي لوظيفة واحدة تسمح لك بتدريب الشبكة. نظرًا لتعقيد ووفرة الرياضيات ، قررت إخراجها في جزء منفصل ، حيث سنختبر أيضًا عمل المكتبة بأكملها ككل.



مرة أخرى ، أرحب بنصيحتك وتعليقاتك في التعليقات.



شكرا لاهتمامكم بالمقال نراكم قريبا!



ملاحظة: كما وعدت - رابط إلى المصادر: GitHub








All Articles