Aula 35 – TensorFlow – Keras – Redes Neurais – RNN Chatbot

Aula 35 – TensorFlow – Keras – Redes Neurais – RNN Chatbot

Voltar para página principal do blog

Todas as aulas desse curso

Aula 34                        Aula 36

TensorFlow - Keras - Redes Neurais

TensorFlow – Keras – Redes Neurais

Pacote Programador Fullstack

Pacote Programador Fullstack

Redes Sociais:

facebook              

 

Site das bibliotecas

Tensorflow

Keras

Cursos Gratuitos

Digital Innovation

Quer aprender python3 de graça e com certificado? Acesse então:

workover

Para aprender Python do zero, além do curso aqui do código fluente, eu indico também esse curso do Python Academy.

Python Academy

Python Academy

Meus link de afiliados:

Hostinger

Digital Ocean

One.com

Canais do Youtube

Toti

Backing Track / Play-Along

Código Fluente

Putz!

Vocal Techniques and Exercises

Fiquem a vontade para me adicionar ao linkedin.

PIX para doações

PIX Nubank

PIX Nubank

Notebook da aula

Base de dados: human_text.txt e o robot_text.txt


Aula 35 – TensorFlow – Keras – Redes Neurais – RNN Chatbot

Aula baseada principalmente no artigo: Generative chatbots using the seq2seq model! de Dhruvil Shah.

Abordagem seq2seq para criar chatbots generativos.

Existem várias tarefas que podem ser resolvidas usando a modelagem seq2seq: resumo de texto, reconhecimento de fala, legenda de imagem e vídeo e resposta a perguntas.

Também pode ser usado em genôma para modelagem de sequências de DNA.

Na prática, são 2 redes neurais recorrentes bem simples que compartilham uma mesma camada oculta e não tem camada de ativação, só uma célula GRU ou LSTM que realiza o processamento.

O seq2seq é considerado um Modelo de Linguagem Condicional, porque a saída depende do contexto identificado pela rede na entrada, e também das palavras anteriores já previstas como saída, para então prever a próxima palavra da sentença de saída.

O que o modelo prevê é: P(y|x)

Ou seja, dada a sentença x como entrada, qual a probabilidade de gerar a sentença de saída y?

Dada a entrada x, eu gero o primeiro token, y1, agora, dado a entrada x e mais o primeiro token gerado, o y1. Qual a probabilidade de gerar o segundo token, o y2?

E assim por diante:

P(x|y) = P(y1|x)
=> P(y2 | y1, x)
=> P(y3 | y1, y2, x) …
=> P(yT | y1, …, yT – 1, x)

Um modelo seq2seq tem duas partes: um codificador e um decodificador.

Ambos trabalham separadamente e se unem para formar um grande modelo de rede neural.

O seq2seq é também chamado de modelo codificador-decodificador.

Utiliza Long Short Term Memory-LSTM para geração de texto a partir do corpus de treinamento, ou seja, a base de dados.

Como o modelo seq2seq funciona?

Codificador

O codificador está na extremidade de alimentação da rede, ele entende a sequência e reduz a dimensão da sequência de entrada.

A sequência tem um tamanho fixo conhecido como vetor de contexto.

Esse vetor de contexto atua como entrada para o decodificador, que gera uma sequência de saída ao atingir o token final.

Essa arquitetura pode lidar com sequências de entrada e saída de comprimento variável.

Decodificador

Se você usar LSTM para o codificador, use o mesmo para o decodificador.

Você pode dizer que o decodificador está em um “estado consciente“.

Ele sabe quais palavras você gerou até agora e qual era o estado oculto anterior.

A primeira camada do decodificador é inicializada usando o vetor de contexto ‘C’ da rede do codificador para gerar a saída.

Em seguida, um token especial é aplicado no início para indicar a geração de saída.

Aplica um token semelhante no final.

A primeira palavra de saída é gerada pela execução das camadas LSTM empilhadas.

Uma função de ativação SoftMax se aplica à última camada.

Seu trabalho é introduzir a não linearidade na rede.

Agora esta palavra é passada pelas camadas restantes e a sequência de geração é repetida.

Vários fatores dependem da melhoria da precisão do modelo codificadordecodificador.

Os hiperparâmetros como otimizadores, perda de entropia cruzada, taxa de aprendizado, etc. Desempenham um papel importante na melhoria do desempenho do modelo.

Exemplo

No exemplo abaixo, é feita uma distribuição de probabilidades de sequências de saída, maximizando a probabilidade de uma sequência alvo como saída, em função de uma determinada sequência anterior recebida como entrada.

Ele prevê uma palavra dada na entrada do usuário e em seguida, cada uma das próximas palavras é prevista usando a probabilidade de ocorrência dessa palavra.

Modelo encoder-decoder

Modelo encoder-decoder

O codificador emite um vetor de estado final (memória) que se torna o estado inicial para o decodificador.

Usamos um método chamado de aprendizado forçado, ou teacher forcing, para treinar o decodificador, que permite prever as seguintes palavras em uma sequência alvo, dada as palavras anteriores.

Como mostrado acima, os estados são passados através do codificador, para cada camada do decodificador.

Hi‘, ‘how‘, ‘are‘ e ‘you‘ são chamados de tokens de entrada, enquanto ‘i‘, ‘am‘ e ‘fine‘ são chamados de tokens alvo.

A probabilidade do token ‘am‘ depende das palavras anteriores e dos estados do codificador.

Estamos adicionando o token  ‘<END>‘ para que o decodificador saiba quando parar.

Construindo um chatbot generativo do zero

A primeira tarefa que teremos que fazer é pré-processar o conjunto de dados.

Pré-processamento do conjunto de dados

Os dados que iremos usar contém respostas humanas (human_text.txt) e respostas de bot(robot_text.txt).

2363 entradas para cada um.

Primeiro, teremos que limpar nosso corpus com a ajuda de Expressões Regulares.

Em seguida, precisaremos fazer pares de resposta humana-bot, para que possamos treinar nosso modelo seq2seq.

Faremos essas tarefas conforme mostrado abaixo.


import re
import random
data_path = "human_text.txt"
data_path2 = "robot_text.txt"
# Defining lines as a list of each line
with open(data_path, 'r', encoding='utf-8') as f:
  lines = f.read().split('\n')
with open(data_path2, 'r', encoding='utf-8') as f:
  lines2 = f.read().split('\n')
lines = [re.sub(r"\[\w+\]",'hi',line) for line in lines]
lines = [" ".join(re.findall(r"\w+",line)) for line in lines]
lines2 = [re.sub(r"\[\w+\]",'',line) for line in lines2]
lines2 = [" ".join(re.findall(r"\w+",line)) for line in lines2]
# grouping lines by response pair
pairs = list(zip(lines,lines2))
#random.shuffle(pairs)

Vale a pena esmiuçar um pouquinho as linhas das regex.

Regex

re.sub()

O re.sub() pode recebe os seguintes parâmetros: re.sub(pattern, repl, string, count=0, flags=0)

Retorna a string obtida, substituindo as ocorrências não sobrepostas da extremidade esquerda do pattern na string pela substituição repl.

Se o padrão não for encontrado, string será retornado inalterado.

O repl pode ser uma string ou uma função, se for uma string, qualquer escape de contrabarra será processado.

O r significa que a string será tratada como string bruta.

Ao contrário de uma string normal, uma string bruta trata as barras invertidas ( \ ) como caracteres literais.

Strings brutas são úteis quando você lida com strings que possuem muitas barras invertidas, por exemplo, expressões regulares ou caminhos de diretório.

Ou seja, \n é convertido em um único caractere de nova linha, \r é convertido em um retorno e assim por diante.

O \[ e depois no final da string pattern \], é para poder representar os caracteres especiais [ e ] e garantir que algumas linhas, como: [start], [voice], etc. Passem na correspondência.

\w – corresponde a quando não é alfa numérico, e o + conhecido como indicador de ocorrência (ou operador de repetição), indica uma ou mais ocorrências (1+) da subexpressão anterior.

Nesse caso, [a-zA-Z]+ ou seja, \w+ corresponde a um ou mais dígitos.

re.findall()

O re.findall() retorna todas as correspondências não sobrepostas do padrão na string, como uma lista de strings ou tuplas.

A string é verificada da esquerda para a direita e as correspondências são retornadas na ordem encontrada.

Correspondências vazias são incluídas no resultado.

O resultado depende do número de grupos de captura no padrão.

Se não houver grupos, retorne uma lista de strings que correspondem a todo o padrão.

Se houver exatamente um grupo, retorne uma lista de strings correspondentes a esse grupo.

Se vários grupos estiverem presentes, retorne uma lista de tuplas de strings correspondentes aos grupos.

Grupos sem captura não afetam a forma do resultado.

Depois de criar os pares, também podemos embaralhá-los antes do treino.

Nossos pares ficarão assim agora:


[('hi', 'hi there how are you'), ('oh thanks i m fine this is an evening in my timezone', 'here is afternoon'),...]

Aqui, ‘hi‘ é a sequência de entrada e ‘hi there how are you‘ é uma sequência de saída ou alvo.

Por essa aula é só, nos vemos na próxima, valeu \o/.


Voltar para página principal do blog

Todas as aulas desse curso

Aula 34                        Aula 36

Meu github:

https://github.com/toticavalcanti

Novamente deixo meus link de afiliados:

Hostinger

Digital Ocean

One.com

Obrigado, até a próxima e bons estudos. 😉

 

About The Author
-

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>