اختراع دراجة أو كتابة مدبر في 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