Continuando o post anterior, como o leitor deve ter observado, nosso objetivo não é fazer perguntas específicas, mas preparar o corpus e desenvolver ferramentas para que várias diferentes perguntas possam ser respondidas. Mas vamos à uma demanda por extração de informação que nos parece óbvia: relações familiares. Imagine tentarmos responder questões como o número de famílias que se perpetuam na política brasileira nas últimas décadas.
O que então precisamos responder é o que esperamos de saída ao executarmos ferramentas de NLP nos verbetes do DHBB. No que segue, assumo que desejamos construir um grafo onde nós são pessoas e arestas representem relações familiares entre as pessoas, rotuladas pelas relações. A idéia seria construir este grafo a partir dos verbetes. Diversas consultas sobre este grafo seriam possíveis e, direta ou indiretamente, as respostas serviriam de dados para sua reportagem. Alguém consegue pensar em algo mais específico ou mais simples?
Construir o grafo que idealizei acima envolve: 1) identificação de nomes próprios de pessoas; 2) identificação de substantivos ou adjetivos relacionados à relações familiares; 3) identificação de padrões sintáticos que identifiquem relações familiares explicitas ou implícitas mencionadas nos verbetes.
Existem algumas tarefas que precisamos realizar: NER (named e entities recognition), NEC (named entities classification: pessoa ou instituição ou lugar etc) e desambiguação de nomes. Para identificar as entidades nomeadas o problema parece simples mas sempre temos casos mais complicados. Por exemplo, podemos marcar uma entidade ou duas na sentença 1, levando as anotação de 2 ou 3:
Note que identificar, classificar e disambiguar não necessariamente são tarefas separadas. Tipicamente a desambiguação significa mapear uma string no texto à uma entrada em uma base de dados. Obviamente a existência de uma lista de nomes de políticos (obtida de sites do governo), pode ajudar, mas em geral usamos recursos mais abrangentes como DBPedia, Wkidata, Yago etc. Tomando a decisão por 2, uma ligação possível seria com a página. A existência da entrada na Wikipedia para `Universidade Federal do Rio de Janeiro’ é uma evidência de que a anotação 2 seria mais adequada. E obviamente se desambiguamos uma entrada X contra um DB que já nos diz o tipo de X também estamos também fazendo a classificação, os problemas se misturam.
A identificação dos nomes pode ser feita diretamente, marcando no texto de entrada segmentos que correspondem a nomes ou como uma camada de anotação acima das árvores sintáticas. Penso que combinar as abordagens sempre ajuda muito a identificarmos errors de processamento. Usando o WKS já temos uma primeira versão de anotações.
Uma das coisas que está na nossa lista de tarefas é verificar as anotações sintáticas a partir de listas de nomes de entidades. Sequencias de tokens partes de um nome deveriam estar todos em uma subárvore da arvore sintática. Esta verificação nos ajudaria a melhorar as análises sintáticas que já temos. Como disse acima, listas de nomes de pessoas, instituições ou lugares podem ser obtidas de sites do governo, das bases que mencionei acima ou usar as anotações que já temos.
Feita a identificação de nomes, podemos partir para os termos de parentesco. Um bom ponto de partida seria a nossa OpenWordnet-PT. Uma revisão da cobertura dela para estes termos seria excelente. Descobrir o que temos e o que está faltando. Assim poderíamos usar a estrutura da WN para generalizar as buscas nos textos por termos relacionados à relações familiares, ao invés de enumerar todos os termos, poderíamos usar as relações semânticas da WN para perguntar por termos e seus hipônimos, por exemplo. Entender a modelagem destes termos na OWN-PT seria o ponto de partida e este assunto é bem interessante por si só:
Uma busca no DHBB pelos termos mais ‘óbvios’ que me ocorreram ajuda a termos uma idéia do que devemos encontrar no DHBB. Esta é uma busca preliminar, não está cobrindo o DHBB inteiro e claramente o analisador sintático ainda comete errors e não faz análises consistentes. Também podemos ter uma idéias da quantidade de sentenças que mencionam estes termos:
% awk '$0 ~ /text =/ {sent = $0} $3 ~ /^(irmã|irmão|pai|mãe|tio|tia|bisavô|bisavó|primo|prima|avô|avó|sobrinho|sobrinha|cunhado|cunhada|parente)$/ {print sent}' *.conllu | wc -l
5812
Em seguida, temos a identificação das possíveis relações de parentesco entre pessoas que possam ser identificadas nos textos. Obviamente, muitas vezes os autores podem apenas mencionar a existência de um parente mas não nomea-lo. Nos exemplos abaixo, note que o nome do verbetado (pessoa que o verbete descreve) não aparece explicitamente nas sentenças.
% awk '$0 ~ /text =/ {sent = $0} $3 ~ /^(irmã|irmão|pai|mãe|tio|tia|bisavô|bisavó|primo|prima|avô|avó|sobrinho|sobrinha|cunhado|cunhada|parente)$/ {print sent}' *.conllu | head
Quando olhamos para os tokens que são termos de relações familiares e sua relação com os demais tokens das sentenças, temos 299 casos de ligações sintáticas diferentes, comprovando o que vemos nos exemplos acima, uma possível grande diversidade de padrões sintáticos usados.
% awk '$3 ~ /^(irmã|irmão|pai|mãe|tio|tia|bisavô|bisavó|primo|prima|avô|avó|sobrinho|sobrinha|cunhado|cunhada|parente)$/ {print $2,$4,$8}' *.conllu | sort | uniq -c | sort -nr | wc -l
299
Os 10 casos mais frequentes são os abaixo. O simbolo nsubj
indica
sujeito da sentença, nmod
indica que a palavra ‘pai’ está
modificando outro substantivo, flat:name
indica que o termo é parte
de um nome etc.
% awk '$3 ~ /^(irmã|irmão|pai|mãe|tio|tia|bisavô|bisavó|primo|prima|avô|avó|sobrinho|sobrinha|cunhado|cunhada|parente)$/ {print $2,$4,$8}' *.conllu | sort | uniq -c | sort -nr | head
649 pai NOUN nsubj
394 pai NOUN nmod
370 irmão NOUN nsubj
309 Sobrinho PROPN flat:name
254 pai NOUN nsubj:pass
211 irmão NOUN appos
177 irmão NOUN nmod
170 irmão NOUN nsubj:pass
163 avô NOUN nsubj
144 tio NOUN nsubj
Isto indica que embora possamos escrever padrões para extração de informações das árvores ou diretamente do texto das sentenças, o trabalho poderá ser bem grande. Uma idéia é construir abstrações nestas estruturas gerando representação mais semânticas para serem analisadas. Outra idéia seria usar técnicas de aprendizado de máquina tanto na identificação de termos para relações familiares quando na extração de relações familiares. Existem vários artigos explorando estas técnicas.
Iniciantes na área de PLN costumam encontrar bibliotecas como NLTK, e acreditar que usando a biblioteca poderão processar textos facilmente. De fato, esta particular biblioteca é bem documentada e descreve no capítulo 7 algumas abordagens para extração de informações. Mas muito dos passos mencionados no texto assumem modelos já treinados, no inglês. E mesmo que existam modelos para Português, nossos experimentos mostram que no DHBB os resultados contém muitos erros em todas as etapa: segmentação de sentenças, pos tagging, identificação de nomes etc. Por isso nosso projeto.
Para interessados na área de processamento de texto, sugiro a leitura do livro ainda em edição https://web.stanford.edu/~jurafsky/slp3/.