Skip to content

Instantly share code, notes, and snippets.

@ryukinix
Last active April 4, 2017 11:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ryukinix/2b06ccc87c8eda02f4c7 to your computer and use it in GitHub Desktop.
Save ryukinix/2b06ccc87c8eda02f4c7 to your computer and use it in GitHub Desktop.
Uma introspecção a respeito dos últimos métodos e algoritmos utilizados na tentativa de extração de tópicos em NLP

LDA

Descrição: Dado um conjunto de documentos, com esse tipo de algoritmo conseguimos uma distribuição de keywords como tópicos para cada documento individual, na qual é ordenado pela sua probabilidade. Podemos definir que o tópico mais provável daquele post é o que tem maior score após o treinamento do modelo LDA.

Prós: Conseguimos um conjunto de tokens para categorizar um post/comment. Como os tópicos são genérico e um tópico tem a tendência de ser categorizado por um documento mais de uma vez, é possível pensar em clusterização de documentos a partir desses tópicos — muito mais facilmente que abordagem anterior usando expressões regulares capitalizadas. Como a análise de criação de tópicos é global, podemos ter inferências de assuntos, pois não necessariamente as keywords (tokens) do tópico mais provavél estarão todas no documento, pode haver mais. (veja no exemplo)

Contras: Precisamos definir antes de rodar o algoritmo quantos tópicos queremos gerar num conjunto de documentos. Um conjunto de keywords ainda não é o nível de abstração maior para definir um tópico. Seria necessário para refinar esses resultados a criação de labels para cada tópico ainda.

Comentários: Um bom exemplo disso é definido nesse estudo na qual o autor procura padrões num dataset de letras sobre músicas de black metal ao tentar definir os tópicos relacionados nas letras como uma soma de keywords, que é muito similar com nosso output de LDA. Cada tópico é identificado como uma soma de 10 keywords ordenada e selecionada pela sua probabilidade relevância. O contexto, como exposto pelo autor, foi escrito manualmente ao taggear uma label para cada um desses tópicos.

Árvore de tópicos

black-metal-topics

Expansão das keywords de um dos tópicos

evil-and-the-devil

Todo o sumário do output pode ser encontrado aqui que é muito semelhante ao que temos usando a implementação do gensim.

Ps.: Posteriormente foi descoberto que o autor usa o Stanford Topic Modeling Toolbox que por baixo dos panos usa LDA também.

Exemplo (após treinado, dados reais usando tx.extractor.Extractor — Seara 221 posts):

>>> doc = """A Fátima tem uma receita especial que é um clássico em sua família: 
             Peru Seara com maçã verde e farofa. 
             Confira quais são os segredinhos dela e coloque Seara na sua ceia. 
             #ExperimenteSeara"""
>>> model.doc2topics[doc]
  [('seara', 0.050292241395710827),
  ('frango', 0.018411098547155866),
  ('dia', 0.01763133381113113),
  ('vai', 0.013373479983465209),
  ('gente', 0.012961695894492937),
  ('receita', 0.011710121610594131),
  ('peru', 0.01040337001735943),
  ('gostoso', 0.010402359312791817),
  ('peito', 0.010401862098707988),
  ('hora', 0.0097230357273362499)]

Observe que frango não está no nosso documento, mas é semanticamente próximo de todo o contexto. Observe que isso é apenas um tópico, onde model.doc2topics retorna o tópico mais provável, mas é possível ajustar para retornar todos os tópicos ordenados pela probabilidade, onde o número de tópicos é definido na construção da classe (um dos nossos problemas com LDA).

Word2Vec

Descrição: Dado um conjunto de documentos, Word2Vec após treinado nos permite detectar similaridades entre palavras, podendo ser usado para buscas semânticas, clusterização e de algum modo correção ortográfica.

Prós:

  • Busca semântica
  • Similaridade
  • Possibilidade de clusterizar documentos

Contras: Ajustes finos na normalização são cruciais para um bom modelo, senão palavras irreconhecíveis estarão no vocabulário como risadas, emoticons e outros tipos de ruido.

Exemplo (após treinado, dados fictícios):

>>> model.most_similiar("banana")
[("banaana", 0.99), ("fruta", 0.9), ("maçã", 0.7), ("frouxo", 0.6) ... ]

Phrases (Gensim)

Descrição: dado um conjunto de documentos, este tipo de algoritmo nos permite encontrar possíves alocações de palavras em uso comuns. Isto é, de forma optimizada, podemos gerar n-grams e juntá-los como tokens únicos, onde muitas vezes não faz sentido sozinho. Como "muito_bom" e "queijo_parmesão".

Prós: invés de gerar ngrams incompreensíveis, podemos alocar de forma optimizada os ngrams mais prováveis de acordo com um set de documentos.

Contras: para cada dimensão de alocação — bigram, trigram, ou qualquer n > 2 — precisamos gerar um modelo exclusivo para ele. Isto é, se o objetivo é encontrar trigrams, precisamos primeiro treinar um modelo para encontrar bigrams que alocará tokens como "muito_bom" e então usamos este aninhado com o treinamento inicial de unigrams parseados pelo modelo bigram (um novo set de treinamento). Desse modo, o que era "agua_na" como bigram, o novo modelo que será treinado como trigram pode de repente fazer merge dos tokens "agua_na" e "boca" -> "agua_na_boca"

Exemplos (pós-treino com o que temos no repositório de ai-nlp):

>>> bigram, trigram = load_models()
>>> tokens = tokenize("Isso é muito bom! Me deu agua na boca!")
>>> normalized = normalize(tokens)
["isso", "e", "muito", "bom", "me", "deu", "agua", "na", "boca"]
>>> bigram[normalized]
["isso", "e", "muito_bom", "me", "deu", "agua_na", "boca"]
>>> trigram[bigram[normalized]]
["isso", "e", "muito_bom", "me", "deu", "agua_na_boca"]

Obervações finais

Potenciais:

  • LDA tem se demonstrado ter um grande potencial para chegar em algum lugar com extração de tópicos. Temos uma implementação em ai-nlp-tx que dado um conjunto de documentos genéricos podemos extrair individualmente o tópico mais provável para cada um dos documentos.
  • O Phrases do gensim pode ser usado em conjunto a LDA termos keywords com mais significado.
  • Word2Vec pode ser usado para clusterizar tópicos, já que cada tópico é um set de keywords. Dessa maneira, podemos criar um grafo de distância entre as relações de cada tópico e depois fazer a regressão dos tópicos aos documentos. No fim teremos um grafo dos documentos (posts, comments) com sua relação de distância identificado individualmente como cada tópico.

Dúvidas persistentes:

  • Ainda não entendo como o HDP (Hierarcichal Dirichlet Process) funciona para encontrar o número natural de tópicos dado um conjunto de documentos para então nos auxiliar em LDA.
  • A classe Extractor para extração de tópicos está por enquanto implementado de um modo não-online — nossa principal classe de funcionamento com LDA implementada no ai-nlp-tx. Nós conseguimos os tópicos individuais para um set de documentos no momento, mas por enquanto não conseguimos salvar esse model para treinamento futuro ou fazer uma atualização no modelo para novas extrações. O que é crucial para novos dados e novos tópicos. Por outro lado, o gensim dá suporte a treinamento online de LDA e inclusive em computação paralela. Apenas precisamos remodelar isso.
  • A saída de LDA nos proveḿ um método conveniente para se fazer muitas coisas, como clusterização de documentos, por outro lado ainda é distante de uma informação de alta abstração como se o tópico fosse uma "Descrição" sucinta do que significa o documento. Uma aproximação possível será um meio de automatizar as labels para os tópicos, mas não tenho ideia ainda como fazer isso.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment