• Nenhum resultado encontrado

A figura 3.1 mostra a estrutura geral utilizada para integrar redes neurais e máquinas virtuais, com no mínimo o codificador da entrada sendo neural. Só isso permitiria que o comando de entrada seja qualquer entidade que uma rede neural possa pro- cessar, ou seja, qualquer entidade que possa ser codificada em um tensor (qualquer

Figura 3.1: Estrutura geral da integração entre máquinas virtuais e redes neurais. O codificador transforma o comando em uma representação vetorial. O controlador define a instrução a ser executada para cada comando através do código de opera- ção. A máquina virtual executa a instrução determinada pelo código de operação, salvando o resultado em sua memória para os passos seguintes ou para a saída. array de números com n dimensões/índices) ou lista de tensores. Isso inclui:

• Texto: Normalmente codificado como uma lista de palavras formando uma frase ou oração ou um n-grams (grupos de n elementos consecutivos extraídos do texto), ou ainda uma árvore descrevendo a análise sintática da oração. • Som: Similar a texto, especialmente quando se refere a reconhecimento de

voz. Considera-se uma série temporal de eventos, tipicamente fonemas para voz, em que cada elemento é traduzido como uma série de atributos tais como um conjunto de amplitudes e frequências.

• Imagens: Imagens são tipicamente tensores de três dimensões: coordenada horizontal, coordenada vertical e canal (por exemplo a cor em imagens co- dificadas em RGB). Imagens 3D, produzidas por exemplo por tomografias, adicionam uma coordenada para profundidade.

• Vídeos: Vídeos são similares a imagens adicionando uma coordenada temporal. • Lista de atributos: Ocasionalmente opta-se por não ter uma arquitetura com- pletamente ponta a ponta e um especialista escolhe uma lista de parâmetros que descrevem as partes importantes do problema.

• Saída de outras redes neurais: Redes neurais de múltipla camada criam uma série de representações intermediárias de complexidade progressivamente mai- ores, e cada módulo pode ser integrado em qualquer parte da rede, de modo que as redes anteriores buscarão criar uma representação adequada para que o novo módulo consiga realizar sua tarefa e aproximar-se da solução.

Como lidar com todos esses formatos de entrada é o resultado de muitas déca- das de trabalho no desenvolvimento dos conhecimentos e técnicas em redes neurais e aprendizado de máquina, e, portanto, a capacidade de uma máquina virtual di- ferenciável de facilmente se integrar com todos esses modelos existentes é o que garante sua versatilidade. Essas entradas são processadas pelos seguinte módulos, até produzir uma saída que é o resultado da execução de um algoritmo criado:

• Codificador da entrada: Dentro do conceito de aprendizado profundo e redes de múltiplas camadas, o codificador é o módulo que cria uma representação mais compacta e eficaz da entrada para os módulos adiante. Por exemplo codificar uma pergunta (uma série de palavras) em uma representação vetorial de forma similar à arquitetura de Encoder-Decoder. No caso de entradas suficientemente simples o próprio interpretador pode fazer sua codificação.

• Interpretador de comandos: É o responsável por gerar os programas, produ- zindo o Código de Operação (ou opcode) a partir de cada comando de entrada e de uma representação do contexto atual do programa na forma do Estado do programa. Esse código de operação define unicamente a tarefa que a máquina virtual irá executar, incluindo qual operação (ex: soma, comparação, copiar dados...), quais seus argumentos e onde guardar os resultados (manipulação da memória, entrada e saída) e qualquer controle de fluxo (condicionais, laços). No contexto de redes neurais, esse módulo é chamado de Controlador.

• Estado do programa: É um estado mantido pelo controlador que indica o contexto atual do programa. É normalmente formado por uma combinação da codificação das escolhas anteriores do controlador, das entradas passadas e em alguns modelos algumas informações da máquina virtual. Esse estado não possui, no entanto, acesso aos dados na memória da máquina virtual, pois deseja-se que sejam criados algoritmos genéricos que não dependam dos dados específicos (por exemplo um somador não deveria se preocupar com os valores dos números que está somando desde que sejam válidos).

• Unidade de execução das instruções: É o módulo responsável por manipular a memória da máquina virtual, executando cada correspondente operação sobre os correspondentes setores da memória. Ao contrário dos demais módulos, a máquina virtual tipicamente não possui qualquer peso a ser treinado, porém é necessário que ela seja diferenciável para a criação de um modelo de ponta a ponta (que pode ser treinado recebendo apenas as entradas e a saída do programa desejado).

• Memória Interna + Externa: A manutenção do estado da máquina virtual, similar aos registradores e memória de um processador ou às variáveis em uma

linguagem de programação. Ela pode ser completamente interna ao modelo, com todos os valores gerados pela própria rede, ou externa, sendo parte da entrada como por exemplo um vetor de números para se ordenar. Essa entrada é diferente da entrada do controlador: essa é uma descrição do programa, enquanto aquela são seus argumentos. A saída dos modelos é tipicamente o estado final da memória.

Usando o exemplo 2, o codificador seria responsável por, primeiramente, trans- formar cada palavra em sua representação vetorial via, por exemplo, word2vec. Em seguida deve combinar todas as representações vetoriais de palavras em uma repre- sentação única para cada comando (nesse exemplo cada comando deve ser separado do resto do texto através de uma etapa de pré-processamento, pois existem vários comandos em uma só frase). A etapa de gerar uma representação para o comando poderia ser feito de forma similar ao codificador do encoder-decoder com ou sem atenção. A partir da representação do comando, e do estado do programa do con- trolador (tipicamente o seu próprio estado oculto sendo uma rede recorrente), o interpretador de comandos gera o código de operação para a máquina virtual.

O código de operação define qual operação a máquina virtual irá executar e com quais argumentos. No exemplo de comando "ponha 20 reais de crédito", a operação deve ser adição e as variáveis "saldo atual", mantida na sua memória interna ou externa, e "20", extraído do comando. possivelmente durante o pré-processamento. Após a máquina virtual atualizar sua memória com o resultado da operação, o processo se reinicia para o próximo comando, ou a saída final é extraída da memória no caso de término do algoritmo.

Ter só o codificador na figura 3.1 como uma Rede Neural significa utilizar modelos neurais apenas para processar a entrada e usar as ferramentas tradicionais para trabalhar com essa nova entrada. Por exemplo construir uma representação das palavras via word2vec e usar algoritmos comuns ou ferramentas matemáticas para processá-los. Apesar de úteis, elas requerem que já se saiba a solução do problema para cada caso, já que não há aprendizado quanto à construção do algoritmo que resolve o problema.

Ter até controlador como rede neural já entra no domínio dos Programadores Neurais, Redes Neurais que produzem algoritmos observáveis através de códigos de operação, ao contrário das redes recorrentes tradicionais que também produzem algoritmos inteiramente dentro de uma caixa-preta. Os programadores neurais po- dem ser divididos em dois grupos: aqueles que treinam o controlador separado da máquina virtual e aqueles que treinam o sistema de ponta a ponta.

3.2.1

Treinar a rede neural e a máquina virtual separada-

mente.

Da forma mais simples, podemos ter a rede neural sendo treinada de forma com- pletamente independente da máquina virtual. Para tanto treina-se a rede neural de forma supervisionada, através de uma base de dados manualmente produzida com a entrada sendo os comandos em sua forma original não estruturada e a saída com um formato compatível com a máquina virtual a ser utilizada.

A vantagem dessa abordagem é que as ferramentas utilizadas não possuem ne- nhuma restrição de execução: programas de manipulação algébrica, programação lógica e até banco de dados e buscas na web são viáveis, já que a máquina virtual não é parte da rede a ser treinada. Para sistemas que não podem ser escritos de forma diferenciável essa é a única opção.

A desvantagem é a necessidade de construir um banco de exemplos para treino novo, e tipicamente com muitas amostras para qualquer problema não trivial, que ficará sempre restrito a uma ferramenta específica. Qualquer mudança na interface da ferramenta exigirá que o banco de exemplos seja reescrito e que a rede seja treinada novamente. Cada amostra do banco também será consideravelmente mais complexa pois quem criará precisará ter domínio da ferramenta, e em casos com múltiplas instruções é necessário escrever um programa inteiro para cada exemplo em vez da saída final.

3.2.2

Treinar o sistema completo ponta a ponta

O sistema treinado ponta a ponta (end-to-end) tem como vantagem a maior flexibi- lidade. As bases de exemplos não mais precisam explicar como realizar a tarefa, mas apenas dizer qual o resultado desejável e deixar para a rede decidir a melhor forma de resolvê-lo. Dessa forma os exemplos não só são mais simples, mas também não dependem de que quem os crie saiba resolver a tarefa com as ferramentas escolhidas. Assim, é possível inclusive que a rede produza novas soluções para problemas que os próprios desenvolvedores das ferramentas nunca planejaram. Torna-se possível também integrar diretamente o sistema a uma rede neural ainda mais profunda, que utiliza a resposta para processamentos ainda mais complexos e treinar o processo todo junto em uma única base de dados. E se o usuário quiser mudar a máquina virtual basta retreinar na mesma base de dados.

Dentro dessa abordagem, existem ainda duas possibilidades no que diz respeito a como treinar a rede. A primeira forma é o treinamento por reforço. O treinamento por reforço tem a vantagem da primeira abordagem em termos de não ter restrições de implementação para a máquina virtual, podendo utilizar até uma pesquisa na internet por exemplo. A rede neural irá produzir um código de operação que será

repassado à máquina virtual, que por sua vez retornará o resultado de seu proces- samento. Se o resultado for correto, os pesos da rede serão ajustados para favorecer essa instrução. Caso contrário. para rejeitar essa instrução. O problema no entanto é que sistemas de reforço são extremamente lentos de treinar, especialmente se o espaço de busca for muito grande (como em programas relativamente longos) e as soluções corretas muito raras em comparação, forçando a rede a errar muitas vezes antes de ter qualquer progresso.

A segunda forma, e a que nosso modelo foca, é o treinamento supervisionado. Como explicado, usa-se um algoritmo de otimização como gradiente descendente para minimizar o erro na saída. Como o gradiente descendente utiliza o gradiente, é necessário que a função seja diferenciável em toda sua extensão, o que restringe consideravelmente a implementação da máquina virtual. Felizmente, boa parte das operações algébricas básicas são diferenciáveis (somas, produtos, exponenciação, e aproximações de demais na forma de séries), enquanto operações lógicas mais complexas, tais como predicados, podem ser implementadas de forma aproximada.