Open arademaker opened 4 years ago
Em https://github.com/cpdoc/dhbb-ner, temos arquivos JSON produzidos pelo Watson Knowledge Studio. Ferramenta da IBM de anotação de entidades, relações e co-referencia. Antes de tentar qualquer outro sistema de NER como acima, queremos cruzar as anotações de NER com analises sintáticas. Isto nos permitirá priorizar as árvores sintáticas que precisamos corrigir no DHBB, e com isso teremos um ciclo de: revisão de anotação ~> treino UDPipe ~> anotação. Existem errors de anotação também veja http://dhbb.mybluemix.net/dhbb/document?id=212
« Antônio Nonato do Amaral» nasceu em Belém , no dia 16 de maio de 1926 , filho de [Domingos Araújo do Amaral] e de [Olinda Guimarães do Amaral] .
O nome da mãe foi erroneamente identificado como "Olinda Guimarães" apenas e "Amaral" foi erroneamente anotado como local. Para esta mesma sentença, o parser também cometeu um erro, ligando Amaral
pela relação de nmod
e não flat
.
O que teremos e cruzar as anotações e achar inconsistências que possam nos sinalizar os erros frequentes. Todo segmentado anotado como uma entidade deve corresponder a uma subárvore na análise sintática.
O script deve receber como entrada um arquivo conllu e um arquivo json, ambos do mesmo documento. Teremos que usar os spans para alinhar sentenças e anotações de cada árvore. O que queremos é produzir como saida um conllup (https://universaldependencies.org/ext-format.html) com as árvores de sintáticas expandidas como as anotações de entidades encontradas no JSON. Simultaneamente, ou posteriormente, podemos ter uma validação destes arquivos conllup procurando por 'potenciais' inconsistências entre as anotações.
~/work/udpipe-1.2.0/bin-osx/udpipe --tokenizer="normalized_spaces;ranges" --tag --parse ~/work/udpipe-1.2.0/models/portuguese-bosque-ud-2.5-191206.udpipe < ../raw/1.raw > 1-new.conllu
obs: atencao para modelo usado com udpipe! ver dir udp para info de qual modelo mais atual temos e/ou seguir orientacoes para treinar.
@arademaker , agora que temos o parser do JSON completo e conseguimos rodar a Conllu.IO usando o stack, comecei a esboçar a verificação das entidades nas subarvores. Me deparei com o seguinte problema: a Aerson esta instalada no meu compilador padrão, mas o Conllu.IO só funciona rodando o ghci com o stack de dentro da pasta da biblioteca. Estou tentando encontrar uma forma de conseguir usar ambas bibliotecas ao mesmo tempo, provavelmente dentro do stack. Se tiver alguma sugestão ou referência para indicar, agradeço.
Faça um fork do https://github.com/arademaker/test e comece de la colocando no src o código que lê o json. Depois em outro arquivo o código que lê o conllu usando a hs-conllu. No app ficará apenas o código que gera o executável final usando as funções do src
Toda a idéia de offsets/sents estou reconsiderando. Principalmente porque todo o diretório sents
pode ser considerado temporário.
De qq. modo, para avançarmos com esta tarefa, precisamos de uns arquivos conllu com offsets por tokens. Então rodei:
ar@leme sents %for f in ../raw/?.raw; do ~/work/apache-opennlp-1.9.3/bin/opennlp SentenceDetector ../src/model_opennlp.bin < $f > $(basename $f .raw).sent; done
e conferi os arquivos 1-9.sent manualmente. Depois executei o comando abaixo para produzir os arquivo .conllu
:
ar@leme udp % ~/work/udpipe-1.2.0/bin-osx/udpipe --outfile={}.conllu --tokenizer="presegmented;normalized_spaces;ranges" --tag --parse ~/work/udpipe-1.2.0/models/portuguese-bosque-ud-2.5-191206.udpipe ../sents/?.sent
Note que o parametro presegmented
faz o udpipe entender que o arquivo .sent
tem uma sentença por linha. Como em cada sentença temos o metadado text =
com o texto da sentença, os arquivos .sent
não precisam ser preservados, podemos facilmente obte-los a partir dos .conllu
.
See b4313a413
@igorcj, os arquivos JSON do repositório https://github.com/cpdoc/dhbb-ner não estão atualizados. Eles foram gerados para alimentar o demo em http://dhbb.mybluemix.net/dhbb/home, mas as anotações foram feitas com um modelo de reconhecimento de entidades e relações antigo.
Com este comando, produzi os arquivo ner/?.json
no 04b8b57f3. Os valores corretos no lugar de APIKEY e URL abaixo não posso publicar, or segurança. Mas o que está sendo feito é passar os arquivos raw para o serviço da IBM chamado natural language understanding e pedindo para ele rodar usando o model treinado no Watson Knowledge Studio.
for f in raw/?.raw; do curl -G --header "Content-Type: application/json" -u 'apikey:APIKEY' --data-urlencode "text@$f" "URL/v1/analyze?version=2020-08-01&features=entities,relations&entities.model=073dab23-dd1e-4ded-badf-f502eb06372c&entities.mentions=true" > ner/$(basename $f .raw).json; done
Então sua tarefa deve ser adaptada para ler este arquivo ner/N.json
e alimentar cada sentença no respectivo udp/N.conllu
com metadados para as mentions detectadas nos tokens da sentença.
Vamos ter que usar o método POST para os arquivos maiores, algo como:
curl -X POST --header "Content-Type: application/json" -u 'apikey:KEY' -d @parameters.json "URL/v1/analyze?version=2019-07-12" > ner/1.json
Mas para isso provavelmente será mais fácil usarmos uma biblioteca de http request como http://www.serpentine.com/wreq/tutorial.html para construir o json antes de passar para o serviço.
Em bc9f733e1 removi os arquivos inválidos.
Revivendo o issue. Trabalhando no repo teste
, temos agora um app test-conllu
que consegue mergear um .json
do diretório ner
produzido pelo WKS e um respectivo .conllu
do firetório udp
produzido pelo UDPipe. Apos mergeeados em um unico .conllu
, o mesmo executável é chamado para verifica a consistencia da análise sintática com a identificação das entidades.
Executando esse processo para os arquivos disponíveis, foram reveladas algumas inconsistências, sendo que me parece as mais comuns serem de datas. O que executei foi:
for n in `for f in ner/*.json; do echo $f | awk -F[/.] '{print $2}'; done`; do echo Processando $n; test-conllu -m ner/$n.json udp/$n.conllu temp/$n.conllu; done
Em seguida, para a verificação:
for f in temp/*.conllu; do echo Processando $f; test-conllu -c $f; done > temp/check.log
Onde esse arquivo .log
produzido continha a analise de 73 documentos, e inconsistencias foram encontradas em32 deles. Seguem as respectivas entidades:
...
Estou agora analisando mais especificamente os casos para tentar especificar qual ferramenta errou, mas ja temos uma clara divergencia em datas. Coisas como maio do mesmo ano
ou agosto de 1966
tem sido marcados como entidades mas não estão contidos em uma subárvore na análise sintática.
for n in ner/*.json; do echo Processando $n; test-conllu -m $n udp/$(basename $n .json).conllu udp/$(basename $n .json)-n.conllu; done
Removi o ultimo comentário longo com a lista de todas as entidades.
De acordo com https://link.springer.com/article/10.1007/s42600-020-00067-7 parece que vale a pena conhecer
https://github.com/flairNLP/flair
Não apenas para POS tagging mas também para NER