التوازن في صنع القرار. شوكة "تجربة عشوائية"

صورة

لكتابة الحياة الحقيقية ، لا تحتاج إلى أي شيء آخر غير هزيمة نفسك تمامًا وكاملًا. أستمر في إنشائه وبعد ذلك سأكتب مقالًا ضخمًا حول هذا الموضوع ، ولكن ، ما هو هذا الشيء في حد ذاته ومدى صعوبة القياس 7 مرات ، وقطع واحد ، ثم قياسه 77 مرة أخرى وفي النهاية عدم قطعه. قياس ، قياس مرة أخرى! - هذا هو شعار شخص يريد إنشاء شيء غير عادي حقًا. الترميز أسهل بكثير من التفكير. ولكن التفكير أمر مؤلم وغير عادي بشكل عام.

ولكن اليوم أريد أن أتطرق إلى "مشكلة" واحدة ظهرت على السطح هنا. تخيل الحركة الفوضوية للجسيمات أو العناصر الكيميائية - تتحرك في حجم محدود مشروط ، ولا تتصادم إلا مع بعضها البعض ، أو تصد - الفوضى في أنقى أشكالها. إذا تم إطلاق مثل هذا النظام ، فعندئذٍ حتى في هذا الجمرة التي تبدو عديمة الفائدة ، ستتم ملاحظة الحركات المنظمة من وقت لآخر: يمكن أن تحدث تصادمات عشوائية في لحظة معينة بطريقة تتحول اتجاه التأثيرات (الاندفاع) بشكل أو بآخر في اتجاه واحد ، ثم تصادم سوف تتحرك الجسيمات في اتجاه واحد ، لتشكيل موجة. في المستقبل ، ستبدأ هذه الموجة من تصادمات الأطراف الثالثة في الاضمحلال وسنرى مرة أخرى صورة فوضوية.

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

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

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

ولهذا أنا أحاول وصف مبادئ الكود الحر. أقصى كود مجاني ممكن. خالية من فهمنا لكيفية ترتيب الحياة - لأن مثل هذا الفهم غالبًا ما يكون خاطئًا أو غير مكتمل جدًا لدرجة أنه لا معنى له. نحن المخلوقات الصغيرة نحاول جاهدين أن ندرس ونصف كل شيء حولنا حتى أننا لا نستطيع القيام بذلك. ولكن لا أحد نهى عن المحاولة.

عندما تكتب شفرة فوضوية ، فأنت لا محالة تصادف شوكة. تجربة عشوائية. أولئك. إما أن تتحرك بشكل عشوائي أكثر ، أو تمكن من تكوين الخبرة. أولئك. ليس فقط تمكين الجسيمات من الاصطدام ، ولكن أيضًا التفاعل. نحن نبحث عن تناظرية للحياة البيولوجية ، وهو أمر لا يمكن تصوره بدون نقل وتجديد الخبرة. RNA / DNA هي تجربة مسجلة تنتقل.

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

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

لنفترض أننا أنشأنا بشكل عشوائي سطرًا من التعليمات البرمجية القابلة للتنفيذ استجابةً لمجموعة رقمية لإدخال عشوائي. يمكن افتراض أن توليد الاستجابة ، أو رد الفعل ، هو خبرة. إذا كان هناك شيء يتفاعل بشكل ثابت مع نفس الإشارات الواردة ، فيمكننا القول أنه يستخدم الخبرة. لذلك ، أود أن أتذكر السلسلة التي تم إنشاؤها. لكن هذا لا يمكن القيام به مباشرة! لا يمكنك فقط أخذ هذا الخط ودفعه في مكان ما إلى متغير الصفيف لمثيل الفصل والبدء في إنشاء نوع من مكتبة التفاعل بهذه الطريقة ، وكتابة شيء مثل IF [input.set in memory_name] ثم [ذاكرة .-> رد فعل]. إنه مستحيل! لأنه ليس حقيقة أن هذه هي طريقة عمل "أنظمة الذاكرة البيولوجية". وليس حقيقة أن بنائها كان في الأصل كما نراه الآن.

في الوقت نفسه ، لا يمكنك فقط إنشاء سلسلة عشوائية 256 بايت على الأقل ومحاولة تنفيذها ، لأنه على أجهزة الكمبيوتر الحديثة سيستغرق الأمر وقتًا طويلاً ولا يناسبنا. من الممكن أن تكون هذه الطريقة مثالية ، ولكن للأسف ، من المستحيل التحقق من ذلك باستخدام التقنيات الحالية غير المطورة.

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

لفهم المشكلة ، تخيل أن لدينا إجراءان محتملان في الشفرة. لا يمكنك أن تشير مباشرة إلى أي واحد تختار ، لأن هذا سيكون قرارًا. وإذا قمت بتوزيع كل شيء بشكل عشوائي ، فأنت بحاجة إلى استخدام الاحتمالات. فقط ماذا؟ 50/50؟ 30/70؟ 80/20؟ لنفترض أن الأشياء الأخرى متساوية ، 50/50 هي في الواقع العلاقة غير المحدودة. ثم سيبدو الرمز شيئًا مثل هذا:

if random.random() >= 0.5:
      1
else:
     2


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

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

في حالتنا ، سيسمح لنا مبدأ الأولوية بتغيير ليس سلاسل التنفيذ على النواة ، ولكن أجزاء من الكود حيث سيتم نقل التحكم. وإذا جعلنا جزءًا من الشفرة على أنه "عشوائي" ، والثاني كـ "متمرس" ، فسيكون التغيير البديل هو الحل الذي نبحث عنه.

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

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

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

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

import random

deter_numb = 69
p_deter = 0.01
p_random = 0.99
iteration = 1

while True:
        print('iter = ',iteration)
        print('p_rand =  ', p_random)         
        print('p_deter = ', p_deter)
        input()
        if p_random > random.random():
            p_random-=0.01                     #  
            p_deter+=0.01
            print(random.random())    #  
        if p_deter > random.random():       
            p_deter-=0.01                      #  
            p_random+=0.01
            print(deter_numb)            #  
        iteration+=1


أحثك على تجربة تشغيل هذا البرنامج النصي بنفسك وإلقاء نظرة على كيفية عمله. هذا رمز موازنة ذاتية. كما يقف الإجراء 1
print(random.random())
- بمعنى آخر. مجرد إخراج رقم عشوائي ، والإجراءات 2 -
print(deter_numb)
- إخراج رقم محدد. في الرمز ، ستكون هناك إجراءات في مكانها ، لقد قمت بعمل المطبوعات هنا فقط لتوضيح المبدأ.

عندما يمر عنصر التحكم إلى الشرط الأول (الجزء العشوائي من الشفرة) ، تقلل الشفرة نفسها من احتمالية التكرار (p_random- = 0.01 - تنقص نفسها) وفي نفس الوقت تزيد من احتمال تنفيذ جزء من الشفرة حيث يتم تطبيق التجربة (p_deter + = 0.01 - زيادة احتمالية الآخر). يحدث الشيء نفسه عند نقل السيطرة إلى الشرط الثاني. وبالتالي ، عند تنفيذ هذين الجزأين من الكود ، فإنهما "يبطئان" في نفس الوقت ، وفي الوقت نفسه "يسرعان" الجزء "المنافس" الآخر من الكود.

يرجى ملاحظة أن الاحتمال الأولي لنقل عنصر التحكم إلى الجزء العشوائي من الرمز هو 99٪ ، والجزء التجريبي - 1٪. هذا يدل على أن النظام متوازن حتى مع هذه الاحتمالات المختلفة جذريا. عند تنفيذ الكود ، سيتبين كيف ستصل هذه النسبة إلى 50/50 في مائة تكرار فقط ، لتشكيل توزيع عادي مع ذروة صريحة 0.5 وحي عامل حوالي 6٪ (في 3-5 مائة تكرارات تالية).

عند تنفيذ الشفرة ، من الواضح أن الاحتمالات تأتي في حالة توازن وتستقر حول 0.5 ، موازنة بعد هذه النقطة تمامًا مثل موازنة البندول في محيط النقطة السفلية.

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

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

All Articles