Aula 38 – TensorFlow – Keras – Redes Neurais – RNN Chatbot
Aula 38 – TensorFlow – Keras – Redes Neurais – RNN Chatbot
Voltar para página principal do blog
Todas as aulas desse curso
Aula 37 Aula 39
Redes Sociais:
Site das bibliotecas
Tensorflow
Keras
Cursos Gratuitos
Digital Innovation
Quer aprender python3 de graça e com certificado? Acesse então:
workover
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
Notebook da aula
Base de dados: human_text.txt e o robot_text.txt
Aula 38 – TensorFlow – Keras – Redes Neurais – RNN Chatbot
O artigo original seguido para essa aula é: Generative chatbots using the seq2seq model! de Dhruvil Shah.
Testando o modelo
Por fim, criaremos uma função que aceita nossas entradas de texto e gera uma resposta usando o codificador e o decodificador que criamos.
O codificador processa cada token na sequência de entrada.
Ele tenta agrupar todas as informações sobre a sequência de entrada em um vetor de comprimento fixo, ou seja, o ‘vetor de contexto’.
Depois de passar por todos os tokens, o codificador passa esse vetor para o decodificador.
Então, no exemplo, a função decode_response(), recebe uma matriz NumPy que representa a sentença de texto de entrada, o que o usuário digitou na caixa de diálogo, e obtém a resposta gerada.
O que acontece na função decode_response() é o seguinte:
1.) Recupera os estados de saída do codificador
2.) Passa os estados de saída para o decodificador que é o estado oculto inicial do decodificador para decodificar a frase palavra por palavra
3 .) Atualiza o estado oculto do decodificador após decodificar cada palavra para que possamos usar palavras previamente decodificadas para ajudar a decodificar novas
Para quando encontra o token ‘<END>‘ que foi adicionado às sequências de destino na tarefa de pré-processamento, ou quando atinge o comprimento máximo da sequência.
A gente pegou esse tamanho máximo com essas linhas de código na parte do Training setup:
max_encoder_seq_length = max([len(re.findall(r”[\w’]+|[^\s\w]”, input_doc)) for input_doc in input_docs])
max_decoder_seq_length = max([len(re.findall(r”[\w’]+|[^\s\w]”, target_doc)) for target_doc in target_docs])
def decode_response(test_input):
#Getting the output states to pass into the decoder
states_value = encoder_model.predict(test_input)
#Generating empty target sequence of length 1
target_seq = np.zeros((1, 1, num_decoder_tokens))
#Setting the first token of target sequence with the start token
target_seq[0, 0, target_features_dict['']] = 1.
#A variable to store our response word by word
decoded_sentence = ''
stop_condition = False
while not stop_condition:
#Predicting output tokens with probabilities and states
output_tokens, hidden_state, cell_state = decoder_model.predict([target_seq] + states_value)
#Choosing the one with highest probability
sampled_token_index = np.argmax(output_tokens[0, -1, :])
sampled_token = reverse_target_features_dict[sampled_token_index]
decoded_sentence += " " + sampled_token
#Stop if hit max length or found the stop token
if (sampled_token == '<END>' or len(decoded_sentence) > max_decoder_seq_length):
stop_condition = True
#Update the target sequence
target_seq = np.zeros((1, 1, num_decoder_tokens))
target_seq[0, 0, sampled_token_index] = 1.
#Update states
states_value = [hidden_state, cell_state]
return decoded_sentence
Juntando tudo — Chatbot Generativo
Vamos criar uma classe que contém métodos necessários para executar um chatbot.
class ChatBot:
negative_responses = ("no", "nope", "nah", "naw", "not a chance", "sorry")
exit_commands = ("quit", "pause", "exit", "goodbye", "bye", "later", "stop")
#Method to start the conversation
def start_chat(self):
user_response = input("Hi, I'm a chatbot trained on random dialogs. Would you like to chat with me?\n")
if user_response in self.negative_responses:
print("Ok, have a great day!")
return
self.chat(user_response)
#Method to handle the conversation
def chat(self, reply):
while not self.make_exit(reply):
reply = input(self.generate_response(reply)+"\n")
#Method to convert user input into a matrix
def string_to_matrix(self, user_input):
tokens = re.findall(r"[\w']+|[^\s\w]", user_input)
#max_encoder_seq_length is the number of matrix rows and num_encoder_tokens is the number of matrix cols
user_input_matrix = np.zeros(
(1, max_encoder_seq_length, num_encoder_tokens),
dtype='float32')
for timestep, token in enumerate(tokens):
#input_features_dict[token] represent the col in array row of the matrix
#in other words, the position in inner array.
if token in input_features_dict:
user_input_matrix[0, timestep, input_features_dict[token]] = 1.
return user_input_matrix
#Method that will create a response using seq2seq model we built
def generate_response(self, user_input):
input_matrix = self.string_to_matrix(user_input)
chatbot_response = decode_response(input_matrix)
#Remove and tokens from chatbot_response
chatbot_response = chatbot_response.replace("",'')
chatbot_response = chatbot_response.replace("",'')
return chatbot_response
#Method to check for exit commands
def make_exit(self, reply):
for exit_command in self.exit_commands:
if exit_command in reply:
print("Ok, have a great day!")
return True
return False
chatbot = ChatBot()
Todos os métodos são autoexplicativos no código acima.
Escopo futuro vs limitação
Aqui usamos um conjunto de dados muito pequeno e obtivemos uma precisão de cerca de 20%.
Testei localmente usando o dobro da amostragem, ao invés de 400 amostras, usei 800 amostras da base de dados.
Primeiro tentei usar 2000 amostras, mas, cada época demorava muito pra terminar, baixei para 800 amostras, só que o resultado da precisão não alterou, ficou em cerca de 20% mesmo.
A limitação de usar essa abordagem é que para criar chatbots generativos, precisamos de conjuntos de dados bem grandes e muito poder computacional para treinar a rede.
Para modelos como o do google translator, por exemplo, são investidos milhões de dólares em processamento computacional para o treinamento das redes.
Conclusão
A arquitetura de domínio fechado se concentra na seleção de respostas de um conjunto de respostas predefinidas, a arquitetura de domínio aberto, permite realizar geração de texto ilimitada.
Os sistemas de domínio fechado usam classificação de intenção, identificação de entidade e seleção de resposta.
Já um chatbot de domínio aberto, ou seja, um modelo generativo, em vez de selecionar respostas prontas, ele gera a resposta palavra por palavra, permitindo novas combinações de linguagem.
Nas indústrias, algumas empresas utilizam os chatbots de domínio fechado para garantir que o usuário sempre receba a resposta predefinida certa.
O domínio Natural Language Processing-PNL está desenvolvendo e treinando redes neurais para aproximar a abordagem que o cérebro humano faz para o processamento de linguagem.
Essa estratégia de aprendizado profundo permite que os computadores manipulem a linguagem humana com muito mais eficiência.