Nltk: Discussão: Ressuscitando o modelo Ngram

Criado em 25 mar. 2016  ·  21Comentários  ·  Fonte: nltk/nltk

Oi pessoal!

Estou trabalhando para garantir que o módulo Ngram Model possa ser adicionado de volta ao NLTK e gostaria de trazer alguns problemas para discussão.

Problema 1
Aqui, @afourney disse que seria bom adicionar interpolação como uma alternativa ao backoff padrão de Katz como uma forma de lidar com ngrams invisíveis. Estive pensando sobre isso e devo ter uma ideia de como isso poderia funcionar. Eu gostaria de apresentá-lo a todas as partes interessadas.

A estrutura de classe atual do módulo model é a seguinte:

  • model.api.ModelI -> supõe-se que seja uma classe abstrata ou uma interface, eu acho.
  • model.ngram.NgramModel -> estende a classe acima, contém a implementação atual do modelo ngram.

Aqui está o que proponho:

  • model.api.Model -> Sinceramente, não tenho certeza se vejo o ponto disso, ambivalente sobre se devo mantê-lo ou abandoná-lo.
  • model.ngram.BasicNgramModel -> Isso é o mesmo que NgramModel , menos tudo o que tem a ver com retirada. Basicamente, ele não pode lidar com ngrams não vistos no treinamento. "Por que isso?" - você pode perguntar. Eu acho que esta seria uma grande demonstração da necessidade de backoff / interpolação. Os alunos podem simplesmente experimentar e ver como é ruim se convencerem a usar as outras classes.
  • model.ngram.BackoffNgramModel -> Herda de BasicNgramModel para produzir a implementação atual de NgramModel , exceto que é mais explícito sobre a parte de retirada.
  • model.ngram.InterpolatedNgramModel -> Também herda de BasicNgramModel , mas usa interpolação em vez de backoff.

Os objetivos de longo prazo aqui são:

a) para permitir que qualquer classe ProbDist seja usada como um estimador de probabilidade, uma vez que a interpolação / retirada são (principalmente) agnósticas do algoritmo de suavização que está sendo usado.
b) para permitir que qualquer um que queira _optimizar_ um NgramModel para seus próprios propósitos seja capaz de herdar facilmente alguns padrões úteis das classes em NLTK.

Edição 2
Infelizmente, o módulo de probabilidade tem seus próprios problemas (por exemplo, # 602 e (minha) implementação de Kneser-Ney é irregular). Portanto, por enquanto, estou apenas testando a exatidão com LidstoneProbDist , já que é fácil de calcular manualmente. Devo me preocupar com a falta de suporte para os métodos de alisamento mais avançados? Ou queremos talvez proceder dessa maneira para garantir pelo menos que o modelo Ngram funcione, e _então_ lidar com as classes de probabilidade problemáticas separadamente?

Python 3 super()
Ao chamar super() , preciso me preocupar com o suporte a python 2? Veja isso para o contexto.

corpus enhancement language-model nice idea tests

Comentários muito úteis

Acho que definitivamente vale a pena ter no NLTK; é uma parte central de quando eu
ensine PNL.

O NLTK está oferecendo suporte a LMs profundos agora? Esta API é compatível com isso?


Jordan Boyd-Graber

Voz: 920.524.9464
[email protected]

http://boydgraber.org

Na terça - feira, 3 de outubro de 2017 às 23h32, alvations

@ Copper-Head https://github.com/copper-head @jacobheil
https://github.com/jacobheil e usuários / devs NLTK interessados ​​em
Modelos de linguagem N-gram.

Exatamente como fazer o check-in no estado atual do submódulo do modelo.

  • Você acha que está pronto para empurrá-lo para o desenvolvimento / master
    filial?
  • Ainda é um tópico que as pessoas buscam ativamente e querem ver no
    NLTK?

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/nltk/nltk/issues/1342#issuecomment-334041035 ou mudo
o segmento
https://github.com/notifications/unsubscribe-auth/AAhoqh5oxzo2Y9mp88I8uwy4lmyNz9Amks5sovxngaJpZM4H4nGe
.

Todos 21 comentários

Seria bom ter uma biblioteca de n-gram funcionando em NLTK. SRILM tem alguns wrappers Python para inferência, mas tem licença restritiva. KenLM tem um wrapper Python para fazer inferências, mas tem dependências na compilação. Nenhum dos dois tem suporte para estimativa. Portanto, atualmente não há ferramentas n-gram bem testadas disponíveis para Python PNL.

@anttttti Obrigado pelo feedback, me sinto muito motivado em enviar um patch vendo toda essa demanda para o recurso :)

Por acaso, você tem alguma opinião sobre os problemas específicos que postei?

Os métodos avançados de suavização são simples de implementar, uma vez que você entenda que eles diferem apenas na forma como o desconto e a interpolação são definidos. Artigos anteriores e muitas das descrições dos livros didáticos fazem os modelos parecerem mais complicados do que são, uma vez que as pessoas não entendiam as conexões tão bem antes. Não deve haver necessidade de módulos separados, apenas configuração de suavização. Os modelos de backoff mais antigos que não foram normalizados corretamente não são usados ​​atualmente, consulte "A Bit of Progress in Language Modeling" de Joshua Goodman para um ótimo resumo. http://arxiv.org/pdf/1602.02332.pdf página 63 resume algumas opções para o desconto e interpolação para um caso unigrama, modelos de ordem superior usam o mesmo recursivamente. Kneser-Ney é um pouco mais complicado com os backoffs modificados.

A suavização não é tão crítica para a maioria dos usos. Com dados suficientes, mesmo Kneser-Ney otimizado não é melhor do que Stupid Backoff. Portanto, apenas ter n-gramas de alta ordem disponíveis em Python com qualquer suavização básica seria bom. Lidstone ou Jelinek-Mercer para cada pedido deve funcionar perfeitamente bem.

Questão 1) Uma coisa que eu acho que seria muito útil é ter um utilitário para construir um vocabulário e censurar tokens OOV. Isso corrigiria muitos dos erros bobos que frustravam os usuários com as versões antigas. Estou anexando um código que faz isso (sinta-se à vontade para usar ou copiar)
lm.txt

Questão 2a) Eu acho que ainda é útil ter Kneser-Ney; é comumente ensinado e é útil ter uma implementação de referência.
Problema 2b) Eu me preocupo que o acoplamento ProbDist torne isso muito mais complicado do que precisa ser. Pode ser mais simples manter a estimativa de probabilidade dentro do modelo de linguagem para coisas como KN. Para outros modelos, pode ser adequado usar ProbDist.

@anttttti "

@ezubaric "_Issue 2b) Eu me preocupo que o acoplamento ProbDist torne isso muito mais complicado do que precisa ser_"

Embora eu não tenha olhado para esse código há algum tempo, minha sensação é que ambas as afirmações são verdadeiras.

Se bem me lembro, ConditionalProbDist (e mais geralmente ProbDist) são normalizados muito cedo para uso em modelos ngram suavizados. Por exemplo, embora saibamos qual é a probabilidade de uma palavra em um determinado contexto, temos dificuldade em raciocinar sobre os próprios contextos (acredito que um patch anterior tentou corrigir esse problema - apesar de todos os esforços, foi um pouco confuso [https: //github.com/nltk/nltk/pull/800]).

IMHO, a coisa toda é um pouco mais de engenharia.

@afourney

IMHO, a coisa toda é um pouco mais de engenharia.

Amém para isso! Estou tentando fazer isso funcionar há muito tempo (enviei # 800 e sim, não era nada elegante) e também estou começando a achar que há muitas partes móveis para que seja razoável.

@ezubaric muito obrigado por esse arquivo, estou pegando totalmente emprestado seu espírito para a refatoração.

Com base em todos esses comentários, aqui está minha nova visão sobre a estrutura do módulo. Temos apenas uma aula: model.ngram.NgramModelCounter .

Basicamente, são vários contadores FreqDist combinados em uma interface clara. _Treinamento_ consiste simplesmente em contar recursivamente o número de ngrams, bem como manter o controle do tamanho do vocabulário (com potencialmente "finalizar" algumas dessas contagens para evitar atualizações após a conclusão do treinamento). @alvations Sei que você gostaria de uma implementação experimental para isso, mas acho que podemos começar com um contador recursivo ineficiente por enquanto e refatorar o back-end mais tarde, já que não deve afetar muito a interface.

Crucialmente, esta classe não lida com probabilidades de forma alguma . Isso deve tornar as coisas significativamente mais simples e, ao mesmo tempo, mais flexíveis. Tudo que alguém precisa fazer para adicionar probabilidades é usar seu método OOP favorito (por exemplo, herança ou composição) para escrever uma classe que usa os atributos de NgramModel para construir seu próprio método prob() .

Se eu tiver tempo, apresentarei um (ou dois!) Exemplos de como poderia funcionar adicionar probabilidades a NgramModelCounter.

O que vocês acham, pessoal?

@ Copper-Head com interface semelhante ao KenLM tanto quanto possível seria bom para integração futura: https://github.com/kpu/kenlm/blob/master/python/example.py

Eu acho que depois que uma versão estável de NgramModel de NLTK for lançada, eu posso tentar refatorar kenlm wrapper para usar interfaces semelhantes às de NLTK, como o que fizemos para scikit-learn .

Esta função também ajudaria no preenchimento: https://github.com/nltk/nltk/blob/develop/nltk/util.py#L381

Acho que @ Copper-Head está sugerindo uma classe que conta unigramas, bigramas, trigramas, etc. de uma forma coordenada que é conveniente para consumir por modelos de linguagem downstream. Nesse caso, acho que a API kenlm ainda não se aplica. (Posso estar errado, mas pelo exemplo postado, não parece que a API kenlm lida com contagens de frequência brutas)

Eu acho que também vale a pena considerar uma API de modelo de linguagem mínima que consome essas contagens ngram. Como @ Copper-Head sugere, esta seria uma subclasse, ou melhor ainda, uma interface completamente separada (permitindo implementações muito diferentes como https://www.projectoxford.ai/weblm). Aqui, acho que pode ser razoável adotar a API kenlm, mas acho que _qualquer_ interface LM ngram deve ser simples o suficiente para que os adaptadores possam ser facilmente escritos.

Acho que uma API ngram mínima realmente só precisa de métodos para (1) calcular a probabilidade condicional de um token dado um contexto ou sequência e (2) relatar o tamanho e a composição do vocabulário conhecido. Quase tudo o mais pode ser calculado por meio de métodos auxiliares, incluindo cálculos de probabilidade conjunta, bem como geração de linguagem. Esses auxiliares podem ou não fazer parte da interface.

Hmm, ponto interessante. Eu me pergunto se manter o controle dessas contagens para GT pode retardar o treinamento um pouco e desnecessariamente para pessoas que não querem usar essa suavização em particular. Eu acho que pode fazer mais sentido fazer o mínimo na classe NgramCounter básica e então simplesmente estender seu método de treinamento (ou __init__ ) em uma subclasse especializada para Good-Turing, ou mesmo em um implementação da API ngram voltada para o cálculo de probabilidades de Good-Turing.
Mas estou apenas sentado para escrever algumas dessas coisas, então talvez isso não acabe sendo um problema no final.

Parece que excluí uma postagem acidentalmente. Para preencher o contexto ausente para leitores futuros: acho que seria bom considerar técnicas de suavização comuns ao projetar a API NgramModelCounter. Por exemplo, permitir que os usuários consultem o número de _espécies_ observadas uma, duas ou N vezes é importante para a suavização Good-Turing (assim como a suavização Witten-Bell, etc.)

Edit: Parece que a classe FreqDist já tem um pouco disso (ver: FreqDist.hapaxes e FreqDist.r_Nr) Eu me pergunto se ele pode ser reaproveitado? Ou se FreqDist deve ser o ponto de partida.

Eu gosto da ideia de ter apenas um objeto de contagem que pode ser consultado com subclasses que implementam métodos de suavização específicos.

Minha única preocupação é que o treinamento terá problemas se não tivermos a capacidade de corrigir o vocabulário antecipadamente: não será consistente com os processos de treinamento LM padrão e rastrear todo o vocabulário faria com que a memória explodisse (o que era um grande problema com o antigo LM também).

Observado. Tenho ideias de como resolver isso. Estarei postando um PR mais tarde hoje.

PR # 1351 está em alta !! Traga as perguntas / detalhes :)

@ Copper-Head - quão longe estamos de poder mesclar isso de volta ao branch principal?

Olhando para minha lista de tarefas, eu diria que preciso de 2 a 3 dias de trabalho concentrado.
Considerando que estou de volta a trabalhar nisso no meu tempo livre da escola e no trabalho diário, eu daria algo entre 2 semanas e um mês antes de terminar com todas as _minhas_ questões pendentes. Isso naturalmente não leva em consideração coisas aleatórias que podem ser trazidas à minha atenção naquele momento.

@ Copper-Head @jacobheil e usuários / desenvolvedores de NLTK interessados ​​em modelos de linguagem N-gram.

Exatamente como fazer o check-in no estado atual do submódulo model .

  • Você acha que ele está pronto para colocá-lo no branch de desenvolvimento / master?
  • Ainda é um tópico que as pessoas buscam ativamente e querem ver no NLTK?

Acho que definitivamente vale a pena ter no NLTK; é uma parte central de quando eu
ensine PNL.

O NLTK está oferecendo suporte a LMs profundos agora? Esta API é compatível com isso?


Jordan Boyd-Graber

Voz: 920.524.9464
[email protected]

http://boydgraber.org

Na terça - feira, 3 de outubro de 2017 às 23h32, alvations

@ Copper-Head https://github.com/copper-head @jacobheil
https://github.com/jacobheil e usuários / devs NLTK interessados ​​em
Modelos de linguagem N-gram.

Exatamente como fazer o check-in no estado atual do submódulo do modelo.

  • Você acha que está pronto para empurrá-lo para o desenvolvimento / master
    filial?
  • Ainda é um tópico que as pessoas buscam ativamente e querem ver no
    NLTK?

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/nltk/nltk/issues/1342#issuecomment-334041035 ou mudo
o segmento
https://github.com/notifications/unsubscribe-auth/AAhoqh5oxzo2Y9mp88I8uwy4lmyNz9Amks5sovxngaJpZM4H4nGe
.

Olá - Eu gostaria de usar o recurso "antigo" do modelo de linguagem em NLTK. Qual é a versão mais recente que ainda tem o modelo de idioma pré-treinado (para inglês)?

Para aqueles que estão encontrando este segmento, eu meio que juntei um submódulo contendo o código do modelo antigo.

https://github.com/sleepyfoxen/nltk_model

@stevenbird , acho que podemos fechar isso finalmente :)

Para obter feedback concreto sobre a implementação existente, as pessoas podem abrir questões separadas.

@ Copper-Head sim, eu concordo. Parabéns! :)

Esta página foi útil?
0 / 5 - 0 avaliações