रोसेनब्लट पर्सेप्ट्रॉन द्वारा एक उत्तेजक लेख के बाद
- इतिहास द्वारा क्या भुलाया और आविष्कार किया गया है? और एक जो रोसेनब्लैट पर्सेप्ट्रॉन में समस्याओं की अनुपस्थिति को पूरी तरह से साबित करता है, और यहां तक कि इसके विपरीत कुछ पहलुओं और संभावनाओं को दर्शाता है।
रोसेनब्लैट पर्सेप्ट्रॉन में पहली "यादृच्छिक" परत की भूमिका क्या है , मुझे लगता है कि कुछ दलालों को यह पता लगाने की इच्छा थी कि यह किस तरह का जानवर है - रोसेनब्लैट पेसेप्ट्रॉन। वास्तव में, मूल के अलावा, उसके बारे में विश्वसनीय जानकारी प्राप्त करना संभव नहीं है। लेकिन यहां तक कि यह वर्णन करना काफी कठिन है कि इस परसेप्ट्रॉन को कैसे प्रोग्राम किया जाए। मैं पूरा कोड अपलोड नहीं करूंगा। लेकिन चलो एक साथ कई मूल बातों के माध्यम से जाने की कोशिश करते हैं।
चलिए शुरू करते हैं ... ओह हां, मैंने आपको चेतावनी दी है, मैं शास्त्रीय रूप से नहीं बताऊंगा, लेकिन कुछ हद तक आधुनिकीकरण ...
सी # कोड, लेकिन मुझे लगता है कि इसे छद्म कोड की तरह व्यवहार करना बेहतर है। लेकिन अगर किसी को कुछ समझ नहीं आया, तो पूछें - मैं समझाऊंगा
और हम सेंसर के साथ शुरू करेंगे।
सार्वजनिक वर्ग के सेंसर
{
सार्वजनिक कार्यक्रम EventHandler ChangeState ;
निजी sbyte राज्य = 0 ;
सार्वजनिक sbyte राज्य
{
{ राज्य वापसी ; }
सेट
{
राज्य = मूल्य ;
अगर ( राज्य == 1 && ChangeState ! = null )
{
ChangeState ( यह , नया EventArgs ( ) ) ;
}
}
}
}
यहां सब कुछ सरल है। सेंसर में 0 या 1. की स्थिति होती है। जैसे ही सेंसर एक इकाई प्राप्त करता है, यह एक घटना भेजता है। अगला हमारे पास एक सिंक है।
सार्वजनिक प्रतिनिधि शून्य BackCommunication ( sbyte प्रकार ) ;
वर्ग cSinaps
{
निजी sbyte प्रकार ;
निजी बैककम्यूनिकेशन hBackCommunication ;
सार्वजनिक cSinaps ( sbyte tType, BackCommunication tBackCommunication )
{
प्रकार = tType ;
hBackCommunication = tBackCommunication ;
}
सार्वजनिक शून्य ChangeSensorState ( ऑब्जेक्ट सॉर्स, EventArgs e )
{
hBackCommunication ( प्रकार ) ;
}
}
इसका एक प्रकार है - सेंसर की गतिविधि को उत्तेजित या बाधित करेगा। साथ ही सेंसर चेंज (ChangeSensorState) पर प्रतिक्रिया। अब वास्तविक A- तत्व मध्य परत में है।
सार्वजनिक वर्ग cAssociation
{
// ए-एलीमेंट सक्रियण स्तर
सार्वजनिक int सक्रियणसूची = 0 ;
// इस ए-तत्व से जुड़े सिनाप्स
निजी cSinaps [ ] oSinaps ;
सार्वजनिक cAssociation ( cSensor [ ] SensField, int SCount, Random RND )
{
int SinapsCount = 10 ;
oSinaps = new cSinaps [ SinapsCount ] ;
int tSinapsNumber = 0 ;
int tmpSensorNumber = 0 ;
sbyte tmpSensorType = 0 ;
के लिए ( int j = 1 ; j < SinapsCount + 1 ; j ++ )
{
tmpSensorNumber = आरएनडी। अगला ( SCount ) ;
अगर ( RND। अगला ( 2 ) == 0 ) tmpSensorType = 1 ; और tmpSensorType = - 1 ;
oSinaps [ tSinapsNumber ] = नया cSinaps ( tmpSensorType, AssumeSinapsSignal ) ;
SensField [ tmpSensorNumber ] । ChangeState + =
नई EventHandler ( oSinaps [ tSinapsNumber ] । ChangeSensorState ) ;
tSinapsNumber ++ ;
}
}
शून्य मानदंडसमूह ( sbyte प्रकार )
{
एक्टिवेशनलेवल + = प्रकार ;
}
}
ए-एलीमेंट बनाते समय, उससे जुड़े सिनैप्स बनाना आवश्यक है, उन्हें 10. होने दें। हम बेतरतीब ढंग से यह तय करते हैं कि किस सेंसर को इसे कनेक्ट करना है और किस प्रकार का सिनैप्स (रोमांचक या निरोधात्मक) होगा। और सबसे महत्वपूर्ण बात, हम इस समय AssumeSinapsSignal को कॉल करने के लिए सेंसर मूल्य को बदलने की सदस्यता लेते हैं। और वहां हम सक्रियण के स्तर को बढ़ाते हैं या संलग्न हुए प्रकार के आधार पर घटते हैं।
सामान्य तौर पर, सब कुछ, जो कुछ भी इतना जटिल था, उसमें बताया गया था।
रोसेनब्लैट परसेप्ट्रॉन में पहली "यादृच्छिक" परत की भूमिका क्या है - हमने इसे लागू किया है। हमारे पास ए-तत्वों के सेट में किसी भी मनमानी समस्या का रैखिक प्रतिनिधित्व पहले से ही गारंटी है।
अब दूसरी लेयर में
त्रुटि सुधार के द्वारा सीखने के लिए आगे बढ़ते हैं। सबसे पहले, सामान्य एल्गोरिथ्म, मुझे लगता है, बिना शब्दों के स्पष्ट है।
सार्वजनिक वर्ग cNeironNet
{
सार्वजनिक सेंसर [ ] SensorsField ; / * सेंसर क्षेत्र * /
सार्वजनिक cAssociation [ ] संघोंFiled ; / * सहयोगी क्षेत्र * /
int ACount ;
int SCount ;
सार्वजनिक एरेलालिस्ट AHConnections ;
रैंडम RND = नया रैंडम ( ) ;
सार्वजनिक cNeironNet ( int argSCount, int argACount )
{
ACount = argACount ;
SCount = argSCount ;
SensorsField = new cSensor [ SCount ] ;
for ( int i = 0 ; मैं < SCount ; i ++ )
{
SensorsField [ i ] = new cSensor ( ) ;
}
असोसिएशनफिल्ड = नया cAssociation [ ACount ] ;
for ( int i = 0 ; मैं < ACount ; i ++ )
{
संबद्धता [ i ] = नया cAssociation ( SensorsField, SCount, RND ) ;
}
}
/ * प्रशिक्षण सेट से प्रसंस्करण के लिए एक नया उदाहरण जोड़ें * /
सार्वजनिक ArrayList JoinStimul ( int [ ] tPerception, int [ ] tReaction )
{
for ( int i = 1 ; मैं < ACount + 1 ; i ++ )
{
एसोसिएशंसफिल्ड [ i ] । एक्टिवेशनलेवल = 0 ;
}
for ( int i = 1 ; मैं < SCount + 1 ; i ++ )
{
SensorsField [ i ] । राज्य = 0 ;
}
// चलो सेंसर पर प्राप्त उदाहरण को फेंक दें
for ( int i = 0 ; मैं < SCount ; i ++ )
{
SensorsField [ i ] । राज्य = tPerception [ i ] ;
}
// याद रखें कि इस उदाहरण में कौन से ए-तत्व सक्रिय थे
AHConnections = नया ArrayList ( ) ;
के लिए ( i = 0 ; मैं < ACount ; i ++ )
{
अगर ( एसोसिएट्सफिल्ड [ i ] । एक्टिवेशनलेवल > 0 )
{
AHConnections। जोड़ें ( i ) ;
}
}
// याद रखें कि इस उदाहरण पर क्या प्रतिक्रिया होनी चाहिए
SaveReaction ( tReaction ) ;
वापसी AHConnections ;
}
/ * जब सभी उदाहरण जोड़े जाते हैं, तो उन्हें सीखने के लिए परसेप्ट्रॉन को बुलाया जाता है * /
निजी शून्य भंडारण ( )
{
// बहुत सारे पुनरावृत्तियों करें
for ( int n = 1 ; n < 100000 + 1 ; n ++ )
{
// प्रत्येक पुनरावृत्ति के लिए, प्रशिक्षण सेट से सभी उदाहरणों को स्क्रॉल करें
for ( int i = 1 ; मैं < StimulCount + 1 ; i ++ )
{
// आर-तत्वों को सक्रिय करें, अर्थात। उम्मीद है
रक्तिवीकरण ( i ) ;
// हमें पता चलता है कि क्या अवधारणकर्ता गलत है या नहीं, अगर हमसे गलती हुई है, तो हम इसे प्रशिक्षण के लिए भेजते हैं
bool e = GetError ( i ) ;
अगर ( ई )
{
LearnedStimul ( i ) ;
त्रुटि ++ ; // त्रुटियों की संख्या, यदि पुनरावृत्ति = 0 के अंत में, तो हम प्रशिक्षण से बाहर हो जाते हैं।
}
}
}
}
}
आर तत्वों को सक्रिय करना भी सरल है। हम सक्रिय ए-तत्वों से वज़न को संक्षिप्त करते हैं, और दहलीज (= 0) के माध्यम से आगे बढ़ते हैं।
निजी शून्य RAktivization ( int ReactionNumber )
{
int [ ] सुम्मा = नया int [ RCount + 1 ] ;
for ( int j = 1 ; j < RCount + 1 ; j ++ )
{
के लिए ( i = 1 ; मैं < AHConnections [ ReactionNumber ] ; गिनती + 1 ; i ++ )
{
सुम्मा [ j ] + = वजन [ AHConnections [ ReactionNumber ] । मान [ i ] । मूल्य [ जे ] ;
}
}
for ( int i = 1 ; मैं < RCount + 1 ; i ++ )
{
if ( सुम्मा [ i ] > 0 ) प्रतिक्रियाएँ [ i ] = 1 ;
if ( सुम्मा [ i ] <= 0 ) प्रतिक्रियाएँ [ i ] = - 1 ;
}
}
जांचें कि क्या कोई त्रुटि है या नीचे नहीं है।
निजी int GetError ( int ReactionNumber )
{
int IsError = 0 ;
for ( int i = 1 ; मैं < RCount + 1 ; i ++ )
{
if ( प्रतिक्रियाएँ [ i ] == आवश्यक शर्तें [ ReaNNumber ] । मूल्य [ i ] )
{
रिएक्शनError [ i ] = 0 ;
}
अन्यथा
{
ईसर = 1 ;
ReactionError [ i ] = आवश्यक निर्देश [ ReactionNumber ] । मूल्य [ i ] ;
}
}
वापसी IsError ;
}
यहां हम उस के साथ वर्तमान प्रतिक्रिया की जांच करते हैं, और जो ReactionError प्रतिक्रिया है उसके बारे में जानने के लिए एक सरणी तैयार करते हैं। अब पिछले एक प्रशिक्षण पर ही रहने दें।
निजी शून्य LearnedStimul ( int ReactionNumber )
{
for ( int j = 1 ; j < RCount + 1 ; j ++ )
{
for ( int i = 1 ; मैं < AHConnections [ ReactionNumber ] ; गिनती + 1 ; i ++ )
{
वजन [ AHConnections [ ReactionNumber ] । मान [ i ] । मान [ j ] + = ReactionError [ j ] ;
}
}
}
और यू।
केवल एक चीज जो वे मुझसे पूछते हैं, "जाहिर है, यह त्रुटि सुधार लर्निंग एल्गोरिदम भी त्रुटि वापस प्रचार एल्गोरिथ्म की तरह अटक जाता है यदि वजन शून्य है?" जैसा कि आप देख सकते हैं, यहां प्रशिक्षण शून्य वजन के साथ शुरू होता है। कोई गणितीय सूत्र नहीं हैं - प्राथमिक वेतन वृद्धि या गिरावट। यदि वजन 0 था, तो जब त्रुटि को ठीक किया जाता है, तो यह या तो +1 या -1 हो जाएगा, शून्य से गुजरने के बाद वजन फिर से संकेत बदल सकता है, लेकिन यह शारीरिक रूप से शून्य में नहीं फंसता है।
युपीडी।नीचे
रिट्रान ने एक स्पष्ट ओओपी मॉडल के अनुसार घटनाओं में मेरे कोड के बदले में ए-तत्वों को सक्रिय करने के लिए कार्यात्मक प्रोग्रामिंग से मैट्रिसेस और
लिनक का उपयोग करने का सुझाव दिया।
सार्वजनिक वर्ग Perceptron1
{
सार्वजनिक int [ ] [ ] SAMatrix { मिलता है ; निजी सेट ; }
सार्वजनिक Perceptron1 ( इंट सेंसर्साउंट, इंट एसोसिएटिवलीकाउंट्स )
{
var random = new random ( ) ;
समेट्रिक्स = नया इंट [ एसोसिएटिवल्सकाउंट ] [ ] ;
के लिए ( var i = 0 ; मैं < एसोसिएटिवकैल्साउंट ; i ++ )
{
SAMatrix [ i ] = नया int [ SensCount ] ;
के लिए ( var j = 0 ; j < 10 ; j ++ )
{
var sindex = यादृच्छिक। अगला ( सेंसरकाउंट ) ;
अगर ( यादृच्छिक। अगला ( 2 ) == 1 )
अगर ( यादृच्छिक। अगला ( 2 ) == 1 )
SAMatrix [ i ] [ sindex ] + = 1 ;
अन्यथा
SAMatrix [ i ] [ sindex ] - = 1 ;
}
}
}
सार्वजनिक int सक्रिय करें ( int i, int [ ] जानकारी )
{
वापसी ( समेट्रिक्स [ i ] । जिप ( इनपुट्स, ( डब्ल्यू, इनपुट ) => डब्ल्यू * इनपुट ) । सम ( ) > 0 ? 1 : 0 ) ;
}
}
हाँ, बेशक कोड बहुत छोटा है। लेकिन यह कम स्पष्ट है, यदि सक्रियण प्रक्रियाएं बदलती हैं तो परिवर्तन करना अधिक कठिन है। लेकिन सबसे महत्वपूर्ण बात,
यह 100 से अधिक बार धीमी गति से काम करता है । यहां आपके पास गणितीय और कार्यात्मक प्रोग्रामिंग के आकर्षण हैं :)
हम इसे इस तरह से परखते हैं (हालांकि ऊपर मेरे कोड में कई बग हैं, लेकिन उन्हें आसानी से तय किया जा सकता है अगर कोई ऐसा करेगा, + उनमें से अधिकांश को ठीक कर दिया जाएगा और ऊपर अपडेट कर दिया जाएगा):
रैंडम यादृच्छिक = नया रैंडम ( ) ;
int [ ] इनपुट = नया int [ १००० ] ;
int [ ] AActiv = नया int [ 900 ] ;
TimeSpan BeginTime = दिनांक समय। अब । TimeOfDay ;
Perceptron1 P1 = नया Perceptron1 ( 1000 , 900 ) ;
for ( int i = 0 ; मैं < 100 ; i ++ )
{
( int j = 0 ; j < 1000 ; j ++ )
{
इनपुट [ जे ] = यादृच्छिक। अगला ( 2 ) ;
}
के लिए ( int j = 0 ; j < 900 ; j ++ )
{
एएक्टिव [ जे ] = पी १। सक्रिय करें ( जे, इनपुट ) ;
}
}
TimeSpan locTime = दिनांक समय। अब । टाइमऑफडे - शुरुआती समय ;
// TimeSpan BeginTime = DateTime.Now.TimeOfDay;
// Perceptron2 P2 = नया Perceptron2 (1000, 900);
// के लिए (int i = 0; मैं <10000; i ++)
// {
// के लिए (int j = 0; j <1000; j ++)
// {
// इनपुट [j] = random.Next (2);
//}
// P2.JoinStimul (इनपुट);
//}
// TimeSpan locTime = DateTime.Now.TimeOfDay - BeginTime;
कंसोल। लिक्लाइन ( locTime। ToString ( ) ) ;
कंसोल। ReadLine ( ) ;