Este projeto foi originalmente planejado para um curso de IA na Universidade de Sofia. Durante a sua execução, fiquei com pouco tempo e não consegui implementar todas as ideias que tinha, mas pretendo continuar trabalhando nisso... e peguei o tema para minha tese de mestrado, usando Transformadores T5 para gerar perguntas- responda pares junto com distratores . Confira no repositório Question-Generation-Transformers.
A abordagem para identificar palavras-chave usadas como respostas alvo foi aceita na conferência RANLP2021 - Generating Answer Candidates for Quizzes and Answer-Aware Question Generators.
A ideia é gerar respostas de múltipla escolha a partir de texto, dividindo esse problema complexo em etapas mais simples:
Para evitar conflitos com pacotes python de outros projetos, é uma boa prática criar um ambiente virtual no qual os pacotes serão instalados. Se você não quiser isso, você pode pular os próximos comandos e instalar diretamente o arquivo requirements.txt.
Crie um ambiente virtual:
python -m venv venv
Entre no ambiente virtual:
Windows:
. .venvScriptsactivate
Linux ou MacOS
source .venvScriptsactivate
Instale o ipython dentro do venv:
ipython kernel install --user --name=.venv
Instale o jupyter lab dentro do venv:
pip install jupyterlab
pip install -r .requirements.txt
jupyter lab
Antes de poder fazer qualquer coisa, queria entender mais sobre como as perguntas são feitas e que tipo de palavras são as respostas.
Usei o conjunto de dados SQuAD 1.0 que contém cerca de 100.000 perguntas geradas a partir de artigos da Wikipedia.
Você pode ler sobre os insights que encontrei no bloco de notas Jupyter de Exploração de Dados .
Minha suposição era que as palavras do texto seriam ótimas respostas para perguntas . Tudo que eu precisava fazer era decidir quais palavras, ou frases curtas, são boas o suficiente para se tornarem respostas.
Resolvi fazer uma classificação binária de cada palavra do texto. spaCy realmente me ajudou com a marcação de palavras.
Eu praticamente precisava criar todo o conjunto de dados para a classificação binária. Extraí cada palavra ininterrupta dos parágrafos de cada pergunta no conjunto de dados SQuAD e adicionei alguns recursos como:
E o rótulo éResposta - se a palavra extraída do parágrafo é a mesma e no mesmo lugar que a resposta da pergunta do SQuAD.
Alguns outros recursos, como pontuação TF-IDF e semelhança de cosseno com o título , seriam ótimos, mas não tive tempo de adicioná-los.
Além disso, cabe à nossa imaginação criar novos recursos - talvez seja no início, meio ou final de uma frase, informações sobre as palavras que a cercam e muito mais... Embora antes de adicionar mais recursos, seria bom ter uma métrica para avaliar se o recurso será útil ou não.
Achei o problema semelhante à filtragem de spam , onde uma abordagem comum é marcar cada palavra de um e-mail como proveniente de um e-mail de spam ou não.
Usei o algoritmo Gaussian Naive Bayes do scikit-learn para classificar cada palavra se é uma resposta.
Os resultados foram surpreendentemente bons – numa rápida olhada, o algoritmo classificou a maioria das palavras como respostas. Aqueles que não eram de fato inadequados.
O legal do Naive Bayes é que você obtém a probabilidade de cada palavra. Na demonstração, usei isso para ordenar as palavras da resposta mais provável para a menos provável.
Outra suposição que tive foi que a sentença de uma resposta poderia facilmente ser transformada em uma pergunta . Apenas colocando um espaço em branco na posição da resposta no texto eu recebo uma pergunta "cloze" (frase com espaço em branco para a palavra que falta)
Resposta: Oxigênio
Pergunta: _____ é um elemento químico com símbolo O e número atômico 8.
Decidi que não valia a pena transformar a pergunta cloze em uma frase mais interrogativa, mas imagino que isso poderia ser feito com uma rede neural seq2seq , da mesma forma que o texto é traduzido de um idioma para outro.
A parte acabou muito bem.
Para cada resposta eu gero as palavras mais semelhantes usando embeddings de palavras e similaridade de cosseno .
A maioria das palavras é adequada e pode facilmente ser confundida com a resposta correta. Mas há alguns que obviamente não são apropriados.
Como não tinha um conjunto de dados com respostas incorretas, optei por uma abordagem mais clássica.
Removi as palavras que não eram da mesma classe gramatical ou da mesma entidade nomeada da resposta e adicionei mais contexto à pergunta.
Gostaria de encontrar um conjunto de dados com respostas de múltipla escolha e ver se consigo criar um modelo de ML para gerar melhores respostas incorretas.
Depois de adicionar um projeto de demonstração, as perguntas geradas não são adequadas para serem colocadas em uma sala de aula instantaneamente, mas também não são ruins.
O legal é a simplicidade e modularidade da abordagem, onde você pode descobrir onde está indo mal ( digamos, é a classificação de verbos ) e corrigir isso.
Ter uma rede neural complexa ( como fazem todos os artigos sobre o assunto ) provavelmente será melhor, especialmente na época em que vivemos. Mas a melhor coisa que descobri sobre essa abordagem é que ela é como uma porta de entrada para um engenheiro de software , com sua mentalidade de engenharia de software, entrar no campo da IA e ver resultados significativos.
Acho este tema bastante interessante e com muito potencial. Provavelmente continuaria trabalhando nesta área.
Até me matriculei em um Master of Data Mining e provavelmente farei alguns projetos semelhantes. Vou vincular qualquer coisa útil aqui.
Já dediquei mais tempo para terminar o projeto, mas gostaria de transformá-lo mais em um tutorial sobre como entrar no campo da IA e ao mesmo tempo ter a capacidade de estendê-lo facilmente com novos recursos personalizados.
Atualização - 29.12.19: O repositório se tornou bastante popular, então adicionei um novo notebook ( Demo.ipynb ) que combina todos os módulos e gera perguntas para qualquer texto. Reordenei os outros notebooks e documentei o código (um pouco melhor).
Atualização - 09.03.21: Adicionado um arquivo requisitos.txt com instruções para executar um ambiente virtual e corrigido o bug com ValueError: operandos não puderam ser transmitidos junto com formas (230, 121) (83, )
Também comecei a trabalhar na minha tese de mestrado com um tópico semelhante de Geração de Perguntas.
Atualização - 27.10.21: Carreguei o código da minha tese de mestrado no repositório Question-Generation-Transformers. Eu recomendo fortemente que você dê uma olhada.
Além disso, a abordagem usando um classificador para escolher os candidatos às respostas foi aceita como artigo de estudante na conferência RANLP2021. Papel aqui.