Inicio     |     Sobre     |     GitHub     |     Games     |     Contato                        

sexta-feira, 5 de abril de 2019

Resumo Semanal de Pesquisa: Project Malmo e Desenvolvimento dos ambientes de testes


   Essa semana a atenção maior foi em finalizar os tutoriais e exemplos básicos em relação ao funcionamento do Project Malmo em conjunto com a linguagem de programação Java. A prioridade é realizar todos os testes básicos possíveis incluindo juntamente e separadamente elementos importantes para a boa comunicação entre a mente do agente e o agente no ambiente. Foi finalizado também o tutorial básico iniciado no resumo anterior <http://algamecode.blogspot.com/2019/03/resumo-semanal-de-pesquisa-project.html>, esse pode ser acompanhado a seguir:



Final do tutorial em python:


    Dando continuidade aos tutoriais em ainda em Python, o código tutorial_6.py mostra um exemplo de códio que utiliza Q-Learning para que o agente aprenda a navegar na plataforma sem cair na lava. É pedido que seja feita a mudança em alguns trechos do código para melhorar a performance de aprendizado, e em seguida é sugerido que o programador tente melhorar a lógica de pontuação de forma a tentar melhorar os resultados obtidos.


    Em seguida no tutorial_7.py ao executar o código é criado uma especie de labirinto simples (sem pareces mas cheio de buracos no chão), nessa etapa é pedido que o programador usando <Enter> tome o controle do agente e jogue um pouco, chegando sempre ao final do labirinto (obs: a cada rodada um novo labirinto é criado). Em seguida é sugerido dar uma olhada no código de exemplo MazeRunner.py, para observar outros tipos de labirintos que podem ser usados e também soluções que façam o agente aprender a navegar pelo labirinto.


   Já o tutorial_8.py tem a mesma proposta, porém ao invés de labirintos você deve encontrar uma caixa amarela que pode ou não estar no mesmo comodo que você. No final a proposta também é que o programador crie um algoritmo que ensine o agente a cumprir o objetivo aqui proposto da melhor forma possível.


   No fim é discutido um pouco sobre geradores de missão e sobre a possibilidade de usar vídeo como retorno para que o agente consiga ver o ambiente, ao invés do Grid usado até aqui. E por fim o desafio final deixado é voltar ao tutorial_2.py e modificar o terreno plano para um terreno mais aleatório (<DefaultWorldGenerator/>), e é deixado o desafio de criar uma IA geral que seja capaz de fazer o agente jogar nesse mundo mais complexo.

   Esses últimos exemplos são mais uma disponibilização de ambientes para que se possa aplicar e testar seus algoritmos e até mesmo aprender a construir e trabalhar com os mesmo, e poderão ser usados mais a diante como ambientes de testes de diferentes tipos de algoritmos, em outros projetos. Reforço que é importante para qualquer um que queira aprender mais a fundo sobre esses experimentos ler e tentar resolver os exercícios propostos no tutorial.

Continuando os tutoriais em Java:


Conforme discutido antes, nos últimos testes foi encontrado um problema de sincronia entre o ambiente do Malmo e o código java. Logo, o que sabemos até o momento é que talvez um Timer resolva, mas é preciso identificar onde isso deve ser usado.
Coloquei um Timer nesse ponto do código apenas para fazer alguns testes:

int delay = 50;   // 5000 delay de 5 seg.
int interval = 10;  // 1000 intervalo de 1 seg.
Timer timer = new Timer();
        
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
//Commands 
agent_host.sendCommand("hotbar.9 1");//Press the hotbar key
agent_host.sendCommand("hotbar.9 0");//Release hotbar key - agent should now be holding diamond_pickaxe
agent_host.sendCommand("pitch 0.2");//Start looking downward slowly
try {
   Thread.sleep(1);//Wait a second until we are looking in roughly the right direction
} catch (InterruptedException ex) {
            Logger.getLogger(ExpMalmoMeca1.class.getName()).log(Level.SEVERE, null, ex);
}
agent_host.sendCommand("pitch 0");//Stop tilting the camera
agent_host.sendCommand("move 0.3");//And start running...
agent_host.sendCommand("attack 1");//Whilst flailing our pickaxe!
//Commands End
}
}, delay, interval);

Também coloquei mensagens para verificar a entrada nas condições de pular a e parar de pular:

if (!pular && (grid[4] != "lava")){
    //agent_host.sendCommand("move 1");
    agent_host.sendCommand("jump 0");
    pular = false;
System.out.println("PAROU DE PULAR \n PAROU DE PULAR");
}
if (grid[3]=="lava"){
    //agent_host.sendCommand("move 0");
    agent_host.sendCommand("jump 1");
    pular = true;
   System.out.println("PULOU \n PULOU");
}

Visualmente a saída foi bem lenta, percebi o agente fazendo lentamente cada um dos comandos presentes dentro do timer. Já as saídas do console foram as seguintes:


PAROU DE PULAR 
 PAROU DE PULAR
Posição: 0=lava

Posição: 1=obsidian

Posição: 2=obsidian

Posição: 3=lava

Posição: 4=obsidian

Posição: 5=obsidian

Posição: 6=lava

Posição: 7=obsidian

Posição: 8=obsidian

PAROU DE PULAR 
 PAROU DE PULAR
Posição: 0=lava

Posição: 1=obsidian

Posição: 2=obsidian

Posição: 3=lava

Posição: 4=obsidian

Posição: 5=obsidian

Posição: 6=lava

Posição: 7=obsidian

Posição: 8=obsidian

PAROU DE PULAR 
 PAROU DE PULAR
Posição: 0=lava

Posição: 1=obsidian

Posição: 2=obsidian

Posição: 3=lava

Posição: 4=obsidian

Posição: 5=obsidian

Posição: 6=lava

Posição: 7=obsidian

Posição: 8=obsidian

...
PAROU DE PULAR 
 PAROU DE PULAR
Posição: 0=obsidian

Posição: 1=obsidian

Posição: 2=obsidian

Posição: 3=obsidian

Posição: 4=obsidian

Posição: 5=obsidian

Posição: 6=obsidian

Posição: 7=obsidian

Posição: 8=obsidian

PAROU DE PULAR 
 PAROU DE PULAR
Posição: 0=obsidian

Posição: 1=obsidian

Posição: 2=obsidian

Posição: 3=obsidian

Posição: 4=obsidian

Posição: 5=obsidian

Posição: 6=obsidian

Posição: 7=obsidian

Posição: 8=obsidian

PAROU DE PULAR 
 PAROU DE PULAR
Posição: 0=obsidian

Posição: 1=obsidian

Posição: 2=obsidian

Posição: 3=obsidian

Posição: 4=obsidian

Posição: 5=obsidian

Posição: 6=obsidian

Posição: 7=obsidian

Posição: 8=obsidian

PAROU DE PULAR 
 PAROU DE PULAR
Posição: 0=obsidian

Posição: 1=obsidian

Posição: 2=obsidian

Posição: 3=obsidian

Posição: 4=obsidian

Posição: 5=obsidian

Posição: 6=obsidian

Posição: 7=obsidian

Posição: 8=obsidian

PAROU DE PULAR 
 PAROU DE PULAR
Posição: 0=obsidian

Posição: 1=obsidian

Posição: 2=obsidian

Posição: 3=obsidian

Posição: 4=obsidian

Posição: 5=obsidian

Posição: 6=obsidian

Posição: 7=obsidian

Posição: 8=obsidian

PAROU DE PULAR 
 PAROU DE PULAR
Mission ended

Com as saídas a cima é possível fazer as seguintes observações:
1º Mesmo quando a condição para pular é verdadeira, ele não pula;
2º Ver e cair na lava são as ultimas coisas que o agente faz, logo essas deveriam ser as ultimas saidas, mas quando ele percebe a lava ele ao menos chegou nela ainda;
3º A ação pular não foi executada nenhuma vez;

Fiz outra alteração apenas para testes no código, fixei o valor da posição 3 da grid como sempre sendo lava (grid[3]="lava";) antes de entrar nas condições, na saída visual o agente saiu pulando a cada passo, e com isso conseguiu cumprir seu objetivo. Porém a saída no console foi um tanto estranha:

No primeiro passo do loop essa foi a saída:

Mission running
Posição: 0=air

Posição: 1=stained_glass

Posição: 2=stained_glass

Posição: 3=air

Posição: 4=stained_glass

Posição: 5=stained_glass

Posição: 6=air

Posição: 7=stained_glass

Posição: 8=stained_glass

PAROU DE PULAR 
 PAROU DE PULAR
PULOU 
 PULOU

Nos últimos passos:

Posição: 0=air

Posição: 1=air

Posição: 2=air

Posição: 3=air

Posição: 4=air

Posição: 5=air

Posição: 6=air

Posição: 7=air

Posição: 8=air

PULOU 
 PULOU
Posição: 0=air

Posição: 1=air

Posição: 2=air

Posição: 3=air

Posição: 4=air

Posição: 5=air

Posição: 6=air

Posição: 7=air

Posição: 8=air

PULOU 
 PULOU
Posição: 0=obsidian

Posição: 1=obsidian

Posição: 2=obsidian

Posição: 3=obsidian

Posição: 4=diamond_block

Posição: 5=obsidian

Posição: 6=obsidian

Posição: 7=obsidian

Posição: 8=obsidian

PULOU 
 PULOU
Posição: 0=obsidian

Posição: 1=obsidian

Posição: 2=obsidian

Posição: 3=obsidian

Posição: 4=diamond_block

Posição: 5=obsidian

Posição: 6=obsidian

Posição: 7=obsidian

Posição: 8=obsidian

PULOU 
 PULOU
Mission ended

O que é possível observar dessa vez?
Ele entrou na primeira condição mesmo não devendo entrar, não encontrei uma explicação lógica mas minha intuição me disse para inverter as condições e adicionar um else na condição de parar de pular. Removi o valor fixo do grid[3] e o código ficou assim:

if ("lava".equals(grid[3])){
//agent_host.sendCommand("move 0");
agent_host.sendCommand("jump 1");
pular = true;
System.out.println("PULOU \n PULOU");
}else if (!pular && (!"lava".equals(grid[4]))){
//agent_host.sendCommand("move 1");
agent_host.sendCommand("jump 0");
pular = false;
System.out.println("PAROU DE PULAR \n PAROU DE PULAR");
}

Enquanto a saída visual dessa fez:



O agente conseguiu cumprir o objetivo, começou a pular assim que chegou próximo a lava. Mas ainda resolvi fazer mais um experimento, removi o timer para ver o que aconteceria e consegui a seguinte saída:



Pelo que é possível observar, as vezes acontece um pequeno atraso na percepção do agente, ou as vezes ele simplesmente começa a pular antes da hora e cai na lava. Na maior parte dos testes houve sucesso na simulação, o agente cumpriu seu objetivo, mas ainda existe alguns problemas que precisam ser solucionados para que não influenciem nos resultados do experimento final.

Então o código numero 5 ficou da seguinte forma: <Ver no Github>

import com.microsoft.msr.malmo.*;
import java.util.Timer;
import java.util.TimerTask;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.json.*;
/**
*
* @author carol
*/
public class ExpMalmoMeca5 {
static
{
System.loadLibrary("MalmoJava"); // attempts to load MalmoJava.dll (on Windows) or libMalmoJava.so (on Linux)
}
/**
* @param argv the command line arguments
*/
public static void main(String argv[]){
// TODO code application logic here
//XML da missão
//+"<ContinuousMovementCommands turnSpeedDegs=\"180\"/>" ou +"<DiscreteMovementCommands/>"
String missionXML = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalon=\"no\" ?>"
+"<Mission xmlns=\"http://ProjectMalmo.microsoft.com\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"
+"<About><Summary>Hello World in Java!</Summary></About>"
+"<ServerSection>"
+"<ServerInitialConditions>"
+"<Time><StartTime>1000</StartTime><AllowPassageOfTime>false</AllowPassageOfTime></Time>"
+"<Weather>clear</Weather>"
+"</ServerInitialConditions>"
+"<ServerHandlers>"
+"<FlatWorldGenerator generatorString=\"3;7,44*49,73,35:1,159:4,95:13,35:13,159:11,95:10,159:14,159:6,35:6,95:6;12;\"/>"
+"<DrawingDecorator>"
+"<DrawSphere x=\"-27\" y=\"69\" z=\"0\" radius=\"30\" type=\"air\"/>"
+"<DrawCuboid x1=\"-25\" y1=\"39\" z1=\"-2\" x2=\"-29\" y2=\"39\" z2=\"2\" type=\"lava\"/>"
+"<DrawCuboid x1=\"-26\" y1=\"39\" z1=\"-1\" x2=\"-28\" y2=\"39\" z2=\"1\" type=\"obsidian\"/>"
+"<DrawBlock x=\"-27\" y=\"39\" z=\"0\" type=\"diamond_block\"/>"
+"</DrawingDecorator>"
+"<ServerQuitFromTimeUp timeLimitMs=\"30000\"/>"
+"<ServerQuitWhenAnyAgentFinishes/>"
+"</ServerHandlers>"
+"</ServerSection>"
+"<AgentSection mode=\"Survival\">"
+"<Name>MalmoTutorialBot</Name>"
+"<AgentStart>"
+"<Placement x=\"0.5\" y=\"56.0\" z=\"0.5\" yaw=\"90\"/>"
+"<Inventory><InventoryItem slot=\"8\" type=\"diamond_pickaxe\"/></Inventory>"
+"</AgentStart>"
+"<AgentHandlers>"
+"<ObservationFromFullStats/>"
+"<ObservationFromGrid>"
+"<Grid name=\"floor3x3\">"
+"<min x=\"-1\" y=\"-1\" z=\"-1\"/>"
+"<max x=\"1\" y=\"-1\" z=\"1\"/>"
+"</Grid>"
+"</ObservationFromGrid>"
+"<ContinuousMovementCommands turnSpeedDegs=\"180\"/>"
+"<InventoryCommands/>"
+"<AgentQuitFromTouchingBlockType>"
+"<Block type=\"diamond_block\" />"
+"</AgentQuitFromTouchingBlockType>"
+"</AgentHandlers>"
+"</AgentSection>"
+"</Mission>";
AgentHost agent_host = new AgentHost(); //Criar agente
try {
StringVector args = new StringVector();
//args.add("JavaExamples_run_mission");
args.add("ExpMalmoMeca5");
for( String arg : argv )
args.add( arg );
agent_host.parse( args );
}
catch( Exception e ) {
System.err.println( "ERROR: " + e.getMessage() );
System.err.println( agent_host.getUsage() );
System.exit(1);
}
if( agent_host.receivedArgument("help") ) {
System.out.println( agent_host.getUsage() );
System.exit(0);
}
MissionSpec my_mission;
try {
my_mission = new MissionSpec(missionXML, true);
MissionRecordSpec my_mission_record = new MissionRecordSpec();
my_mission.setSummary("Primeiro Experimento de Missão");
try {
agent_host.startMission( my_mission, my_mission_record );
}
catch (MissionException e) {
System.err.println( "Error starting mission: " + e.getMessage() );
System.err.println( "Error code: " + e.getMissionErrorCode() );
// We can use the code to do specific error handling, eg:
if (e.getMissionErrorCode() == MissionException.MissionErrorCode.MISSION_INSUFFICIENT_CLIENTS_AVAILABLE)
{
// Caused by lack of available Minecraft clients.
System.err.println( "Is there a Minecraft client running?");
}
System.exit(1);
}
} catch (Exception ex) {
Logger.getLogger(ExpMalmoMeca5.class.getName()).log(Level.SEVERE, null, ex);
}
//Loop until mission starts:
WorldState world_state;
System.out.print( "Waiting for the mission to start" );
do {
System.out.print( "." );
try {
Thread.sleep(100);//Thread.sleep(10);
} catch(InterruptedException ex) {
System.err.println( "User interrupted while waiting for mission to start." );
return;
}
world_state = agent_host.getWorldState();
for( int i = 0; i < world_state.getErrors().size(); i++ )
System.err.println( "Error: " + world_state.getErrors().get(i).getText() );
} while( !world_state.getIsMissionRunning() );
System.out.println( "" );
System.out.println( "Mission running" );
int delay = 50; // 5000 delay de 5 seg.
int interval = 10; // 1000 intervalo de 1 seg.
Timer timer = new Timer();
//timer.scheduleAtFixedRate(new TimerTask() {
//@Override
//public void run() {
//Commands
agent_host.sendCommand("hotbar.9 1");//Press the hotbar key
agent_host.sendCommand("hotbar.9 0");//Release hotbar key - agent should now be holding diamond_pickaxe
agent_host.sendCommand("pitch 0.2");//Start looking downward slowly
try {
Thread.sleep(1);//Wait a second until we are looking in roughly the right direction
} catch (InterruptedException ex) {
Logger.getLogger(ExpMalmoMeca5.class.getName()).log(Level.SEVERE, null, ex);
}
agent_host.sendCommand("pitch 0");//Stop tilting the camera
agent_host.sendCommand("move 0.5");//And start running...
agent_host.sendCommand("attack 1");//Whilst flailing our pickaxe!
//Commands End
//}
//}, delay, interval);
boolean pular = false;
//Loop until mission ends:
do {
try {
Thread.sleep((long) 0.1);
} catch (InterruptedException ex) {
Logger.getLogger(ExpMalmoMeca5.class.getName()).log(Level.SEVERE, null, ex);
}
world_state = agent_host.getWorldState();
for( int i = 0; i < world_state.getErrors().size(); i++ ) {
TimestampedString error = world_state.getErrors().get(i);
System.err.println( "Error: " + error.getText() );
}
/*
System.out.print( "video,observations,rewards received: " );
System.out.print( world_state.getNumberOfVideoFramesSinceLastState() + "," );
System.out.print( world_state.getNumberOfObservationsSinceLastState() + "," );
System.out.println( world_state.getNumberOfRewardsSinceLastState() );
for( int i = 0; i < world_state.getRewards().size(); i++ ) {
TimestampedReward reward = world_state.getRewards().get(i);
System.out.println( "Summed reward: " + reward.getValue() );
}
*/
//Parcialmente funcionando
if (world_state.getNumberOfObservationsSinceLastState() > 0){
TimestampedStringVector observations = world_state.getObservations();
if (observations.isEmpty())System.out.println("Observation Vazio!!");
String obs_text = observations.get((int) (observations.size() - 1)).getText();
JSONObject observation = new JSONObject(obs_text);
JSONArray blocks = observation.getJSONArray("floor3x3");
String grid[] = {"","","","","","","","",""};
//Ver o que há em todas as posições do array
//timer.scheduleAtFixedRate(new TimerTask() {
//@Override
//public void run() {
for (int i = 0; i < 9; ++i) {
String block = blocks.getString(i);
grid[i] = block;
System.out.println("Posição: "+ i + "=" +block+ "\n");
//if (grid [i] == "lava") grid[3]="lava";
}
//}
//}, delay, interval);
//grid[3]="lava";
if ("lava".equals(grid[3])){
//agent_host.sendCommand("move 0");
agent_host.sendCommand("jump 1");
pular = true;
System.out.println("PULOU \n PULOU");
}
else if (!pular && (!"lava".equals(grid[4]))){
//agent_host.sendCommand("move 1");
agent_host.sendCommand("jump 0");
pular = false;
System.out.println("PAROU DE PULAR \n PAROU DE PULAR");
}
//------
/*TimestampedString msg = world_state.getObservations().get(0);
String msg2 = msg.getText();
JSONObject observations = new JSONObject();
JSONArray floor = new JSONArray();
floor = (JSONArray) observations.get("floor3x3");
System.out.println(floor);*/
//-----
//JSONObject jobj = new JSONObject();
//String grid = jobj.getJSONObject("floor3x3").getString("floor3x3");
//JSONArray json = new JSONArray();
//json.getJSONArray(0);
//String obj = (String) json.get("floor3x3");
//System.out.print(json);
//System.out.print( world_state.getNumberOfObservationsSinceLastState());
//String msg = world_state.getObservations().toString();
//JSONObject json = new JSONObject();
//String observation = json.getString(msg);
//String grid[] = null;
//for( int i = 0; i < world_state.getObservations().size(); i++ ) {
//System.out.print(world_state.getObservations().get(i));
//}
}
/*
if world_state.number_of_observations_since_last_state > 0:
msg = world_state.observations[-1].text
observations = json.loads(msg)
grid = observations.get(u'floor3x3', 0)
if jumping and grid[4]!=u'lava':
agent_host.sendCommand("jump 0")
jumping = False
if grid[3]==u'lava':
agent_host.sendCommand("jump 1")
jumping = True
*/
} while( world_state.getIsMissionRunning() );
System.out.println( "Mission ended" );
//Mission has ended.
//END
}
}

Seguindo, o próximo exemplo deixado usa um algoritmo para ensinar o agente a navegar pela plataforma sem cair na lava. Como no momento para este trabalho é preciso focar no uso da arquitetura MECA com o Malmo, não vou dar enfase a construção desse tipo de algoritmo. Mais a diante posso estar falando e escrevendo esse e outros tipos de algoritmos de aprendizado de maquina, computação natural e inteligencia artificial no geral. Agora vamos focar na construção do ambiente que será utilizado e no uso do MECA para controlar um agente. Mais exemplos de ambientes podem ser encontrados na pagina do GitHub desse estudo ou no próprio project Malmo.

Criei uma classe apenas de missões onde estarei disponibilizando diferentes missões implementadas. Também fiz uma análise de alguns dos poucos exemplos de projetos em java que usam o Malmo, algumas observações interessantes são:

É possível a criação de missões diretamente pela API (sem o uso do XML) um exemplo simples é:

MissionSpec my_mission = new MissionSpec();
my_mission.timeLimitInSeconds(10);
my_mission.requestVideo( 320, 240 );
my_mission.rewardForReachingPosition(19.5f,0.0f,19.5f,100.0f,1.1f);
MissionRecordSpec my_mission_record = new MissionRecordSpec("./saved_data.tgz");
my_mission_record.recordCommands();
my_mission_record.recordMP4(20, 400000);
my_mission_record.recordRewards();
my_mission_record.recordObservations();

É interessante também observar essa parte do código <https://github.com/Microsoft/malmo/blob/master/Malmo/samples/Java_examples/JavaExamples_run_mission.java>. Observe que ele pega o estado do ambiente antes do loop principal e dentro do loop, após a execução de ação. Também observei que ele usou um thread com um valor alto perto dos que havíamos usado aqui até agora:

WorldState world_state;
System.out.print( "Waiting for the mission to start" );
do {
System.out.print( "." );
try {
Thread.sleep(100);
} catch(InterruptedException ex) {
System.err.println( "User interrupted while waiting for mission to start." );
return;
}
world_state = agent_host.getWorldState();
for( int i = 0; i < world_state.getErrors().size(); i++ )
System.err.println( "Error: " + world_state.getErrors().get(i).getText() );
} while( !world_state.getIsMissionRunning() );
System.out.println( "" );
// main loop:
do {
agent_host.sendCommand( "move 1" );
agent_host.sendCommand( "turn " + Math.random() );
try {
Thread.sleep(500);
} catch(InterruptedException ex) {
System.err.println( "User interrupted while mission was running." );
return;
}
world_state = agent_host.getWorldState();
System.out.print( "video,observations,rewards received: " );
System.out.print( world_state.getNumberOfVideoFramesSinceLastState() + "," );
System.out.print( world_state.getNumberOfObservationsSinceLastState() + "," );
System.out.println( world_state.getNumberOfRewardsSinceLastState() );
for( int i = 0; i < world_state.getRewards().size(); i++ ) {
TimestampedReward reward = world_state.getRewards().get(i);
System.out.println( "Summed reward: " + reward.getValue() );
}
for( int i = 0; i < world_state.getErrors().size(); i++ ) {
TimestampedString error = world_state.getErrors().get(i);
System.err.println( "Error: " + error.getText() );
}
} while( world_state.getIsMissionRunning() );
System.out.println( "Mission has stopped." );


Continuaremos a revisão de trabalhos relacionados na próxima semana.

Criando o ambiente de testes:


  No ultimo resumo foram deixadas algumas questões importantes para o desenvolvimento do ambiente. É preciso deixar claro que como o foco está na arquitetura cognitiva, em seu teste e na coleta de dados dos resultados alcançados pela mesma, é necessário direcionar a construção do ambiente visando o melhor para se alcançar a qualidade de testes necessários. Por isso, olhando para a arquitetura é possível afirmar que precisamos de um ambiente que ofereça:
  • Possibilidade de tomada de decisão;
  • Diferentes situações;
  • Situações repetidas (Simples);
  • Mais de um objetivos;
  • Número razoável de ações para o agente;
   Vamos começar a construção do ambiente do zero, com um ambiente simples. Para facilitar o trabalho, se organizar melhor criei uma classe apenas para os ambientes, de forma que sempre que for preciso usar um ambiente diferente basta trocar a função (cada função chama um ambiente). Nosso ambiente agora está simples, podemos ir implementando funcionalidades conforme o necessário.


   Na ultima semana deixei algumas questões em aberto que são importantes para a construção do ambiente e estarei respondendo agora. 

1 - Como será o terreno?
R: O terreno será plano mas não será 100% regular, terá muitos tipos de obstáculos espalhados. Quanto ao tamanho, fica entre médio e grande.

2 - As ações serão diretas ou desenvolvidas/pronta?
R: A resposta dessa questão será melhor explicada com o desenvolvimento do MECA para o uso nesse projeto, mas pode-se dizer que é uma mistura de ambos, haverá as ações simples e as ações complexas que são formadas por um tipo de plano ou conjunto de ações simples.

3 - Quais ações estarão disponíveis ao agente?
R: Praticamente todas, talvez a menos útil a primeiro momento seja "agachar" mas será deixado, para quem sabe nos surpreendermos com o resultado.

4 - Como será o feedback que o agente receberá a cada interação com o ambiente?
R: A cada ciclo cognitivo o agente executará uma ação, e receberá como retorno o resultado dessa ação, se foi negativa ou positiva de acordo com sua expectativa e como o ambiente se encontra após isso.
Mais respostas para os pontos de satisfação serão dadas com o desenvolvimento da arquitetura.

5 - Os experimentos, missões/simulações serão por turnos ou diretas?
R: Serão simulações longas, de 30 minutos até 3 horas cada de acordo com a necessidade. Porém serão feitas diversas experimentações para ser possível comprar os níveis de aprendizado e os resultados.

6 - Como a missão é finalizada?
R: Com o tempo, quando há um erro no sistema ou no caso quando o agente morre ele retorna ao mesmo mundo com as mesmas lembranças porem com um feedback bem negativo.

7 - Quanto tempo a missão irá durar?
R: De 30 minutos a umas 3 horas cada.

8 - Quais dados serão salvos?
R: Tempo, blocos e objetos a volta (visão), ação tomada e pontuações.

9 - Como serão salvos os dados?
R: Em vídeo e dados em arquivo texto.

Continuaremos a construção do ambiente na próxima semana.

MECA como controlador:


  A arquitetura cognitiva MECA (Multipurpose Enhanced Cognitive Architecture) foi criada pelo grupo de pesquisa na FEEC-UNICAMP, coordenado pelo Professor Dr. Ricardo Ribeiro Gudwin. O MECA é uma arquitetura cognitiva geral, construída utilizando o CST (Cognitive Systems Toolkit) <http://cst.fee.unicamp.br/> e baseada em diversas teorias de psicologia cognitiva. No meu trabalho estou focando no uso da teoria dos processos duais e na memória episódica, mas vale ressaltar que o MECA é uma arquitetura nova, ainda pouco explorada e com um grande potencial.

    A teoria dos processos duais, resumidamente, fala da interação de dois subsistemas que compõem a mente. Chamados de Sistema 1 e Sistema 2, receptivamente um é responsável pelos processos rápidos e automáticos da mente (e.g. dirigir ou caminhar para casa pelo mesmo caminho de sempre) enquanto o outro é responsável pelos processos lentos e de planejamento. Os Sistemas 1 e 2 implementados no MECA são ilustrados na imagem abaixo.


   Por ser construído usando o CST, o MECA é basicamente constituído de objetos de memória e codelets. As memórias armazenam informação e auxiliam na comunicação entre os codelets, enquanto os codelets são como blocos de códigos responsáveis por constituir e executar os processos da arquitetura.

  Para explicar melhor e de forma mais simples o funcionamento da arquitetura vou criar uma situação hipotética baseada em possíveis situações que podem acontecer em um experimento no Project Malmo.

  Temos um agente situado em um ambiente, nesse ambiente há plantas, blocos, alimentos, diamantes, animais, monstros, casas e um ponto de troca. O agente consegue ver tipos de objetos dentro do seu campo de visão, que é uma determinada quantidade de quadros a sua frente e ao seu lado. O agente também consegue, pegar itens, quebrar blocos, trocar de item no inventário, comer, bater e andar.

  Todas as entradas de dados (o que o agente vê ou percebe) são realizadas pelo sistema 1, assim como as saídas (ações que o agente executa). Digamos que não há nada interessante no campo de visão do agente, ele não está com fome e sua vida está cheia, sua maior motivação é encontrar diamantes. Após ficar um tempo parado ele perceber que seu ponto de riqueza apenas cai e de perceber que quando ele anda (para qualquer direção) ele pode encontrar riquezas e assim  aumentar esse mesmo ponto, ele vai ter um feedback positivo para a ação andar e com o tempo de tanto repetir essa ação para essa condição de ambiente, e assim se tornará uma ação automática, executada pelo sistema 1. Mas então algo novo acontece, um criatura aparece, não há situações parecidas em sua memória, então o sistema 2 entra para tentar escolher a melhor decisão a se tornar nesse caso, ele vai atacar a criatura? ele vai fugir? ambas essas opções podem precisar de um pequeno plano, um conjunto de ações que serão definidos também pelo sistema 2. Esse foi um exemplo bem simples, será mais fácil visualizar esse funcionamento na prática.

   No sistema 1 existem três tipos de memória (sensorial, de percepção e motor) e há 4 subsistemas. O subsistema sensorial (codelets sensoriais), responsável pelas entradas e saídas de dados. Subsistema perceptivo (codelets perceptivos e de atenção), responsável por detectar situações especificas, enviar informações ao sistema 2 e gerar dados de percepção na memoria de trabalho. Subsistema motivacional do sistema 1(codelets motivacionais, de humor e emocionais), esses satisfazem uma necessidade ou buscam cumprir um objetivo a longo prazo. E por ultimo temos o sistema de comportamento motor (codelets comportamentais e motor), responsáveis por gerar os comportamentos e saídas, ou ações fazendo assim o agente interagir com o ambiente.

   No sistema 2 é possível encontrar 5 diferentes tipos de memórias (buffer perceptivo, episódico e as memórias episódica, operacional e procedural) e 5 subsistemas. Temos aqui o subsistema motivacional do sistema 2 (formado pelos codelets de metas e de avaliação), responsável por gerar metas para o subsistema de planejamento e buscar cumprir necessidades especificas daquele momento. Subsistema de planejamento (codelet do Soar), responsável por gerar regras, criar planos se baseando em previsões de possíveis futuros, usando o processo de imaginação como avaliador de melhores ações. O subsistema de consciência (codelet de consciência), serve como um avaliador que qualifica um objeto de memória. Subsistema de expectativas (codelet de expectativas), responsável por criar previsões de possíveis futuros a curto prazo e buscar inconsistências nessas previsões. E por fim o subsistema episódico (codelets de atenção, de aprendizagem episódica e de recuperação episódica), aqui são criados, armazenados e recuperados os episódios da memória episódica.

   Continuaremos com a construção e adaptação do MECA para esse trabalho na próxima semana. Mais sobre o MECA pode ser visto nos artigos:
An Overview of the Multipurpose Enhanced Cognitive Architecture (MECA)
An urban traffic controller using the MECA cognitive architecture
The Multipurpose Enhanced Cognitive Architecture (MECA)

    Por fim, foi feita a leitura das documentações tanto da API quando do XML do Project Malmo, possibilitando uma visão mais avançada do sistema. Também foi feita a leitura e o estudo dos projetos disponíveis no GitHub do Malmo e do Marlo. Lembrando que ambas as documentações são documentos de consulta a serem usados durante o desenvolvimento.

Próxima semana:

  • O que há pronto no meca? O que falta ser feito?
  • Controlador manual para um agente no malmo em java.
  • Como será implementada a arquitetura em conjunto com o Malmo?
  • Finalizando a construção do ambiente para experimento.

Referências:


Exemplos de outros projetos que usam o Project Malmo e a linguagem de programação Java:
<http://microsoft.github.io/malmo/blog/BuildBattle/Introduction/>
<https://www.programcreek.com/java-api-examples/?code=carlo-/MalmoAgent/MalmoAgent-master/src/main/JavaAgent.java#>
<https://github.com/deeplearning4j/rl4j/tree/master/rl4j-malmo/src/main/java/org/deeplearning4j/malmo>
<https://github.com/Microsoft/malmo/tree/master/Malmo/test/JavaTests>
<https://github.com/Microsoft/malmo/blob/master/Minecraft/src/main/java/com/microsoft/Malmo/Client/ClientStateMachine.java>
<https://github.com/Microsoft/malmo/tree/master/Malmo/samples/Java_examples>

Project Malmo Doc.
<http://microsoft.github.io/malmo/0.30.0/Documentation>
<http://microsoft.github.io/malmo/0.30.0/Schemas/Mission.html>

Nenhum comentário:

Postar um comentário