तंत्रिका नेटवर्क का विषय पहले से ही हब पर एक से अधिक बार कवर किया गया है, लेकिन आज मैं त्रुटि के पीछे प्रसार के तरीके से एक बहुपरत तंत्रिका नेटवर्क को प्रशिक्षित करने के लिए एल्गोरिदम से पाठकों को परिचित कराना चाहूंगा और इस पद्धति का कार्यान्वयन करूंगा।
मैं तुरंत एक आरक्षण करना चाहता हूं कि मैं तंत्रिका नेटवर्क के क्षेत्र में विशेषज्ञ नहीं हूं, इसलिए मुझे पाठकों से रचनात्मक आलोचना, टिप्पणियों और परिवर्धन की उम्मीद है।
सैद्धांतिक भाग
यह सामग्री तंत्रिका नेटवर्क की मूल बातें से परिचित हो जाती है, लेकिन मैं तंत्रिका नेटवर्क के सिद्धांत पर अनावश्यक परीक्षणों के बिना पाठक को विषय के पाठ्यक्रम से परिचित करना संभव मानता हूं। तो, उन लोगों के लिए जो पहली बार वाक्यांश "तंत्रिका नेटवर्क" सुनते हैं, मैं तंत्रिका नेटवर्क को एक भारित निर्देशित ग्राफ के रूप में देखने का प्रस्ताव करता हूं जिनके नोड्स (न्यूरॉन्स) परतों में व्यवस्थित होते हैं। इसके अलावा, एक परत के नोड में पिछली परत के सभी नोड्स के साथ कनेक्शन हैं। हमारे मामले में, इस तरह के ग्राफ में इनपुट और आउटपुट परतें होंगी, जिनमें से नोड्स इनपुट के रूप में काम करते हैं और
क्रमशः आउटपुट। प्रत्येक नोड (न्यूरॉन) में एक सक्रियण फ़ंक्शन होता है - नोड (न्यूरॉन) के आउटपुट पर सिग्नल की गणना के लिए जिम्मेदार फ़ंक्शन। विस्थापन की अवधारणा भी है, जो एक नोड है, जिसका आउटपुट हमेशा इकाई दिखाई देता है। इस लेख में, हम एक तंत्रिका नेटवर्क की सीखने की प्रक्रिया पर विचार करेंगे, जो "शिक्षक" की उपस्थिति को मानता है, अर्थात, सीखने की प्रक्रिया जिसमें सीखने को सही प्रतिक्रियाओं के साथ प्रशिक्षण उदाहरणों के अनुक्रम के साथ नेटवर्क प्रदान करके होता है।
जैसा कि अधिकांश तंत्रिका नेटवर्क के मामले में, हमारा लक्ष्य नेटवर्क को इस तरह से प्रशिक्षित करना है जैसे कि सीखने की प्रक्रिया में उपयोग किए गए इनपुट डेटा (याद रखना) और इनपुट डेटा के जवाब में सही परिणाम उत्पन्न करने की क्षमता के बीच नेटवर्क की क्षमता के बीच संतुलन हासिल करना है। समान, लेकिन उन लोगों के समान नहीं जो प्रशिक्षण में उपयोग किए गए थे (सामान्यीकरण के सिद्धांत)। त्रुटि वापस प्रसार विधि का उपयोग करते हुए एक नेटवर्क को सीखना तीन चरणों में शामिल है: इनपुट को डेटा खिलाना, इसके बाद आउटपुट की दिशा में डेटा वितरण, गणना करना और संबंधित त्रुटि का प्रचार करना और वजन को समायोजित करना। प्रशिक्षण के बाद, यह केवल नेटवर्क के इनपुट को डेटा की आपूर्ति करने और उन्हें आउटपुट की दिशा में वितरित करने के लिए माना जाता है। उसी समय, यदि नेटवर्क प्रशिक्षण एक लंबी प्रक्रिया हो सकती है, तो एक प्रशिक्षित नेटवर्क द्वारा परिणामों की प्रत्यक्ष गणना बहुत तेज है। इसके अलावा, प्रवाह प्रसार को बढ़ाने के लिए डिज़ाइन किए गए पीछे के प्रसार विधि के कई रूप हैं।
सीखने की प्रक्रिया।
यह भी ध्यान देने योग्य है कि सिंगल-लेयर न्यूरल नेटवर्क काफी सीमित है कि वह किस ट्रेनिंग में इनपुट टेम्प्लेट के अधीन है, जबकि मल्टी-लेयर नेटवर्क (एक या अधिक छिपी परतों के साथ) में ऐसी कोई खामी नहीं है। इसके बाद, त्रुटि के प्रसार के साथ एक मानक तंत्रिका नेटवर्क का विवरण दिया जाएगा।
आर्किटेक्चर
चित्रा 1 छिपे हुए न्यूरॉन्स (तत्वों जेड) की एक परत के साथ एक बहुपरत तंत्रिका नेटवर्क को दर्शाता है।

नेटवर्क आउटपुट का प्रतिनिधित्व करने वाले न्यूरॉन्स (द्वारा दर्शाया गया है

), और छिपे हुए न्यूरॉन्स पक्षपाती हो सकते हैं (जैसा कि छवि में दिखाया गया है)। आउटपुट ऑफसेट

नामित

छिपा हुआ तत्व

-

। ये विस्थापन न्यूरॉन्स से निकलने वाले बॉन्ड पर भार के रूप में काम करते हैं, जिनमें से आउटपुट हमेशा 1 दिखाई देता है (वे चित्र 1 में दिखाए गए हैं, लेकिन आमतौर पर प्रदर्शित नहीं होते हैं, निहित)। इसके अलावा, चित्रा 1 में, तीर इनपुट से आउटपुट तक डेटा प्रसार के चरण के दौरान सूचना के आंदोलन को दिखाते हैं। सीखने की प्रक्रिया में, संकेत विपरीत दिशा में प्रचार करते हैं।
एल्गोरिथम विवरण
नीचे प्रस्तुत एल्गोरिथ्म एक छिपे हुए परत के साथ एक तंत्रिका नेटवर्क पर लागू होता है, जो अधिकांश अनुप्रयोगों के लिए स्वीकार्य और पर्याप्त स्थिति है। जैसा कि पहले उल्लेख किया गया है, नेटवर्क प्रशिक्षण में तीन चरण शामिल हैं: नेटवर्क इनपुट को प्रशिक्षण डेटा की आपूर्ति, त्रुटियों का प्रसार, और वजन में सुधार। पहले चरण के दौरान, प्रत्येक इनपुट न्यूरॉन

एक संकेत प्राप्त करता है और इसे प्रत्येक छिपे हुए न्यूरॉन्स को प्रसारित करता है

। प्रत्येक छिपा हुआ न्यूरॉन तब अपने सक्रियण फ़ंक्शन (नेटवर्क फ़ंक्शन) के परिणाम की गणना करता है और अपना सिग्नल भेजता है

सभी आउटपुट न्यूरॉन्स। हर आउटपुट न्यूरॉन

बदले में, इसके सक्रियण समारोह के परिणाम की गणना करता है

, जो कि संबंधित इनपुट डेटा के लिए दिए गए न्यूरॉन के आउटपुट सिग्नल के अलावा कुछ भी नहीं है। सीखने की प्रक्रिया में, नेटवर्क के आउटपुट पर प्रत्येक न्यूरॉन गणना किए गए मूल्य की तुलना करता है

शिक्षक के साथ प्रदान किया गया

(लक्ष्य मान), दिए गए इनपुट पैटर्न के लिए संबंधित त्रुटि मान का निर्धारण करना। इस त्रुटि के आधार पर गणना की जाती है

।

से त्रुटियों का प्रचार करते समय उपयोग किया जाता है

पिछली परत के सभी नेटवर्क तत्वों (छिपे हुए न्यूरॉन्स के साथ जुड़े)

), और बाद में भी जब आउटपुट न्यूरॉन्स और छिपे हुए लोगों के बीच कनेक्शन के वजन को बदलते हैं। इसी तरह गणना की जाती है

हर छिपे हुए न्यूरॉन के लिए

। यद्यपि इनपुट लेयर में त्रुटि को प्रचारित करने की आवश्यकता नहीं है,

छिपी हुई परत और इनपुट न्यूरॉन्स के न्यूरॉन्स के बीच कनेक्शन के वजन को बदलने के लिए उपयोग किया जाता है। आखिरकार

पहचान की गई है, सभी बांडों के वजन का एक साथ समायोजन है।
लीजेंड:
निम्नलिखित लर्निंग का उपयोग नेटवर्क लर्निंग एल्गोरिदम में किया जाता है:

प्रशिक्षण डाटा इनपुट वेक्टर


शिक्षक द्वारा प्रदान किए गए लक्ष्य आउटपुट का वेक्टर


घटक समायोजन वजन को जोड़ता है

आउटपुट न्यूरॉन त्रुटि के अनुरूप

; इसके अलावा, न्यूरॉन त्रुटि जानकारी

यह छिपी हुई परत के उन न्यूरॉन्स में फैलता है जो इससे जुड़े होते हैं

।

घटक समायोजन वजन को जोड़ता है

उत्पादन परत से छिपे हुए न्यूरॉन तक फैलने के समान

त्रुटि सूचना।

सीखने की गति।

सूचकांक I के साथ इनपुट पर न्यूरॉन। इनपुट न्यूरॉन्स के लिए, इनपुट और आउटपुट सिग्नल समान हैं -

।

छिपे हुए न्यूरॉन j का विस्थापन।

छिपा हुआ न्यूरॉन जे; छिपे हुए तत्व के इनपुट को दिया गया कुल मूल्य

इंगित किया गया है

:

संकेत उत्पादन

(करने के लिए आवेदन करने का परिणाम है

सक्रियण फ़ंक्शन) इंगित किया गया है

:


आउटपुट पर एक न्यूरॉन का विस्थापन।

सूचकांक k के तहत उत्पादन में न्यूरॉन; कुल मूल्य आउटपुट तत्व के इनपुट को आपूर्ति करता है

इंगित किया गया है

:

। संकेत उत्पादन

(करने के लिए आवेदन करने का परिणाम है

सक्रियण फ़ंक्शन) इंगित किया गया है

:
सक्रियण समारोह
त्रुटि वापस प्रसार एल्गोरिथ्म में सक्रियण समारोह में कई महत्वपूर्ण विशेषताएं होनी चाहिए: निरंतरता, भिन्नता और नीरस गैर-घटती। इसके अलावा, कम्प्यूटेशनल दक्षता के लिए, यह वांछनीय है कि इसकी व्युत्पत्ति आसानी से मिल जाए। अक्सर, सक्रियण फ़ंक्शन एक संतृप्ति फ़ंक्शन भी होता है। सबसे अधिक उपयोग किए जाने वाले सक्रियण कार्यों में से एक एक द्विआधारी सिग्मोइड फ़ंक्शन है जिसमें मानों की एक सीमा होती है (0, 1) और इसे निम्न के रूप में परिभाषित किया जाता है:


एक अन्य व्यापक सक्रियण फ़ंक्शन एक द्विध्रुवी सिग्मॉइड है जिसमें मानों की एक श्रृंखला होती है (-1, 1) और इसे इस प्रकार परिभाषित किया जाता है:


लर्निंग एल्गोरिदम
लर्निंग एल्गोरिथम इस प्रकार है:
चरण ०
वज़न का प्रारंभ (सभी बॉन्डों का वजन यादृच्छिक छोटे मूल्यों द्वारा आरंभीकृत किया जाता है)।
चरण 1
जब तक एल्गोरिथ्म की समाप्ति की स्थिति ठीक नहीं होती, तब तक 9 के माध्यम से चरण 2 का प्रदर्शन किया जाता है।
चरण 2
प्रत्येक जोड़ी {डेटा, टारगेट वैल्यू} के लिए, चरण 3 से 8 तक का प्रदर्शन किया जाता है।
इनपुट से आउटपुट तक डेटा प्रसार:
चरण 3
हर इनपुट न्यूरॉन

प्राप्त संकेत भेजता है

अगली परत में सभी न्यूरॉन्स (छिपे हुए)।
चरण 4
हर छुपा हुआ न्यूरॉन

भारित आने वाले संकेतों को दर्शाता है:

और सक्रियण फ़ंक्शन लागू करता है:

फिर यह अगली परत (आउटपुट) के सभी तत्वों को परिणाम भेजता है।
चरण 5
हर आउटपुट न्यूरॉन

भारित आने वाले संकेतों को दर्शाता है:

और सक्रियण फ़ंक्शन को लागू करता है, आउटपुट सिग्नल की गणना करता है:

त्रुटि प्रसार वापस:
चरण 6
हर आउटपुट न्यूरॉन

लक्ष्य मान प्राप्त करता है - वह आउटपुट मान जो दिए गए इनपुट सिग्नल के लिए सही है, और त्रुटि की गणना करता है:

उस राशि की गणना भी करता है जिसके द्वारा बांड का वजन बदलता है

:

। इसके अलावा, यह ऑफसेट समायोजन की मात्रा की गणना करता है:

और भेजता है

पिछली परत में न्यूरॉन्स।
चरण 7
हर छुपा हुआ न्यूरॉन

आने वाली त्रुटियों को सारांशित करता है (बाद की परत में न्यूरॉन्स से)

और त्रुटि के परिमाण की गणना करता है, सक्रियण फ़ंक्शन के व्युत्पन्न द्वारा परिणामी मूल्य को गुणा करता है:

उस राशि की गणना भी करता है जिसके द्वारा बांड का वजन बदलता है

:

। इसके अलावा, यह ऑफसेट समायोजन की मात्रा की गणना करता है:

चरण 8. वजन बदलें।
हर आउटपुट न्यूरॉन

विस्थापन तत्व और छिपे हुए न्यूरॉन्स के साथ अपने कनेक्शन का वजन बदलता है:

हर छुपा हुआ न्यूरॉन

विस्थापन तत्व और आउटपुट न्यूरॉन्स के साथ इसके कनेक्शन का वजन बदलता है:

चरण 9
एल्गोरिथ्म की समाप्ति की स्थिति की जाँच करना।
एल्गोरिथ्म के संचालन की समाप्ति के लिए शर्त दोनों सीखने की प्रक्रिया के दौरान पूर्व निर्धारित न्यूनतम पर नेटवर्क के उत्पादन में परिणाम की कुल द्विघात त्रुटि की उपलब्धि हो सकती है, और एल्गोरिदम की एक निश्चित संख्या के पुनरावृत्तियों का निष्पादन। एल्गोरिथ्म एक विधि पर आधारित है जिसे ग्रेडिएंट डीसेंट कहा जाता है। संकेत के आधार पर, फ़ंक्शन का ग्रेडिएंट (इस मामले में, फ़ंक्शन का मान एक त्रुटि है, और पैरामीटर नेटवर्क में लिंक के भार हैं) वह दिशा देता है जिसमें फ़ंक्शन के मान सबसे तेजी से बढ़ते (या घटते) हैं।
प्रारंभिक वजन और ऑफसेट का चयन
रैंडम आरंभीकरण। प्रारंभिक भार की पसंद प्रभावित करेगी कि क्या नेटवर्क वैश्विक (या केवल स्थानीय) न्यूनतम त्रुटि तक पहुंच सकता है, और यह प्रक्रिया कितनी जल्दी होगी। दो न्यूरॉन्स के बीच वजन में परिवर्तन अगली परत से न्यूरॉन के सक्रियण समारोह और पिछली परत के न्यूरॉन के सक्रियण समारोह के व्युत्पन्न के साथ जुड़ा हुआ है। इस संबंध में, ऐसे प्रारंभिक भारों को चुनने से बचना महत्वपूर्ण है जो सक्रियण फ़ंक्शन या इसके व्युत्पन्न को रीसेट करेंगे। इसके अलावा, प्रारंभिक वज़न बहुत बड़ा नहीं होना चाहिए (या प्रत्येक छिपे या आउटपुट न्यूरॉन के लिए इनपुट संकेत सबसे अधिक संभावना है कि यह बहुत ही छोटे सिग्मॉइड मान (संतृप्ति क्षेत्र) के क्षेत्र में आएगा)। दूसरी ओर, यदि प्रारंभिक भार बहुत छोटा है, तो छिपे या आउटपुट न्यूरॉन्स के लिए इनपुट सिग्नल शून्य के करीब होगा, जिससे सीखने की गति भी बहुत कम हो जाएगी। भार को प्रारंभिक करने के लिए मानक प्रक्रिया उन्हें अंतराल (-0.5; 0.5) में यादृच्छिक मान असाइन करना है। मूल्य या तो सकारात्मक या नकारात्मक हो सकते हैं, क्योंकि नेटवर्क को प्रशिक्षित करने के बाद प्राप्त अंतिम भार दोनों संकेतों का हो सकता है। आरंभिक नुग्येन - विधवा। नीचे प्रस्तुत मानक आरंभीकरण प्रक्रिया का सरल संशोधन तेजी से सीखने की सुविधा प्रदान करता है: छिपे हुए और आउटपुट न्यूरॉन्स, साथ ही आउटपुट परत के विस्थापन के बीच के कनेक्शन का वजन, प्रारंभिक प्रक्रिया के रूप में, मानक प्रक्रिया में अंतराल (-0.5; 0.5) से यादृच्छिक मूल्यों द्वारा किया जाता है।
हम निम्नलिखित संकेतन प्रस्तुत करते हैं:

इनपुट न्यूरॉन्स की संख्या

छिपे हुए न्यूरॉन्स की संख्या

स्केलिंग कारक:

प्रक्रिया में निम्नलिखित सरल चरण शामिल हैं:
हर छिपे हुए न्यूरॉन के लिए

:
वजन के अपने वेक्टर को इनिशियलाइज़ करें (इनपुट न्यूरॉन्स के साथ कनेक्शन):

गणना करना

वजन को पुन: व्यवस्थित करें:

ऑफसेट मान सेट करें:

व्यावहारिक हिस्सा
मैं एक न्यूरॉन की अवधारणा के कार्यान्वयन से शुरू करूंगा। बेस लेयर के रूप में इनपुट लेयर के न्यूरॉन्स और बेस क्लास के डेकोरेटर के रूप में छिपे हुए और आउटपुट को प्रस्तुत करने का निर्णय लिया गया। इसके अलावा, न्यूरॉन आउटगोइंग और इनकमिंग कनेक्शन के बारे में जानकारी संग्रहीत करता है, और प्रत्येक न्यूरॉन की रचना में इसकी सक्रियता फ़ंक्शन होती है।
न्यूरॉन इंटरफ़ेस template <typename T> class Neuron { public: Neuron( ) : mNetFunc( new Linear ), mSumOfCharges( 0.0 ) { }; Neuron( NetworkFunction * inNetFunc ) : mNetFunc( inNetFunc ), mSumOfCharges( 0.0 ){ }; Neuron( std::vector<NeuralLink<T > *>& inLinksToNeurons, NetworkFunction * inNetFunc ) : mNetFunc( inNetFunc ), mLinksToNeurons(inLinksToNeurons), mSumOfCharges(0.0){ }; Neuron( std::vector<Neuron *>& inNeuronsLinkTo, NetworkFunction * inNetFunc ); virtual ~Neuron( ); virtual std::vector<NeuralLink<T > *>& GetLinksToNeurons( ){ return mLinksToNeurons; }; virtual NeuralLink<T> * at( const int& inIndexOfNeuralLink ) { return mLinksToNeurons[ inIndexOfNeuralLink ]; }; virtual void SetLinkToNeuron( NeuralLink<T> * inNeuralLink ){ mLinksToNeurons.push_back( inNeuralLink ); }; virtual void Input( double inInputData ){ mSumOfCharges += inInputData; }; virtual double Fire( ); virtual int GetNumOfLinks( ) { return mLinksToNeurons.size( ); }; virtual double GetSumOfCharges( ); virtual void ResetSumOfCharges( ){ mSumOfCharges = 0.0; }; virtual double Process( ) { return mNetFunc->Process( mSumOfCharges ); }; virtual double Process( double inArg ){ return mNetFunc->Process( inArg ); }; virtual double Derivative( ){ return mNetFunc->Derivative( mSumOfCharges ); }; virtual void SetInputLink( NeuralLink<T> * inLink ){ mInputLinks.push_back( inLink ); }; virtual std::vector<NeuralLink<T > *>& GetInputLink( ){ return mInputLinks; }; virtual double PerformTrainingProcess( double inTarget ); virtual void PerformWeightsUpdating( ); virtual void ShowNeuronState( ); protected: NetworkFunction * mNetFunc; std::vector<NeuralLink<T > *> mInputLinks; std::vector<NeuralLink<T > *> mLinksToNeurons; double mSumOfCharges; }; template <typename T> class OutputLayerNeuronDecorator : public Neuron<T> { public: OutputLayerNeuronDecorator( Neuron<T> * inNeuron ){ mOutputCharge = 0; mNeuron = inNeuron; }; virtual ~OutputLayerNeuronDecorator( ); virtual std::vector<NeuralLink<T > *>& GetLinksToNeurons( ){ return mNeuron->GetLinksToNeurons( ) ;}; virtual NeuralLink<T> * at( const int& inIndexOfNeuralLink ){ return ( mNeuron->at( inIndexOfNeuralLink ) ) ;}; virtual void SetLinkToNeuron( NeuralLink<T> * inNeuralLink ){ mNeuron->SetLinkToNeuron( inNeuralLink ); }; virtual double GetSumOfCharges( ) { return mNeuron->GetSumOfCharges( ); }; virtual void ResetSumOfCharges( ){ mNeuron->ResetSumOfCharges( ); }; virtual void Input( double inInputData ){ mNeuron->Input( inInputData ); }; virtual double Fire( ); virtual int GetNumOfLinks( ) { return mNeuron->GetNumOfLinks( ); }; virtual double Process( ) { return mNeuron->Process( ); }; virtual double Process( double inArg ){ return mNeuron->Process( inArg ); }; virtual double Derivative( ) { return mNeuron->Derivative( ); }; virtual void SetInputLink( NeuralLink<T> * inLink ){ mNeuron->SetInputLink( inLink ); }; virtual std::vector<NeuralLink<T > *>& GetInputLink( ) { return mNeuron->GetInputLink( ); }; virtual double PerformTrainingProcess( double inTarget ); virtual void PerformWeightsUpdating( ); virtual void ShowNeuronState( ) { mNeuron->ShowNeuronState( ); }; protected: double mOutputCharge; Neuron<T> * mNeuron; }; template <typename T> class HiddenLayerNeuronDecorator : public Neuron<T> { public: HiddenLayerNeuronDecorator( Neuron<T> * inNeuron ) { mNeuron = inNeuron; }; virtual ~HiddenLayerNeuronDecorator( ); virtual std::vector<NeuralLink<T > *>& GetLinksToNeurons( ){ return mNeuron->GetLinksToNeurons( ); }; virtual void SetLinkToNeuron( NeuralLink<T> * inNeuralLink ){ mNeuron->SetLinkToNeuron( inNeuralLink ); }; virtual double GetSumOfCharges( ){ return mNeuron->GetSumOfCharges( ) ;}; virtual void ResetSumOfCharges( ){mNeuron->ResetSumOfCharges( ); }; virtual void Input( double inInputData ){ mNeuron->Input( inInputData ); }; virtual double Fire( ); virtual int GetNumOfLinks( ){ return mNeuron->GetNumOfLinks( ); }; virtual NeuralLink<T> * ( const int& inIndexOfNeuralLink ){ return ( mNeuron->at( inIndexOfNeuralLink) ); }; virtual double Process( ){ return mNeuron->Process( ); }; virtual double Process( double inArg ){ return mNeuron->Process( inArg ); }; virtual double Derivative( ){ return mNeuron->Derivative( ); }; virtual void SetInputLink( NeuralLink<T> * inLink ){ mNeuron->SetInputLink( inLink ); }; virtual std::vector<NeuralLink<T > *>& GetInputLink( ){ return mNeuron->GetInputLink( ); }; virtual double PerformTrainingProcess( double inTarget ); virtual void PerformWeightsUpdating( ); virtual void ShowNeuronState( ){ mNeuron->ShowNeuronState( ); }; protected: Neuron<T> * mNeuron; };
तंत्रिका लिंक इंटरफ़ेस नीचे प्रस्तुत किया गया है, प्रत्येक लिंक एक वजन और एक न्यूरॉन के लिए एक पॉइंटर को संग्रहीत करता है:
तंत्रिका संचार इंटरफ़ेस template <typename T> class Neuron; template <typename T> class NeuralLink { public: NeuralLink( ) : mWeightToNeuron( 0.0 ), mNeuronLinkedTo( 0 ), mWeightCorrectionTerm( 0 ), mErrorInformationTerm( 0 ), mLastTranslatedSignal( 0 ){ }; NeuralLink( Neuron<T> * inNeuronLinkedTo, double inWeightToNeuron = 0.0 ) : mWeightToNeuron( inWeightToNeuron ), mNeuronLinkedTo( inNeuronLinkedTo ), mWeightCorrectionTerm( 0 ), mErrorInformationTerm( 0 ), mLastTranslatedSignal( 0 ){ }; void SetWeight( const double& inWeight ){ mWeightToNeuron = inWeight; }; const double& GetWeight( ){ return mWeightToNeuron; }; void SetNeuronLinkedTo( Neuron<T> * inNeuronLinkedTo ){ mNeuronLinkedTo = inNeuronLinkedTo; }; Neuron<T> * GetNeuronLinkedTo( ){ return mNeuronLinkedTo; }; void SetWeightCorrectionTerm( double inWeightCorrectionTerm ){ mWeightCorrectionTerm = inWeightCorrectionTerm; }; double GetWeightCorrectionTerm( ){ return mWeightCorrectionTerm; }; void UpdateWeight( ){ mWeightToNeuron = mWeightToNeuron + mWeightCorrectionTerm; }; double GetErrorInFormationTerm( ){ return mErrorInformationTerm; }; void SetErrorInFormationTerm( double inEITerm ){ mErrorInformationTerm = inEITerm; }; void SetLastTranslatedSignal( double inLastTranslatedSignal ){ mLastTranslatedSignal = inLastTranslatedSignal; }; double GetLastTranslatedSignal( ){ return mLastTranslatedSignal; }; protected: double mWeightToNeuron; Neuron<T> * mNeuronLinkedTo; double mWeightCorrectionTerm; double mErrorInformationTerm; double mLastTranslatedSignal; };
प्रत्येक सक्रियण कार्य एक अमूर्त वर्ग से होता है, जो कार्य को स्वयं और व्युत्पन्न को साकार करता है:
सक्रियण फ़ंक्शन इंटरफ़ेस class NetworkFunction { public: NetworkFunction(){}; virtual ~NetworkFunction(){}; virtual double Process( double inParam ) = 0; virtual double Derivative( double inParam ) = 0; }; class Linear : public NetworkFunction { public: Linear(){}; virtual ~Linear(){}; virtual double Process( double inParam ){ return inParam; }; virtual double Derivative( double inParam ){ return 0; }; }; class Sigmoid : public NetworkFunction { public: Sigmoid(){}; virtual ~Sigmoid(){}; virtual double Process( double inParam ){ return ( 1 / ( 1 + exp( -inParam ) ) ); }; virtual double Derivative( double inParam ){ return ( this->Process(inParam)*(1 - this->Process(inParam)) );}; }; class BipolarSigmoid : public NetworkFunction { public: BipolarSigmoid(){}; virtual ~BipolarSigmoid(){}; virtual double Process( double inParam ){ return ( 2 / ( 1 + exp( -inParam ) ) - 1 ) ;}; virtual double Derivative( double inParam ){ return ( 0.5 * ( 1 + this->Process( inParam ) ) * ( 1 - this->Process( inParam ) ) ); }; };
न्यूरॉन्स के उत्पादन के लिए एक तंत्रिका कारखाना जिम्मेदार है:
तंत्रिका कारखाने इंटरफ़ेस template <typename T> class NeuronFactory { public: NeuronFactory(){}; virtual ~NeuronFactory(){}; virtual Neuron<T> * CreateInputNeuron( std::vector<Neuron<T > *>& inNeuronsLinkTo, NetworkFunction * inNetFunc ) = 0; virtual Neuron<T> * CreateOutputNeuron( NetworkFunction * inNetFunc ) = 0; virtual Neuron<T> * CreateHiddenNeuron( std::vector<Neuron<T > *>& inNeuronsLinkTo, NetworkFunction * inNetFunc ) = 0; }; template <typename T> class PerceptronNeuronFactory : public NeuronFactory<T> { public: PerceptronNeuronFactory(){}; virtual ~PerceptronNeuronFactory(){}; virtual Neuron<T> * CreateInputNeuron( std::vector<Neuron<T > *>& inNeuronsLinkTo, NetworkFunction * inNetFunc ){ return new Neuron<T>( inNeuronsLinkTo, inNetFunc ); }; virtual Neuron<T> * CreateOutputNeuron( NetworkFunction * inNetFunc ){ return new OutputLayerNeuronDecorator<T>( new Neuron<T>( inNetFunc ) ); }; virtual Neuron<T> * CreateHiddenNeuron( std::vector<Neuron<T > *>& inNeuronsLinkTo, NetworkFunction * inNetFunc ){ return new HiddenLayerNeuronDecorator<T>( new Neuron<T>( inNeuronsLinkTo, inNetFunc ) ); }; };
तंत्रिका नेटवर्क द्वारा आयोजित न्यूरॉन्स को इंगित करता है
परतें (सामान्य रूप से, न्यूरॉन्स की ओर संकेत वेक्टर्स में जमा होती हैं जो हैं
परत वस्तुओं के साथ प्रतिस्थापित करने की आवश्यकता है), सार शामिल हैं
एक न्यूरॉन फैक्ट्री, साथ ही एक नेटवर्क लर्निंग एल्गोरिदम।
तंत्रिका नेटवर्क इंटरफ़ेस template <typename T> class TrainAlgorithm; template <typename T> class NeuralNetwork { public: NeuralNetwork( const int& inInputs, const int& inOutputs, const int& inNumOfHiddenLayers = 0, const int& inNumOfNeuronsInHiddenLayers = 0, const char * inTypeOfNeuralNetwork = "MultiLayerPerceptron" ); ~NeuralNetwork( ); bool Train( const std::vector<std::vector<T > >& inData, const std::vector<std::vector<T > >& inTarget ); std::vector<int> GetNetResponse( const std::vector<T>& inData ); void SetAlgorithm( TrainAlgorithm<T> * inTrainingAlgorithm ) { mTrainingAlgoritm = inTrainingAlgorithm; }; void SetNeuronFactory( NeuronFactory<T> * inNeuronFactory ) { mNeuronFactory = inNeuronFactory; }; void ShowNetworkState( ); const double& GetMinMSE( ){ return mMinMSE; }; void SetMinMSE( const double& inMinMse ){ mMinMSE = inMinMse; }; friend class Hebb<T>; friend class Backpropagation<T>; protected: std::vector<Neuron<T > *>& GetLayer( const int& inInd ){ return mLayers[inInd]; }; unsigned int size( ){ return mLayers.size( ); }; std::vector<Neuron<T > *>& GetOutputLayer( ){ return mLayers[mLayers.size( )-1]; }; std::vector<Neuron<T > *>& GetInputLayer( ){ return mLayers[0]; }; std::vector<Neuron<T > *>& GetBiasLayer( ) { return mBiasLayer; }; void UpdateWeights( ); void ResetCharges( ); void AddMSE( double inPortion ){ mMeanSquaredError += inPortion; }; double GetMSE( ){ return mMeanSquaredError; }; void ResetMSE( ) { mMeanSquaredError = 0; }; NeuronFactory<T> * mNeuronFactory; TrainAlgorithm<T> * mTrainingAlgoritm; std::vector<std::vector<Neuron<T > *> > mLayers; std::vector<Neuron<T > *> mBiasLayer; unsigned int mInputs, mOutputs, mHidden; double mMeanSquaredError; double mMinMSE; };
और अंत में, नेटवर्क को प्रशिक्षित करने के लिए जिम्मेदार वर्ग का इंटरफ़ेस:
लर्निंग एल्गोरिथम इंटरफ़ेस template <typename T> class NeuralNetwork; template <typename T> class TrainAlgorithm { public: virtual ~TrainAlgorithm(){}; virtual double Train(const std::vector<T>& inData, const std::vector<T>& inTarget) = 0; virtual void WeightsInitialization() = 0; protected: }; template <typename T> class Hebb : public TrainAlgorithm<T> { public: Hebb(NeuralNetwork<T> * inNeuralNetwork) : mNeuralNetwork(inNeuralNetwork){}; virtual ~Hebb(){}; virtual double Train(const std::vector<T>& inData, const std::vector<T>& inTarget); virtual void WeightsInitialization(); protected: NeuralNetwork<T> * mNeuralNetwork; }; template <typename T> class Backpropagation : public TrainAlgorithm<T> { public: Backpropagation(NeuralNetwork<T> * inNeuralNetwork); virtual ~Backpropagation(){}; virtual double Train(const std::vector<T>& inData, const std::vector<T>& inTarget); virtual void WeightsInitialization(); protected: void NguyenWidrowWeightsInitialization(); void CommonInitialization(); NeuralNetwork<T> * mNeuralNetwork; };
सभी कोड github पर उपलब्ध है: सोवियत / न्यूरल नेटवर्क्स
अंत में, मैं यह नोट करना चाहूंगा कि तंत्रिका नेटवर्क के विषय को फिलहाल पूरी तरह से विकसित नहीं किया गया है, बार-बार हम हबर के पन्नों पर देखते हैं कि तंत्रिका नेटवर्क के क्षेत्र में वैज्ञानिकों की नई उपलब्धियों का उल्लेख है, नए अद्भुत विकास। मेरे हिस्से के लिए
यह लेख एक दिलचस्प तकनीक में महारत हासिल करने का पहला कदम था, और मुझे आशा है कि किसी के लिए यह उपयोगी साबित होगा।
प्रयुक्त साहित्य:
तंत्रिका नेटवर्क लर्निंग एल्गोरिथ्म एक अद्भुत किताब से लिया गया था:
लॉरेन वी। Fausett "तंत्रिका नेटवर्क के बुनियादी ढांचे: वास्तुकला, एल्गोरिदम और अनुप्रयोग"।