Équilibre dans la prise de décision. Fork "expérience aléatoire"

image

Pour écrire la vraie vie, vous n'avez besoin de rien d'autre que de vous vaincre complètement et complètement. Je continue de le créer et plus tard j'écrirai un énorme article sur ce sujet, mais, mon, quelle est cette chose en soi et à quel point il est difficile de mesurer 7 fois, d'en couper un, puis de le mesurer encore 77 fois et finalement de ne pas le couper. Mesurez, mesurez encore! - C'est la devise de quelqu'un qui veut créer quelque chose de vraiment inhabituel. Le codage est beaucoup plus facile que de penser. Mais penser est douloureux et inhabituel en général.

Mais aujourd'hui, je veux m'attarder sur un "problème" qui a fait surface ici campagne. Imaginez le mouvement chaotique des particules ou des éléments chimiques - ils se déplacent dans un certain volume conditionnellement fini, n'entrent en collision que les uns avec les autres, ou repoussent le chaos dans sa forme la plus pure. Si un tel système est lancé, même dans cette fourmilière apparemment inutile, des mouvements structurés seront observés de temps en temps: des collisions aléatoires à un certain moment peuvent se produire de telle sorte que la direction des impacts (impulsion) se produise plus ou moins dans une direction, puis se heurte les particules se déplaceront dans une direction, formant une onde. À l'avenir, cette vague de collisions avec des tiers commencera à décliner et nous verrons à nouveau une image chaotique.

Ceux. au hasard dans son essence forme involontairement une structure, mais la structure n'est qu'une forme temporaire de ce hasard. Circulant de cette manière, le chaos prend diverses formes, que nous percevons comme quelque chose de raisonnable, c'est-à-dire commandé. Dans l'ensemble, le rationnel est ce qui se répète pour qu'une telle répétition à une personne puisse être remarquée. Cependant, nous ne nous attarderons pas là-dessus maintenant, mais réfléchissons un peu plus en profondeur.

Rappelons que très probablement le soi-disant La «vie» sur Terre est née de l'interaction chaotique des éléments chimiques. Une telle vie ne se serait jamais produite si une molécule n'avait pas été capable de tirer des électrons d'une autre, ou vice versa, séparée de la sienne. Cette OCCASION elle-mêmece n'est que parce que les composés sont apparus des éléments, et des composés également les premiers réplicants et organismes. Par conséquent, si nous voulons créer une vie numérique, nous devons DONNER L'OPPORTUNITÉ de l' interaction.

Si nous étions de grands architectes de l'univers et connaissions exactement toutes ses lois, à partir de la primaire, les problèmes de leur numérisation ne constitueraient pas de sérieux problèmes. Mais parce que comme nous ne le sommes pas (malheureusement), nous ne pouvons que compter sur le fait que nous pouvons deviner et créer les mêmes conditions qui étaient avec l'avènement de la vie biologique, rendant ainsi possible la vie numérique.

C'est pour cela que j'essaie de décrire les principes du code libre. Le code libre maximum possible. Libre de notre propre compréhension de la façon dont la vie devrait être organisée - car une telle compréhension est probablement erronée ou si incomplète qu'elle n'a pas trop de sens. Nous, petites créatures, essayons si fort d'étudier et de décrire tout ce qui nous entoure que nous ne pouvons même pas le faire. Mais personne n'a interdit d'essayer.

Lorsque vous écrivez un code chaotique, vous tombez inévitablement sur une fourchette. Expérience aléatoire. Ceux. soit aller chaotiquement plus loin, soit permettre la formation de l'expérience. Ceux. permettent non seulement aux particules d'entrer en collision, mais aussi d'interagir. Nous recherchons un analogue de la vie biologique, impensable sans transfert et régénération d'expérience. L'ARN / ADN est une expérience enregistrée qui est transmise.

En revanche, il ne peut en aucun cas être déterminé, car nous ne savons pas vraiment comment il s'est développé et se développe. Si cette tentation n'est pas supprimée, les erreurs sont inévitables. En d'autres termes, nous ne pouvons pas dire au programme à quoi devrait ressembler l'expérience et comment elle devrait être formée. Mais nous pouvons lui donner les outils avec lesquels il peut en principe se former.

J'ai lutté avec moi-même pendant très longtemps, car il me semblait que la structure du stockage de l'expérience pouvait être décrite très simplement. Penser que la simplicité, qui nous semble simple basée sur nos propres idées sur la simplicité, est un moyen sûr de nous tromper. Je soupçonne que la vraie simplicité est vraiment complexe. Mais je propose de ne pas entrer ici dans la démagogie.

Supposons que nous avons généré au hasard une ligne de code exécutable en réponse à un ensemble numérique d'entrée aléatoire. On peut supposer que la génération de réponse, ou réaction, est une expérience. Si quelque chose réagit de la même manière stable aux mêmes signaux entrants, nous pouvons dire qu'il utilise l'expérience. Par conséquent, je voudrais me souvenir de la chaîne générée. Mais cela ne peut pas être fait directement! Vous ne pouvez pas simplement prendre cette ligne et la placer quelque part dans la variable tableau de l'instance de classe et commencer à créer une sorte de bibliothèque de réactions de cette manière, en écrivant quelque chose comme IF [input.set dans memory_ array] THEN [memory .-> reaction]. C'est impossible! Parce que ce n'est pas un fait que c'est ainsi que fonctionnent les «systèmes de mémoire biologique». Et pas le fait que leur construction était à l'origine la même que nous la voyons maintenant.

Dans le même temps, vous ne pouvez pas simplement prendre et générer au hasard une chaîne d'au moins 256 octets et essayer de l'exécuter, car sur les ordinateurs modernes, cela prendra beaucoup de temps et ne nous convient pas. Il est possible qu'une telle méthode soit idéale, mais hélas, il est impossible de le vérifier avec les technologies actuelles non développées.

De plus, nous avons toujours un langage de programmation et, quoi qu'on en dise, notre propre idée d'au moins quelque chose. Vous ne pouvez pas du tout construire quelque chose à partir de rien. Par conséquent, nous avons besoin d'un regard subjectif. Par exemple, je ne peux pas m'empêcher de voir comment une forme passe dans une autre et vice versa, comment le chaos prend facilement une forme et s'en sépare tout comme une balle soulevée d'un sol et relâchée tombe sur cet étage et laisse une marque. En conséquence, je ne veux rien déterminer exactement, mais je ne peux pas non plus tout randomiser.

Afin de comprendre le problème, imaginez que nous avons 2 actions possibles dans le code. Vous ne pouvez pas indiquer directement lequel choisir, car ce sera une décision. Et si vous randomisez tout, vous devez utiliser des probabilités. Simplement quoi? 50/50? 30/70? 80/20? Supposons, toutes choses étant égales par ailleurs, 50/50 est en effet la relation la plus indéfinie. Ensuite, le code ressemblera à ceci:

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


Quel est le problème avec ce code? Et le fait qu'à chaque itération de la boucle, ce code choisira TOUJOURS au hasard soit la première action, soit la seconde. En d'autres termes, un tel chaos n'est jamais structuré, car il n'a même pas une telle possibilité théorique. Dans l'ensemble, nous avons affaire à la même détermination. Il existe un moyen de sortir de cette situation. Elle consiste dans le fait que l'action1 et l'action2 elles-mêmes doivent changer les conditions dans lesquelles elles sont appliquées. Il y a, je pense, différentes options, mais je voudrais proposer les suivantes.

Comme vous le savez, les systèmes d'exploitation équilibrent les threads dans la file d'attente d'exécution à l'aide de la hiérarchisation. Un thread en cours d'exécution au moment de l'exécution perd progressivement la priorité, tandis qu'un thread inactif dans une file d'attente augmente cette priorité. À un certain rythme, la priorité de ce dernier devient plus élevée que la première, les flux changent de place, puis la situation se répète. Ainsi, les flux alternent assez rapidement les uns après les autres et on voit l'illusion qu'ils sont exécutés presque simultanément.

Dans notre cas, le principe de priorité nous permettra de changer non pas les threads à exécuter sur le noyau, mais des parties du code où le contrôle sera transféré. Et si nous faisons une partie du code comme «aléatoire», et la seconde comme «expérimentale», alors leur changement alternatif sera la solution même que nous recherchons.

En d'autres termes, le code, en appliquant l'expérience, augmentera à chaque fois la probabilité que la prochaine fois que l'action soit aléatoire, et agissant de manière aléatoire, augmentera la probabilité d'appliquer l'expérience lors des itérations suivantes du cycle. Ainsi, nous obtenons le flux de chaos souhaité dans l'expérience et vice versa - exactement ce dont nous avons besoin.

Un avantage incroyable de cette conception est qu'il n'y a absolument aucun problème avec l'ossification du système, qui est connue, par exemple, dans les mêmes réseaux de neurones. D'un autre côté, nous sacrifions la stabilité, mais nous n'en avons pas besoin ici.

Je souhaite ici surtout soulignerque les programmeurs classiques ordinaires ont besoin de la stabilité du code comme une manne céleste: la reconnaissance doit reconnaître de manière stable, et pas une fois à chaque fois, le serveur doit répondre avec une réponse prescrite à la demande du client correspondante de temps en temps, et non pas une fois pour la même réponse , puis un autre, etc. etc. Dans la programmation régulière, l'instabilité du code est un bug clair qui est détecté lors des tests. Dans notre cas, cette stabilité n'est pas nécessaire du tout, car nous n'avons pas de tâche de code claire. Plus précisément, ce n'est pas du tout. Mais nous pouvons le dire autrement: nous avons besoin de la stabilité du code de transfert de changement de contrôle, et nous l'obtenons. On peut également dire que le pendule est stable, même s'il parvient à passer d'un point à l'autre en un cycle.

Afin de ne pas être infondé, je suggère de regarder le code élémentaire suivant en Python, que j'ai esquissé aujourd'hui, guidé par toutes les considérations ci-dessus.

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


Je vous invite à essayer d'exécuter ce script par vous-même et à voir comment cela fonctionne. Il s'agit d'un code auto-équilibré. En l'état de l'action 1
print(random.random())
- c'est à dire. juste une sortie de nombre aléatoire, et les actions 2 -
print(deter_numb)
- sortie d'un nombre déterminé. Dans le code, il y aura des actions à leur place, j'ai fait les impressions ici juste pour démontrer le principe.

Lorsque le contrôle passe à la première condition (la partie aléatoire du code), le code lui-même réduit la probabilité de répétition (p_random- = 0,01 - se décrémente) et augmente en même temps la probabilité d'exécution de la partie du code où l'expérience est appliquée (p_deter + = 0,01 - incrément de la probabilité d'un autre). La même chose se produit lors du transfert du contrôle à la deuxième condition. Ainsi, ces deux morceaux de code, lorsqu'ils sont exécutés, eux-mêmes «ralentissent» et «accélèrent» en même temps l'autre partie «concurrente» du code.

Veuillez noter que la probabilité initiale que le contrôle soit transféré à la partie aléatoire du code est de 99% et à la partie expérimentale - 1%. Cela montre que le système est équilibré même avec des probabilités radicalement différentes. Lors de l'exécution du code, on verra comment ce ratio atteindra 50/50 en une centaine d'itérations, formant une distribution normale avec un pic explicite de 0,5 et un voisinage de travail d'environ 6% (dans les 3-5 à 10000 itérations suivantes).

Lors de l'exécution du code, il est clair que les probabilités s'équilibrent et s'installent autour de 0,5, s'équilibrant au-delà de ce point, tout comme un balancier s'équilibrant au voisinage de son point inférieur.

Une autre caractéristique est visible ici: soit un nombre aléatoire soit un nombre déterminé est affiché (69), ou les deux à la fois, ce qui signifie que le système peut soit appliquer l'expérience, puis agir de manière aléatoire, ou vice versa, ou simplement appliquer l'expérience, ou simplement agir au hasard. En d'autres termes, l'exécution du code lui-même reste aléatoire, mais nous avons permis au système d'appliquer l'expérience, c'est-à-dire nous nous sommes débarrassés de la détermination lorsque nous avons décidé de l'action, ce qui était exactement ce dont nous avions besoin.

Dans le prochain article, nous considérerons la formation d'actions aléatoires et d'expérience. Eh bien, ou quelque chose séparément, voyons comment ça se passe.

All Articles