Jump to content

Bem vindo à Unidev
Registre para ter acesso a todos os recursos do site. Uma vez registrado e logado, você poderá criar tópicos, postar em tópicos já existentes, gerenciar seu perfil e muito mais. Se você já tem uma conta, faça login aqui - ou então crie aqui uma conta agora mesmo!
- - - - -
Photo

Aprendizado por Reforço para Games


por Eric Laukien

Este artigo assume que o leitor já sabe o que são redes neurais e como elas operam. Se você não sabe o que são redes neurais, recomendo tentar esses ótimos tutoriais no AI Junkie [http://www.ai-junkie...lved/nnt1.html]

Redes neurais são normalmente desconsideradas quando se trata de Inteligência Artificial de game. Isto porque já receberam muita atenção antes, mas não durou muito. Entretanto, redes neurais ainda são uma área de intensa pesquisa, e vários algoritmos de aprendizado são desenvolvidos para cada um dos 3 tipos básicos de aprendizado: supervisionado, não supervisionado e apredizado por reforço.

Aprendizado por reforço é um algoritmo de aprendizado que permite um agente aprender com seu ambiente e melhorar a si mesmo por conta própria. Esta é uma classe de algoritmos de aprendizado que iremos focar neste artigo. Este artigo vai discutir o uso de algoritmos genéticos assim como um algoritmo que o autor tem pesquisado para Apredizado por reforço de agente simples (single-agent). Este artigo assume que as redes neurais são do tipo simples de Integre-e-dispare (integrate and fire), sem spiking de ativação sigmoidal.


Algoritmos Genéticos
Conceito

Algoritmos genéticos são um dos mais simples mas também dos mais efetivos métodos de aprendizado por reforço. Porém ele tem uma limitação chave: ele tem que operar em vários agentes (IA). Mesmo assim, algoritmos genéticos podem ser uma grande ferramenta para criar redes neurais via processo de evolução.

Algoritmos genéticos são parte de uma vasta gama de algoritmos evolucionários. Suas operações básicas procedem da seguinte maneira:
1 - Inicializar um set de genes
2 - Avaliar a capacidade/condições de todos os genes
3 - Juntar genes baseado em quão bem é sua performance (fazendo crossover e mutação)
4 - Trocar genes antigos por novos (children)
5 - Repetir passos 2 - 4 até que atinja um critério de término

Os genes podem ser tanto uma codificação direta dos traços da IA (caso do peso do neuron na rede neural), ou indireta, codificação "generativa". Avaliar a capacidade/condição é onde maior parte do tempo de processamento é gasto, já que envolve simular um fenótipo criado de cada genótipo para garantir o quão bem ele é em terminar determinada tarefa. A capacidade/condição é gravada, e são tipicamente classificadas de modo que a menor é sempre 0. A razão para isso é o passo de juntar. Aqui, genes são selecionados baseados na sua capacidade/condição usando uma função de seleção. Uma função de seleção popular é a função de seleção de capacidade/condição proporcional em roleta, onde escolhe aleatoriamente genes probabilidades proporcionais à sua capacidade/condição. Algumas funções de seleção como a de seleção capacidade/condição proporcional requerem todas as capacidades/condições positivas, e por isso elas são tipicamente redimensionadas para que a menor seja sempre 0.

Quando um par de gene raiz (parents) é selecionado, seus gene são cruzados usando uma função de crossover. Esta função depende da sua codificação, mas geralmente você vai querer traços de cada raiz para colocar no gene filho resultante (child) sem ser destrutivo. Depois do crossover, os genes também são mutados (levemente alterados aleatoriamente) para ajudar a forçar o algoritmo a executar uma maior exploração de possíveis soluções.

Ao longo do tempo, os genótipo irão melhorar por conta própria, e frequentemente irão aprender a explorar falhas em qualquer sistema em que estiverem operando!

Agora, iremos discutir um particular método de codificação de gene para redes neurais.

NEAT

O código seguinte executa o algoritmo genético seguindo a metodologia NEAT (Neuro-Evolution of Augmenting Topologies, ou Neuro-Evolução de Topologias em Expansão) criada por Kenneth Stanley. Como resultado, os genes da rede neural são codificados armazenando conexões entre neurons como pares de indices (indexados no array de neurons) junto com o peso (weight) associado, assim como os vieses (bias) para cada um dos neurons.

Esta é toda a informação necessária para construir uma rede neural completamente funcional de genes. Entretanto, junto com essa informação, ambos os vieses de neurons (bias) e as conexões de genes tem um "número de inovação" especial armazenado junto com eles. Esses números são únicos, um contador é incrementado a cada vez que um número de inovação e associado. Dessa forma, quando os genes de rede são juntados, podemos dizer se conexões compartilham hereditariedade olhando se seus números de inovação batem. Eles podem então ser cruzados diretamente, enquanto os genes sem números de inovações correspondentes podem ser associados aleatoriamente com os filhos da rede neural.

Esta descrição falta alguns detalhes, mas tem a intenção de simplesmente prover uma visão superficial do modo que o algoritmo genético incluído no pacote do software funciona.

Enquanto o algoritmo genético funciona muito bem para vários problemas, ele requer que muitos agentes sejam simulados ao mesmo tempo em vez de um aprendendo sozinho por conta própria. Então, iremos cobrir brevemente outro método de treinamento de rede neural.


Regra de Atualização de peso de Dopamina Local com pesos e traços de saída
Conceito

É bem provável que este método já tenha sido inventado, mas não pude achar trabalhos descrevendo esse mesmo método até agora. Este método se aplica em como os pesos dos neurons são atualizados quando aprendendo em um cenário de um único agente (single-agent). Este método é inteiramente separado do seleção de topologia da rede. Como resultado, o pacote de software incluso usa um algoritmo genético para evoluir a topologia para uso com o sistema de aprendizado por reforço de agente único. Claro, poderia simplesmente crescer a rede neural adicionando aleatoriamente neurons com o passar do tempo.

De qualquer forma, descobri esta técnica depois de muita tentativa e erro enquanto tentava achar uma regra de atualização para redes neurais que opera usando a informação disponível a nível de neuron/synapse. Isto de certa forma poderia ser biologicamente plausível. O método usa um sinal de recompensa, dopamina, para determinar quando a rede deve ser recompensada ou castigada. Para fazer este método funcionar, precisa adicionar um traço de saída (variável de ponto flutuante - float) para cada neuron, assim como um traço de peso (weight) para cada peso de neuron, exceto para o viés de peso (bias weight). Fora isso, somente será necessário a dopamina do sinal de recompensa (reward signal dopamine), que pode receber qualquer valor onde positivo significa recompensar a rede e negativo significa punir a rede (sendo assim o 0 neutro e não fazendo nada). Quando tem essa informação, tudo que precisa é atualizar os pesos da rede neural depois de cada ciclo de atualização normal usando o seguinte código (nesse caso em C++):


m_output = Sigmoid(potential * activationMultiplier);


m_outputTrace += -traceDecay * m_outputTrace + 2.0f * m_output - 1.0f;


// Weight update
for(size_t i = 0; i < numInputs; i++)
{
	m_inputs[i].m_trace += -traceDecay * m_inputs[i].m_trace + m_outputTrace * (m_inputs[i].m_pInput->m_outputTrace * 0.5f + 0.5f);
	m_inputs[i].m_weight += alpha * m_inputs[i].m_trace * dopamine;
}


// Bias update
m_bias += alpha * m_outputTrace * dopamine;


Onde m_output é a saída do neuron, traceDecay é o valor que define o quão rápido a rede esquece (valores de [0,1]), alpha é a taxa de aprendizado, e m_inputs é uma array de conexões.

Esse código funciona da seguinte maneira:
O traço de saída (output trace) é simplesmente uma saída média ao longo do tempo que decresce se deixada sem mexer. A atualização de peso (weight update) simplesmente move o peso se a dopamina não é igual a 0 (ainda não tem a condição perfeita) na direção que causaria sua saída média sair menos se a dopamina for negativa ou sair mais se a dopamina for positiva. Entretanto, ele faz isso baseado no traço de peso (weight trace), que mede o quanto uma conexão tem contribuído para o disparo de um neuron ao longo do tempo, e assim ajuda a julgar o quão elegível um peso é para atualização de peso. O viés (bias) não usa traço de peso, já que ele sempre é elegível para atualização de peso.

Este método é capaz de resolver o problema de XOR com considerável facilidade (ele aprende facilmente uma porta XOR). Eu testei ele com uma simples rede neural feed-foward (1 camada escondida com 2 neurons), uma nuvem neural crescente, e redes resultantes do algoritmo NEAT.


USO NOS GAMES?

Estes métodos parecem ser totalmente overkill para jogos. Mas, eles podem fazer coisas que métodos tradicionais não podem. Por exemplo, com o algoritmo genético, você pode fazer um controlador de personagem (character controller) baseado em física como este [http://www.youtube.c...v=mQNWNIM7waU].

A animação não foi feita por um animador, mas a IA aprendeu a andar sozinha. Isto resulta numa animação que pode reagir ao ambiente diretamente. A IA neste video foi criada usando o mesmo pacote de software que este artigo engloba (link abaixo).

A segunda técnica discutida pode ser usada para fazer personagens de jogos ou inimigos aprenderem de acordo com sua expêriencia. Inimigos podem por exemplo serem associados a uma recompensa para o quão perto eles chegam do jogador, assim eles irão tentar chegar o mais perto possível do jogador com alguns sensores de entrada. Este método pode ser também usado para games de bichinhos virtuais, onde você pode recompensar ou punir o bichinho de acordo com o comportamento que você queira alcançar.

USANDO O CÓDIGO

O pacote de software que acompanha este artigo contém um manual de como usar o código.
O pacote de software pode ser encontrado aqui: [https://sourceforge....atvisualizers/]

CONCLUSÃO

Espero que este artigo tenha provido uma visão e inspiração para o uso de aprendizado por reforço de redes neurais de IA nos jogos. Agora suma daqui e vai fazer alguma IA de game legal!

Fonte: gamedev.net
[http://www.gamedev.n...for-games-r3271]



0 Comments