Equilíbrio na tomada de decisão. Garfo "experiência aleatória"

imagem

Para escrever a vida real, você não precisa de nada além de se derrotar completamente e completamente. Eu continuo a criá-lo e mais tarde vou escrever um artigo enorme sobre esse tópico, mas, meu, o que é isso em si e quão difícil é medir 7 vezes, cortar um, depois medir outro 77 vezes e, eventualmente, não cortar. Meça, meça novamente! - Este é o lema de alguém que quer criar algo verdadeiramente incomum. Codificar é muito mais fácil do que pensar. Mas pensar é doloroso e incomum em geral.

Mas hoje eu quero me debruçar sobre um "problema" que surgiu aqui na campanha. Imagine o movimento caótico de partículas ou elementos químicos - eles se movem em algum volume condicionalmente finito, apenas colidem, ou repelem - o caos em sua forma mais pura. Se um sistema desse tipo for lançado, mesmo nesse formigueiro aparentemente inútil, movimentos estruturados serão observados de tempos em tempos: colisões aleatórias em um determinado momento podem ocorrer de tal maneira que a direção dos impactos (impulso) seja mais ou menos em uma direção e colidam partículas se moverão em uma direção, formando uma onda. No futuro, essa onda de colisões de terceiros começará a decair e veremos novamente uma imagem caótica.

Essa. aleatoriamente em sua essência involuntariamente forma uma estrutura, mas a estrutura é apenas uma forma temporária desse aleatório. Fluindo dessa maneira, o caos assume várias formas, que percebemos como algo razoável, isto é, encomendado. Em geral, o racional é o que é repetido para que essa repetição para uma pessoa possa ser notada. No entanto, não vamos nos aprofundar nisso agora, mas pense um pouco mais.

Lembre-se de que provavelmente os chamados A "vida" na Terra surgiu como resultado da interação caótica de elementos químicos. Tal vida nunca teria acontecido se uma molécula não tivesse sido capaz de puxar elétrons de outra, ou vice-versa, se separando da sua. Esta própria OPORTUNIDADEfoi apenas devido ao fato de os compostos aparecerem a partir dos elementos, e a partir dos compostos os primeiros replicantes e organismos. Portanto, se queremos criar uma vida digital, precisamos DAR A OPORTUNIDADE de interação.

Se fôssemos grandes arquitetos do universo e soubéssemos exatamente todas as suas leis, começando pelo primário, os problemas de digitalizá-los não constituiriam problemas sérios. Mas porque como não somos (infelizmente), só podemos confiar no fato de que podemos adivinhar e criar as mesmas condições que estavam com o advento da vida biológica, possibilitando assim o surgimento da vida digital.

É por isso que estou tentando descrever os princípios do código livre. O código livre máximo possível. Livre de nossa própria compreensão de como a vida deve ser organizada - pois tal compreensão provavelmente é errada ou tão incompleta que faz muito pouco sentido. Nós, pequenas criaturas, estamos nos esforçando tanto para estudar e descrever tudo ao nosso redor que nem conseguimos fazê-lo. Mas ninguém proibiu tentar.

Quando você escreve um código caótico, inevitavelmente encontra um garfo. Experiência aleatória. Essa. ou mova-se caoticamente mais adiante ou possibilite a formação da experiência. Essa. permite não apenas que partículas colidam, mas também interaja. Estamos procurando um análogo da vida biológica, que é impensável sem a transferência e a regeneração da experiência. RNA / DNA é uma experiência registrada que é transmitida.

Por outro lado, não pode ser determinado em nenhum caso, porque não sabemos realmente como ele se desenvolveu e se desenvolve. Se essa tentação não for removida, os erros são inevitáveis. Em outras palavras, não podemos dizer ao programa como a experiência deve parecer e como deve ser formada. Mas podemos dar a ela as ferramentas com as quais ele pode, em princípio, ser formado.

Lutei comigo mesmo por muito tempo, porque me pareceu que a estrutura do armazenamento da experiência podia ser descrita de maneira bastante simples. Pensar que a simplicidade, que nos parece simples com base em nossas próprias idéias sobre simplicidade, é uma maneira de nos enganar. Suspeito que a verdadeira simplicidade seja verdadeiramente complexa. Mas proponho não entrar em demagogia aqui.

Suponha que geramos aleatoriamente uma linha de código executável em resposta a um conjunto numérico de entrada aleatória. Pode-se supor que a geração de resposta, ou reação, seja experiência. Se algo reage de maneira estável aos mesmos sinais recebidos, podemos dizer que usa experiência. Portanto, gostaria de lembrar a sequência gerada. Mas isso não pode ser feito diretamente! Você não pode simplesmente pegar essa linha e inseri-la em algum lugar na variável array da instância da classe e começar a criar um tipo de biblioteca de reação dessa maneira, escrevendo algo como IF [input.set in memory_ array] THEN [memory .-> reação]. É impossível! Porque não é assim que funcionam os "sistemas de memória biológica". E não o fato de que sua construção era originalmente a mesma que a vemos agora.

Ao mesmo tempo, você não pode simplesmente gerar e gerar aleatoriamente uma sequência de pelo menos 256 bytes e tentar executá-la, porque em computadores modernos isso leva uma quantidade enorme de tempo e não é adequado para nós. É possível que esse método seja ideal, mas, infelizmente, é impossível verificar isso com as atuais tecnologias não desenvolvidas.

Além disso, ainda temos uma linguagem de programação e, o que quer que se diga, nossa própria idéia de pelo menos alguma coisa. Você não pode construir algo do nada. Portanto, precisamos de um olhar subjetivo. Por exemplo, não posso deixar de ver como uma forma passa para outra e vice-versa, como o caos assume facilmente uma forma e também se separa dela, assim como uma bola levantada do chão e liberada cai no chão e deixa uma marca. Como resultado, não quero determinar nada exatamente, mas também não posso randomizar tudo.

Para entender o problema, imagine que tenhamos 2 ações possíveis no código. Você não pode indicar diretamente qual escolher, pois isso será uma determinação. E se você aleatoriamente tudo, precisará usar probabilidades. Somente o que? 50/50? 30/70? 80/20? Suponha, sendo outras coisas iguais, 50/50 é realmente a relação mais indefinida. Em seguida, o código será algo como isto:

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


O que está errado neste código? E o fato de que a cada iteração do loop, esse código SEMPRE escolhe aleatoriamente a primeira ação ou a segunda. Em outras palavras, esse caos nunca é estruturado, porque nem sequer tem essa possibilidade teórica. Em geral, aqui estamos lidando com a mesma determinação. Existe uma maneira de sair dessa situação. Consiste no fato de que a própria ação1 e a ação2 devem alterar as condições sob as quais são aplicadas. Penso que existem opções diferentes, mas gostaria de oferecer o seguinte.

Como você sabe, os sistemas operacionais equilibram encadeamentos na fila de execução usando a priorização. Um encadeamento em execução no tempo de execução perde gradualmente a prioridade, enquanto um encadeamento inativo em uma fila aumenta essa prioridade. Em um determinado momento, a prioridade do último se torna mais alta que a primeira, os fluxos mudam de lugar e a situação se repete. Assim, os fluxos alternam rapidamente um após o outro e vemos a ilusão de que eles são executados quase simultaneamente.

No nosso caso, o princípio da prioridade nos permitirá alterar não os threads para execução no kernel, mas partes do código onde o controle será transferido. E se fizermos uma parte do código como "aleatória" e a segunda como "experimental", a mudança alternativa será a mesma solução que estamos procurando.

Em outras palavras, o código, aplicando experiência, aumentará cada vez mais a probabilidade de que da próxima vez que a ação seja aleatória, e agindo aleatoriamente, aumentará a probabilidade de aplicar a experiência nas iterações subsequentes do ciclo. Assim, colocamos o fluxo desejado de caos em experiência e vice-versa - exatamente o que precisamos.

Uma vantagem incrível desse projeto é que não há nenhum problema com a ossificação do sistema, que é conhecido, por exemplo, nas mesmas redes neurais. Por outro lado, sacrificamos a estabilidade, mas não precisamos dela aqui.

Desejo aqui especialmente enfatizarque programadores clássicos comuns precisam de estabilidade de código como maná do céu: o reconhecimento deve reconhecer de maneira estável, e nem uma vez, o servidor deve responder com uma resposta prescrita à solicitação do cliente correspondente de tempos em tempos, e não com a mesma resposta e depois outro, etc. etc. Na programação regular, a instabilidade do código é um erro claro detectado nos testes. No nosso caso, essa estabilidade não é necessária a partir da palavra, porque não temos uma tarefa de código clara. Mais precisamente, não é de todo. Mas podemos colocar de outra maneira: precisamos da estabilidade da alteração do código de transferência de controle e conseguimos. Também se pode dizer que o pêndulo é estável, embora consiga ir de um ponto ao contrário em um ciclo.

Para não ser infundado, sugiro olhar para o código elementar a seguir em Python, que esbocei hoje, guiado por todas as considerações acima.

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


Peço que você tente executar esse script por conta própria e veja como ele funciona. Este é um código de auto-equilíbrio. Como a ação 1 permanece
print(random.random())
- ou seja, apenas uma saída de número aleatório e as ações 2 -
print(deter_numb)
- saída de um número determinado. No código, haverá ações em seu lugar, eu fiz as impressões aqui apenas para demonstrar o princípio.

Quando o controle passa para a primeira condição (a parte aleatória do código), o próprio código reduz a probabilidade de repetição (p_random- = 0,01 - diminui a si mesmo) e ao mesmo tempo aumenta a probabilidade de execução da parte do código em que a experiência é aplicada (p_deter + = 0,01 - incremento da probabilidade de outra). O mesmo acontece ao transferir o controle para a segunda condição. Assim, esses dois trechos de código, quando executados, "desaceleram" e, ao mesmo tempo, "aceleram" a outra parte "concorrente" do código.

Observe que a probabilidade inicial de que o controle seja transferido para a parte aleatória do código é de 99% e para a experimental - 1%. Isso mostra que o sistema é equilibrado, mesmo com probabilidades radicalmente diferentes. Ao executar o código, será visto como essa proporção chegará a 50/50 em apenas cem iterações, formando uma distribuição normal com um pico explícito de 0,5 e uma vizinhança de trabalho de cerca de 6% (nas próximas 3-500 iterações).

Ao executar o código, fica claro que as probabilidades entram em equilíbrio e se estabelecem em torno de 0,5, equilibrando-se além desse ponto, como um pêndulo equilibrando-se nas proximidades de seu ponto inferior.

Mais um recurso é visível aqui: um número aleatório ou um determinado é exibido (69), ou os dois ao mesmo tempo, o que significa que o sistema pode aplicar a experiência e então agir aleatoriamente, ou vice-versa, ou apenas aplicar a experiência ou apenas agir aleatoriamente. Em outras palavras, a execução do código em si permanece aleatória, mas permitimos que o sistema aplique experiência, ou seja, nos livramos da determinação ao decidir sobre a ação, que era exatamente o que precisávamos.

No próximo artigo, consideraremos a formação de ações e experiências aleatórias. Bem, ou algo separadamente, vamos ver como vai.

All Articles