cpdoc / dhbb-nlp

processamentos DHBB
Other
5 stars 2 forks source link

split of sentences #39

Open arademaker opened 4 years ago

arademaker commented 4 years ago

usando https://opennlp.apache.org/docs/1.9.2/manual/opennlp.html#tools.sentdetect.detection.api no ABCL podemos fazer o split de sentenças ficar bem mais rápido sem ter que reler modelo para cada file.

arademaker commented 4 years ago

Consultando https://abcl.org e o manual, consegui implementar o código Lisp que roda no ABCL chamando a biblioteca OpenNLP. O código ficou mais simples do que a versão puramente Java, Detector.java. Vide 3a31fe86d. Atualmente, o processamento do OpenNLP é agora 3-4 vezes mais rápido que o Freeling.

Removi os post-processing de OpenNLP e isto voltou a aumentar o número de diferenças entre OpenNLP e Freeling, temos duas saídas, vide 25f965464:

  1. retreinar o modelo OpenNLP
  2. agora em Lisp, melhorar a implementação do post-processamento (ou pre-processing) a partir de uma lista de abreviações e dos casos que fazíamos via awk e sed.

Usar Java a partir de CL via ABCL é algo que podemos explorar em outras etapas do projeto, como para trabalhar com RDF.

arademaker commented 4 years ago

até agora estamos usando Freeling e OpenNLP e comparando resultados. Os arquivos iguais são movidos para sents/, os arquivos diferentes permanecem nos respectivos diretórios. Depois que @lucasrct treinou o OpenNLP, acho que estamos tendo na grande maioria dos casos, melhores resultados do OpenNLP do que o Freeling. Por exemplo, quase todos os casos onde uma sentença começa com aspas o OpenNLP fez o certo. Quando temos sentenças terminadas como abreviações, como siglas de partidos, também OpenNLP acerta mais.

Além disso, o workflow não é eficiente. Primeiro porque Freeling é muito mais lento agora do que o OpenNLP. Segundo porque os Makefiles, apenas os arquivos que sofriam alteração no raw/ eram reprocessados. Agora o script do OpenNLP reprocessa tudo e a identificação dos arquivos iguais é destrutiva, apagando arquivos dos diretórios opennlp e fl.

Sugiro:

  1. talvez abandonar o Freeling
  2. avaliar, para curiosidade, a NLTK de Python porque ela implementa o https://www.aclweb.org/anthology/J06-4003.pdf.
  3. tentarmos aprender como abreviações podem ser passadas para o OpenNLP durante treino, é durante treino, certo? Alguns erros permanecem por conta disso, podemos resolver com mais exemplos para treino? ou a informação de abreviações ajudaria o sistema melhor? Vejam saidas de:

% rg --multiline "S.\nPaulo" *.sent
% rg --multiline "[dDsS]r.\n" *.sent

(o comando rg é o https://github.com/BurntSushi/ripgrep)

  1. tentarmos efetivamente entender o que OpenNLP não consegue aprender e vermos se justifica tentarmos uma implementação nossa de segmentação, algo usando talvez outro.

Para 4 alguns links que encontrei:

@lucasrct , se lembrar de algo que achamos e que não esteja na lista, please comente. Acho que para alguns passos daqui, @Cristiananc poderia ajudar...

arademaker commented 4 years ago

In 131ac9370

  1. script src/segmentation.py que usa NLTK para segmentação. É possível treinar segmentador, não explorei ainda.
  2. relatório src/segmentation.org que compara saidas do fl/, opennlp/ e nltk/.
  3. diretório nltk/

Como dito acima, as estatisticas no codigo lisp acima podem ajudar a investigar as diferenças e ver o que opennlp ainda está errando e eventualmente quem conseguimos treinar com mais sucesso: NLTK ou OpenNLP? Existe algum caso onde Freeling acerta? Me parece que boa parte das diferenças é causada por: 1) sentenças que terminam com ponto seguido de aspas (."); e 2) alguma abreviações, principalmete de nomes do meio. Opennlp e NLTK, não são consistentes nestes casos.

Os diretórios fl, opennlp, nltk e sents precisam ser consolidados e transformados em apenas um diretório que coresponderá a nossa segmentação de sentenças. Precisamos começar a usar algum JSON talvez por arquivo assim podemos ter a separação por parágrafo e por sentença.

lucasrct commented 4 years ago

@arademaker Você chegou a treinar o modelo do punct? Pelo que me lembro o ideal é treinar em cima do próprio corpus mesmo, para ele aprender as abreviações que aparecem lá. Não encontrei nada referente ao treino no seu código.

Eu vou fazer um diff do nltk e opennlp e nltk e freeling para ver o que sai, mas eu ainda acho que o OpenNLP é mais promissor, ele tende a ser mais robusto a erros e o DHBB contém vários.

@Cristiananc podemos conversar sobre um pipeline para corrigir algumas frases que o opennlp erra e re-treiná-lo com a ideia de melhorá-lo. Eu fiz isso com algumas frases uma vez e a melhora foi bem significativa. Dá pra automatizar o processo e o treino do OpenNLP é muito rápido, menos de 30 segundos.

arademaker commented 4 years ago

@lucasrct tem um README dentro do zip em https://github.com/nltk/nltk_data/tree/gh-pages/packages/tokenizers que explica o passo-a-passo para treinar. O ideal seria aprendemos a treinar sim. Neste README também tem a informação de como o modelo existente para PT foi treinado. Quando vc instala no NLTK e faz o download desta dependência para rodar o src/segmentation.py, ele cria um diretório nltk_data no seu home, e este zip é expandido lá.

Correto, concordo que o OpenNLP parece o mais promissor mesmo. De todos acho que Freeling é o menos robusto e ainda mais lento. Veja no segmentation.org que coloquei um último comando para gerar um sample de diferenças dado algum critério. Em todos os casos onde OpenNLP tem menos sentenças, acho que bastaria retreinarmos ele com os casos onde ele errou. Pipeline que conversamos. Um dos casos foi causado por inconsistências de abreviações como LTDA, Ltda. etc.

arademaker commented 4 years ago

mas eu ainda acho que o OpenNLP é mais promissor, ele tende a ser mais robusto a erros e o DHBB contém vários.

Lembrando que o interessante aqui não é comparar as ferramentas, mais os métodos e entender o limite que cada método sendo usado.. este é a questão interessante.

arademaker commented 4 years ago

Não acho que vale tanto à pena, mas apenas para não esquecer que existem coisas como http://www.sfu.ca/rst/index.html.

arademaker commented 4 years ago

e como comparar com o udpipe e a capacidade de udpipe aprender comparado com opennlp? Temos 5 sentenças em:

Filho de imigrantes italianos de origem pobre, Camilo Cola cursou as quatro primeiras séries do ensino fundamental, na Escola Pindobas Singular. Trabalhou como agricultor e lavador de carros, e em 1944 foi enviado com a Força Expedicionária Brasileira para combater na Itália durante a II Guerra Mundial. Quando retornou da Europa, utilizou uma linha especial de créditos para ex-combatentes para comprar o primeiro caminhão, que seria o princípio de sua empresa de transportes, a Viação Itapemirim S.A. Estabeleceu posição de destaque no setor de transportes, fundando e dirigindo outras empresas atuantes na área: Flecha S.A - Turismo Comércio e Indústria; Samadisa - São Mateus Diesel Serviços e Autos LTDA; Ercisa - Estação Rodoviária Cachoeira do Itapemirim S.A; Tecnobus Serviços Com. e Ind. LTDA. Foi ainda fundador e administrador de outras empresas, como a Conpasso - Construções e Participações Sociais LTDA; Itabira Administradora e Corretora de Seguros LTDA; Cola Representações Ind. e Com. Ltda; Massad Cola Repreendimentos e Participações LTDA; Massad Cola Marketing e Comunicação LTDA; Cola Comercial e Distribuidora LTDA; Gráfica e Editora Itabira LTDA; Itapemirim Turismo Agência de Viajens e Despachos LTDA; Complexo Agroindustrial Pindobras LTDA; Imobiliária Bianca Ltda; Itampemirim Informática LTDA; Marbrasa Mámores e Granitos do Brasil LTDA.

arademaker commented 4 years ago

@lucasrct

  1. No opennlp/README.org vc fala do amostras_DHBB.sent e do param.txt. O param.txt está no directorio. Onde está o amostras_DHBB.sent? Seria o sents/sentences_gold.sent?

  2. O arquivo model_trained.pickle usando pelo src/segmentation.py para produzir os arquivos em nltk não está no repositório. Também não achei instruções de como produzir o model_trained.pickle.

@igorcg

O objetivo final é consolidar os diretórios fl, sents, nltk e opennlp em apenas um diretório. Até agora usamos:

a. Freeling. Deterministico: tokenização antes de split olhando o codigo sabemos exatamente o que faz. b. NLTK ideia principal é o https://www.aclweb.org/anthology/J06-4003.pdf, mas como faz tokenização vs segmentação, detalhes não sabemos. c. OpenNLP (treino, MaxEnt model? não sasbemos detalhes) d. UDPipe (treino: mas sabemos pouco como é feita a parte de split de sentenças e como podemos controlar/treinar)

Como já comentado acima, para terminar este issue, temos que rever os links acima, responder as perguntas sobre ferramentas, decidir sobre uma. Obviamente, seria vantajoso usar menos ferramentas durante o projeto, mas isto não é tão importante.

E precisamos evitar tantas copias de textos e arquivos. Uma possivel idéia seria:

Podemos ter um arquivo como o opennlp/golden.txt com um nome de arquivo por linha que indique os arquivos sent revisados. ou seja, ao invés de copiar sentenças de diferentes documentos para o arquivo sents/sentences_gold.sent, teremos arquivos revisados. Treino do opennlp seria um script que iria ler o arquivo golden.txt, juntar em um file para treinar o sistema. acho que podemos ter facilmente mais que 9K sentenças no DHBB e com isso não usar mais os dados do Bosque para treinar o opennlp. Faz sentido? Vantagem? Desvantagem?

ar@leme opennlp % wc -l `cat golden.txt`
      14 1.sent
     216 100.sent
      13 10928.sent
      31 11046.sent
      66 11160.sent
      29 11419.sent
      40 11440.sent
      14 11512.sent
      20 11526.sent
      21 11530.sent
      39 11587.sent
      51 973.sent
     182 5426.sent
     736 total
ar@leme opennlp % wc -l ../sents/sentences_gold.sent
     203 ../sents/sentences_gold.sent

Outra página para ser lida:

arademaker commented 4 years ago

Juntei os diretórios opennlp, fl e sents no ultimo. O código principal agora é o detector.lisp que processar o Freeling e o OpenNLP e gera um único arquivo quando eles concordam no número de sentenças e gera dois arquivos quando eles discordam. Pode melhorar, não deveria usar apenas número de sentenças.

arademaker commented 4 years ago

@lucasrct assim que vc responder sobre o modelo faltante para o nltk, junto o diretório nltk também no sents.

lucasrct commented 4 years ago

@arademaker Já coloquei lá na pasta src o arquivo. Eu não vi a mensagem, estava watching o dhbb-nlp, mas não para atualização dos issues, agora já corrigi e vou receber no meu e-mail as conversas.

Sobre o modelo, acho que vale carregá-lo e encontrar quais tokens ele considerou como abreviação. Isso vai com certeza encontrar erros no DHBB e também entender melhor como ele funciona.

@lucasrct

  1. No opennlp/README.org vc fala do amostras_DHBB.sent e do param.txt. O param.txt está no directorio. Onde está o amostras_DHBB.sent? Seria o sents/sentences_gold.sent?

Isso, eu tinha escrito o README e depois achei melhor mudar o nome, mas acabei me esquecendo de alterar a documentação.

  1. O arquivo model_trained.pickle usando pelo src/segmentation.py para produzir os arquivos em nltk não está no repositório. Também não achei instruções de como produzir o model_trained.pickle.

Acabei de upar o arquivo, eu vou criar uma documentação de como produzir o modelo colocar lá também.

@igorcg

Se precisar de ajuda para entender mais as pastas no DHBB e também o workflow similar que temos para os arquivos UDP, podemos conversar.

Por fim, sobre usar as sentenças do DHBB para treinar o opennlp, algumas considerações:

  1. Pensando por alto, não vejo vantagem a nível de acurácia, não vejo motivo para usar um conjunto de dados com X sentenças quando podemos usar um com X+Y sentenças. Cabe notar que, diferentemente da análise sintática, podemos facilmente assumir que a segmentação do Bosque está correta, não?

  2. Algum motivo em especial para evitar usar o bosque? Pensando no modelo somente, é melhor usar dois cojuntos de dados com frases de estilos diferentes do que apenas o estilo do DHBB. E não sei se obteríamos resultados de fato melhores mesmo dentro do DHBB.

  3. Eu não sei se coletar 9K frases do DHBB será um trabalho simples.

arademaker commented 4 years ago

@lucasrct, não consigo rodar:

% source .env/bin/activate
(.env) ar@leme ~ % cd
(.env) ar@leme ~ % cd work/cpdoc/dhbb-nlp/src
(.env) ar@leme src % python segmentation.py
Traceback (most recent call last):
  File "segmentation.py", line 6, in <module>
    sent_tokenizer = nltk.data.load('model_trained.pickle')
  File "/Users/ar/.env/lib/python3.7/site-packages/nltk/data.py", line 757, in load
    resource_val = pickle.load(opened_resource)
ValueError: unsupported pickle protocol: 5

Sobre comentários acima. Não podemos assumir segmentação do bosque está correta. Infelizmente. Tem uns problemas lá. Acho que com uns 20 arquivos do DHBB já temos dados suficientes para treinar o OpenNLP. Mas ainda não estou certo entre vantagens vs desvantagens de ter uma lista de files golden vs ter cópias de sentenças hard em um arquivo golden... E sim, podemos também corrigir o Bosque..

igorcj commented 4 years ago

Plano de ação

O plano de ação envolve retirar uma amostra estatisticamente coerente dos casos de divergência entre o Freeling e o OpenLP, analisa-la manualmente e comparar o resultado com as duas ferramentas apresentadas, além da NLTK e a UDPipe.

Passo 1

Determinar quais os casos de divergência entre o OpenLP e o Freeling e extrair uma amostra a ser trabalhada em todo o issue.

Passo 2

Análise manual da amostra: percorrer todos os textos realizando a segmentação de forma manual e guardando os resultados como uma base de comparação para os algoritmos.

Passo 3

Obter as segmentações para os metodos.

Passo 4

Comparação dos resultados dos quatro métodos com a base gerada no passo da análise manual. Determinar o índice de acerto de cada método e identificar eventual melhor candidato ao projeto.

Passo 5

Caso confirmada a suspeita prévia de que o OpenLP apresenta um melhor desempenho, cabe ainda alimentar o modelo de Learning com os casos analisados manualmente nesse processo numa tentativa de melhoria. Nesse caso é preciso também um minucioso controle para verificar o aprendizado.

arademaker commented 4 years ago

Outra ferramenta relevante https://github.com/google/sentencepiece

arademaker commented 4 years ago

O que temos agora no branch sentences é um pipeline para rodar o openNLP e NLTK e produzir as diferenças de spans nos arquivos diff.

ao olhar as diferenças, com o novo sent-descompact, descobrimos casos onde tanto NLTK quanto OpenNLP devolveram com uma sentença um span contendo uma quebra de linha, ou seja, de alguma forma a quebra de linha existente (nos raw apenas entre parágrafos), foi ignorada pelas ferramentas.

% ../src/sent-descompact.lisp ../raw/2100.raw 2100.diff
(op): Seu irmão, Diogo Borges Fortes, foi comandante-em-chefe da Armada de 1958 a 1959 e ministro do Superior Tribunal Militar (STM) de 1960 a 1967.
(nk): Seu irmão, Diogo Borges Fortes, foi comandante-em-chefe da Armada de 1958 a 1959 e ministro do Superior Tribunal Militar (STM) de 1960 a 1967.
Transferindo-se para o Rio de Janeiro, então Distrito Federal, estudou no Colégio Militar dessa cidade e em abril de 1926 sentou praça, ingressando na Escola Militar do Realengo, de onde saiu aspirante-a-oficial da arma de artilharia em janeiro de 1929.
(op): Transferindo-se para o Rio de Janeiro, então Distrito Federal, estudou no Colégio Militar dessa cidade e em abril de 1926 sentou praça, ingressando na Escola Militar do Realengo, de onde saiu aspirante-a-oficial da arma de artilharia em janeiro de 1929.

% ../src/sent-descompact.lisp ../raw/1737.raw 1737.diff
(nk): Ao longo de sua vida empresarial, Germano Dockhorn fundou no Sul do país as seguintes empresas: Sociedade Dockhorn, Laticínios Dockhorn, Germano Dockhorn S.A., Industrial Dockhorn, Cereais Dockhorn, Cia.
(op): Ao longo de sua vida empresarial, Germano Dockhorn fundou no Sul do país as seguintes empresas: Sociedade Dockhorn, Laticínios Dockhorn, Germano Dockhorn S.A., Industrial Dockhorn, Cereais Dockhorn, Cia. de Administração Germano Dockhorn e Rádio Colonial Ltda.
Faleceu em Três de Maio, no dia 11 de fevereiro de 1973.
(nk): de Administração Germano Dockhorn e Rádio Colonial Ltda.
(nk): Faleceu em Três de Maio, no dia 11 de fevereiro de 1973.

precisamos pensar como lidar com isso. boa parte das diferenças podem ser causadas por isso. podemos passar a processar por parágrafos? Podemos descobrir se conseguimos fazer NLTK e OpenNLP serem robustos a isso?

arademaker commented 3 years ago

ok, concordamos que não são as quebras de linhas que atrapalham os algoritmos. Então agora

openNLP:

  1. http://opennlp.apache.org/docs/1.9.3/manual/opennlp.html#tools.sentdetect.training
  2. readme que lucas fez

Podemos a partir dos diff e sent, criar um conjunto de arquivos em sents/golden e fazer a segmentacao 'manual'. depois podemos treinar o openNLP e evaliar. Precisamos não apenas dos casos difíceis mas também dos casos óbvios para o sistema aprender.

NLTK

igorcj commented 3 years ago

Consegui observar algumas coisas bem interessantes com o que já extrai dos diffs. Dei uma analisada numérica nessa planiha. Acho que vale dar uma conferida. Ademais, já tenho 273 sentenças gold.

arademaker commented 3 years ago

@igorcj para fecharmos este issue, queremos ter uma esquema documentado que como a segmentacao atual é feita no diretorios sents e como podemos, gradativamente, revisar as anotações automaticas (.offset) e transforma-las em gold (.goffset).

arademaker commented 3 years ago

precisamos avaliar quantos erros devem existir nas segmentações do UDPipe! Como? comparar com o openNLP e Punkt (Haskell ou NLTK)?!

arademaker commented 3 years ago

@analununes por favor, citar aqui comentario sobre o artigo do Punkt de não pre-treinar modelo. Colocar também link para o PDF...

analununes commented 3 years ago

Link para o PDF: https://www.aclweb.org/anthology/J06-4003.pdf

Sobre usar lista de abreviações no treinamento (páginas 24 e 25 do PDF): "The results show that Punkt can indeed benefit from additional abbreviation lists, but only if these are prepared with care. Providing such a carefully prepared abbreviation list reduced the error rate of our system on the WSJ corpus from 1.65% to 1.58%, the error rate on the Brown corpus from 1.02% to 0.92%, and the error rate on the German NZZ corpus from 0.35% to 0.32%. Additional general-purpose abbreviation lists thus do improve the performance of our system, but the decrease of the error rate is not very great. Table 14 also shows that abbreviation lists from which abbreviations homographic to ordinary words and single-character abbreviations have not been removed are not helpful at all and instead lead to an increased error rate on all of the three corpora. "

Casos problemáticos (página 28 do PDF): "The first type of error results from the type-based nature of our approach to abbreviation detection. Abbreviations may not be recognized as such and wrong sentence boundaries may be introduced if an abbreviation is a homograph of an ordinary word or homographic types. For example, the English abbreviation in. for inch might not be recognized because it coincides with the frequent preposition in. All occurrences of in with and without a final period will be added together and the type in will most probably be classified as a non-abbreviation. All instances of in followed by a period will then be marked as ordinary words preceding a sentence boundary. This type of error was common in the English, Italian, and Portuguese test corpora."

arademaker commented 3 years ago

Mas uma ferramenta que trata de segmentação .

https://gmb.let.rug.nl/elephant/about.php

arademaker commented 3 years ago

Depois do tempo que dedicamos ao problema de segmentação, este issue merece ser fechado com algum resultado mais consistente sobre a segmentação de sentenças no DHBB. O mini pode ser nossa referencia, golden data, dado que já corrigi vários erros de segmentação nele.

Já discutimos várias abordagens/ferramentas (regras, supervisionados, não supervisionados etc): openNLP,. NLTK/Punkt, udpipe, IBM WKS/NLU, Freeling e agora o Elephant. Além dos links acima, temos ainda o https://github.com/diasks2/pragmatic_segmenter que em algum momento olhamos e coloco aqui para não esquecermos. Enfim, precisamos reavaliar o que escrevemos em http://arademaker.github.io/bibliography/propor-2020.html sobre segmentação e ver o que faltou ser dito. sobre o assunto. Por um lado, sabemos que em boa parte do DHBB, segmentação via OpenNLP vs NLTK/Punkt nos dá 1-2% de discordancia entre eles, considerando todo o DHBB, e por isso o assunto parece pouco relevante, dado que os possíveis erros parecem ser irrelevantes. Por outro lado, o fato de ferramentas concordarem não significa que ambas estão certas e, existem perguntas ainda sem resposta:

  1. quais os limites de cada método/ferramenta?
  2. qual abordagem é melhor para o DHBB? não apenas em termos de resultados quantitativos mas também em termos qualitativos e de manutenabilidade.
  3. podemos combinar as abordagens? Existe algum espaço para desenvolvermos alguma ou método nosso?