Universidade de São Paulo Mestrado em Ciência da Computação Instituto de Matemática e Estatística Disciplina MAC5725 – Lingüística Computacional Análise Sintática de Frases utilizando Gramáticas Livres de Contexto Probabilísticas Christian Danniel Paz Trillo [email protected] 17 de Outubro de 2004 Resumo 1 Introdução Lingüística Computacional é o estudo científico da linguagem desde uma perspectiva computacional. A análise de frases válidas numa linguagem natural é uma sub-área de interesse importante porque seu desenvolvimento ajuda o desenvolvimento de outras sub-áreas como a sumarização automática de textos, recuperação de informação, reconhecimento de diálogo, e outras. Os problemas presentes na análise sintática de frases são: • Dada uma sentença em linguagem natural e uma gramática descrevendo a estrutura da linguagem, reconhecer se ela é gramatical ou não. • Dadas as mesmas entradas, além de reconhecer se a sentença é gramatical, devolver a(s) estrutura(s) que faz(em) ela ser gramatical, i.e. sua árvore sintática. É possível atribuir a essas árvores uma probabilidade extraída também da gramática indicando quão provável é essa solução. • Um dos problemas principais é a criação da gramática para uma linguagem natural, pois essas gramáticas são muito amplas. Existem dois enfoques para a criação dessas gramáticas: o primeiro consiste em manualmente identificar e expressar as regras baseadas no conhecimento humano; e o segundo é automático, 1 e consiste em extrair regras de textos existentes, chamados de corpus. O enfoque utilizado aqui consiste em extrair as regras de um corpus existente em que as estruturas das frases foram manualmente identificadas e anotadas. O corpus utilizado foi gerado pelo trabalho do projeto Tycho Brahe de Português Histórico1 , e o corpus foi simplificado para reduzir o número de regras da gramática. O presente trabalho descreve uma implementação do algoritmo de Earley para gramáticas livres de contexto probabilísticas, utilizando o 75% do corpus para extração das regras e o 25% restante para teste das mesmas, calculando a precisão e cobertura dos resultados para avaliar quão próximas são as respostas obtidas pelo algoritmo das que foram manualmente anotadas no corpus. A Seção 2 descreve o corpus utilizado e as considerações tomadas para o processamento do mesmo. A Seção 3 detalha a implementação feita em termos do algoritmo e as estruturas de dados utilizadas. A Seção 4 apresenta os resultados obtidos pelo algoritmo considerando a precisão das respostas, assim como uma discussão sobre a eficiência do algoritmo em termos de tempo e espaço consumido. Finalmente, a Seção ?? apresenta algumas conclusões abordadas durante a implementação do algoritmo. 2 Corpus Um dos métodos de extração automática de regras para uma gramática de linguagem natural utiliza um corpus manualmente anotado. As anotações feitas no corpus indicam a estrutura das sentenças que conformam o texto. Um exemplo de frase sem anotações presente no corpus é: Não foi preciso que os sucessos verificassem aquele vaticínio, Dita frase está presente no corpus com as correspondentes anotações como segue: (IP (NEG Não) (SR foi) (ADJP (ADJ preciso)) (CP (C que) (IP (NP (D os) (N sucessos)) (VB verificassem) (NP (D aquele) (N vaticínio)))) (, ,)) Em que aparece a estrutura da frase em forma de regras. As regras que podem ser extraídas da frase anotada são: 1 http://www.ime.usp.br/˜tycho 2 • NEG → Não • SR → foi • ADJ → preciso • ADJP → ADJ • C → que • D → os • N → sucessos • NP → D N • VB → verificassem • D → aquele • N → vaticínio • IP → NP VB NP • CP → C IP • ,→, • IP → NEG SR ADJP CP , O corpus original do projeto Tycho Brahe contém informação mais detalhada sobre as estruturas das frases, por exemplo a regra (D os), está presente no corpus original como (D-P os) indicando que os é um determinante (D) em plural(P). Esse detalhe foi tirado do corpus para reduzir o número de regras geradas o que reduz o tempo de resposta do algoritmo de reconhecimento. Este processo de filtragem foi automático, mas gerou algumas regras que produziam laços infinitos no reconhecimento das frases, por exemplo: IP → IP ou o conjunto de regras {PP → IP, IP → PP}. Esses problemas foram identificados manualmente e as regras removidas automaticamente. Um 75% das frases do corpus, selecionadas aleatoriamente, é utilizado para extrair as regras da gramática e para treiná-la e o 25% restante é utilizado para testar, e delas só as árvores sintáticas são extraídas. 3 Descrição da Implementação A implementação foi feita em C++ usando a libreria STL, e o compilador g++ para linux. Na Seção 3.1 as estruturas de dados utilizadas na implementação do algoritmo são detalhadas, e na Seção ?? apresentamos o algoritmo de Earley utilizado na implementação. 3 3.1 Estruturas de Dados Na figura 1 se mostra o diagrama de classes na linguagem UML para as propriedades e operações principais usadas na implementação. As classes foram: Figura 1: Diagrama de Clases para a implementação. • Item Gramatical(GrammarItem), Terminal e Não Terminal(NonTerminal): um item gramatical é um não terminal ou não terminal da gramática, o não terminal tem a informação para saber se ele deriva a terminais(é lado esquerdo de regras léxicas); • Regra(Rule): uma regra é representada pelo não terminal do seu lado esquerdo e os itens gramaticais do seu lado esquerdo(sejam terminais ou não terminais). Uma regra armazena a sua probabilidade, que é a contagem de aparições dela no corpus, dividido pela contagem de aparições de regras que tem o mesmo não terminal no lado esquerdo; • Regra Instanciada(InstancedRule): uma regra instanciada é uma regra sendo processada pelo algoritmo, e que contém informação do estado de processamento dela, o número de não terminais do lado direito que foram analisados(arcPos) e as posições em que cada um dos seus itens foi instanciado; • Item de Processamento(ProcessingEntry): sempre que uma regra é finalizada, o não terminal do lado esquerdo dela deve ser analisado para ativar outras re4 gras nas que ele aparece do lado direito, esta estrutura armazena a informação necessária para verificar isso; • Analisador Sintático(EarleyParser): é a implementação do algoritmo de Earley que será explicada na seguinte Seção. Para executar o algoritmo, ele conta com seis estruturas: – arcos: os arcos são as regras para as quais pelo menos um dos elementos do seu lado direito foi processado com as entradas que foram avaliadas, são indexados pela posição do primeiro elemento ainda não instanciado e pelo elemento, – arcos não instanciados: são uma cópia das regras originais da gramática(sem considerar as regras léxicas), – arcos léxicos: são arcos não instanciados associados às regras léxicas, – regras finalizadas: os arcos que são processados até o último símbolo do seu lado direito são ditos de finalizados e são armazenados nesta estrutura, são indexadas pela posição em que começam e pelo não terminal do seu lado esquerdo. O algoritmo utiliza uma pilha de itens de processamento durante a sua execução. Além disso, para cada não terminal que foi instanciado dominando duas posições específicas se ele está na pilha atualmente esperando para ser processada, assim como a regra de maior probabilidade que instanciou aquele não terminal nessas posições. • Árvore Sintática e Nó da árvore(STTree e STNode): A árvore sintática de uma frase é a estrutura dela. Existem dois modos de construir a árvore, quando ela é extraída do conjunto de frases de teste, ela é gerada diretamente em base à representação anotada da frase; quando o algoritmo de Earley reconhece uma frase ele gera uma árvore sintática segundo as regras que ele encontrou que estavam presentes na frase. A árvore anotada e a árvore gerada são comparadas para obter a similaridade entre elas, i. e., o número de nós em que elas coincidem. O número de coincidências dividido pelo número de nós da arvore gerada é a precisão do algoritmo para essa frase. O número de coincidências dividido pelo número de nós da árvore extraída do corpus anotado é a cobertur do algoritmo. Essas duas medidas permitem avaliar o desempenho do algoritmo. Um programa foi escrito para geração aleatória de instâncias de 3-SAT, e é rodado com: ./gen N L e gera um arquivo gen_N_L onde N é o número de variáveis, e L o número de cláusulas. O programa de resolução é chamado: 5 DPL(nível) 1. Se nível = 0 Então 1.1. Aplicar Redução Unipolar; 2. aplicou <- verdadeiro; 3. Enquanto a fórmula seja indefinida e aplicou 3.1. aplicou <- BCP(nível); 4. Se a fórmula é falsa Então 4.1. Desfazer os BCPs feitos no nível; 4.2. Retorna falso; 5. Se a fórmula é verdadeira Então 5.1. Retorna verdadeiro; 6. lit <- Seleção de Literal; 7. var <- lit.variable; 8. Se lit.sinal é verdadeiro Então 8.1. var.valor <- verdadeiro; 9. Senão 9.1. var.valor <- falso; 10. Se DPL(nível + 1) é verdadeiro Então 10.1. Retorna verdadeiro; 11. var.valor <- negação(var.valor); 12. Se DPL(nível + 1) é verdadeiro Então 12.1. Retorna verdadeiro; 13. var.valor <- indefinido; 14. Desfazer os BCPs feitos no nível; 15. Retorna falso; Figura 2: O algoritmo DPL implementado. ./solver arquivo_problema arquivo_saída Onde o arquivo de problema está no formato proposto no SATLIB[?] e o arquivo de saída contém os resultados da execução do programa, i.e. se o problema é satisfazível e a valoração encontrada que faz o problema satisfazível se houver. 4 Resultados Testes foram feitos para encontrar de manera experimental o ponto de mudança de fase para 3-SAT. O ponto de mudança de fase é ubicado no valor L/N no qual a porcentagem de problemas satisfazíveis de um conjunto de instâncias geradas aleatóriamente é próximo a 50%. O valor de N foi fixado para os testes a 50 e 100, tomando 100 arquivos aleatórios em cada ponto de L/N evaluado. Os resultados obtidos podem ser 6 vistos na figura ??. O gráfico mostra a relação entre a variação de valores L/N e a porcentagem de problemas satisfazíveis dos 100 arquivos aleatórios. O ponto de mudança de fase foi encontrado em 4.3 em N=50 e em 4.25 para N=100. Outra característica notada é que os problemas que tomaram mais tempo (em média e máximo para os 100 arquivos aleatórios) para ser resolvidos estão na proximidade do ponto de mudança de fase, naqueles pontos em que a porcentagem de problemas satisfazíveis é diferente de 0% e de 100%, como pode ser visto nas figuras ?? e ??. Os gráficos mostram a relação entre L/N e o tempo em segundos tomado pelo algoritmo para resolver os problemas aleatórios em média e no máximo. Os valores obtidos nos testes foram registrados e são mostrados nas tabelas 1 e ??. 5 Conclusões • A implementação de reduções como BCP e literais unipolares assim como o uso da heurística MOM para a escolha do literal sob estruturas de dados adequadas, permite reduzir dramáticamente o tempo que o algoritmo toma para resolver o problema. • A mudança de fase é um fenómeno singular neste problema e se apresenta num pequeno intervalo de valores L/N , para valores entre 3.5 e 6, já para os outros pontos, a porcentagem de problemas satisfazíveis é ou 0% ou 100%. • Nestes pontos próximos a mudança de fase foi percebido que o tempo de resolução em geral tomado pelo algoritmo foi maior que nos outros valores de L/N . 7 L/N 0.5 1 2 3 3.5 3.76 4 4.1 4.2 4.3 4.32 4.34 4.36 4.38 4.4 4.44 4.5 4.6 4.7 4.8 4.9 5 6 7 8 9 10 20 L 25 50 100 150 175 188 200 205 212 215 216 217 218 219 220 222 225 230 235 240 245 250 300 350 400 450 500 1000 % Satisfazíveis 100 100 100 100 100 95 91 78 66 60 59 52 47 47 47 38 42 25 18 16 13 6 0 0 0 0 0 0 Tempo médio(s) 0.04 0.04 0.06 0.04 0.03 0.03 0.05 0.07 0.1 0.12 0.09 0.07 0.12 0.07 0.11 0.08 0.11 0.11 0.13 0.12 0.15 0.13 0.13 0.14 0.15 0.14 0.2 0.32 Tempo máximo(s) 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 Tabela 1: Resultados obtidos para N=50. 8