Eu tenho um sistema semi-funcional que resolve esse problema, código aberto usando o scikit-learn, com uma série de postagens de blog que descrevem o que estou fazendo. O problema que estou enfrentando é a desambiguação de sentido de palavra (escolher uma das várias opções de sentido de palavra ), que não é o mesmo que Reconhecimento de entidade nomeada. Minha abordagem básica é um tanto competitiva com as soluções existentes e (crucialmente) é personalizável.
Existem algumas ferramentas comerciais NER (OpenCalais, DBPedia Spotlight e AlchemyAPI) que podem fornecer um resultado comercial bom o suficiente - experimente primeiro!
Eu usei alguns deles para um projeto de cliente (eu consultor usando PNL / ML em Londres), mas não fiquei feliz com a recordação ( precisão e recall ). Basicamente, eles podem ser precisos (quando dizem "Esta é a Apple Inc", normalmente estão corretos), mas com pouca memória (raramente dizem "Esta é a Apple Inc", embora para um humano o tweet seja obviamente sobre a Apple Inc). Achei que seria um exercício intelectualmente interessante construir uma versão de código aberto sob medida para tweets. Aqui está o código atual:
https://github.com/ianozsvald/social_media_brand_disambiguator
Vou observar - não estou tentando resolver o problema generalizado de desambiguação de sentido de palavra com esta abordagem, apenas desambiguação de marca (empresas, pessoas, etc.) quando você já tem seus nomes. É por isso que acredito que essa abordagem simples funcionará.
Comecei isso há seis semanas e está escrito em Python 2.7 usando scikit-learn. Ele usa uma abordagem muito básica. Eu vetorizo usando um vetorizador de contagem binária (só conto se uma palavra aparece, não quantas vezes) com 1-3 n-gramas . Eu não escala com TF-IDF (TF-IDF é bom quando você tem um comprimento de documento variável; para mim, os tweets são apenas uma ou duas frases e meus resultados de teste não mostraram melhorias com TF-IDF).
Eu uso o tokenizer básico, que é muito básico, mas surpreendentemente útil. Ele ignora @ # (assim você perde algum contexto) e, claro, não expande um URL. Eu, então, treino usando regressão logística , e parece que esse problema é um tanto linearmente separável (muitos termos para uma classe não existem para a outra). Atualmente estou evitando qualquer corte / limpeza (estou tentando a coisa mais simples possível que pode funcionar).
O código tem um README completo, e você deve ser capaz de ingerir seus tweets com relativa facilidade e seguir minhas sugestões de teste.
Isso funciona para a Apple, pois as pessoas não comem ou bebem computadores Apple, nem digitamos ou brincamos com frutas, então as palavras são facilmente divididas em uma categoria ou outra. Esta condição pode não se manter ao considerar algo como #definance para o programa de TV (onde as pessoas também usam #definance em relação à Primavera Árabe, partidas de críquete, revisão de exames e uma banda de música). Abordagens mais inteligentes podem ser necessárias aqui.
Tenho uma série de posts descrevendo este projeto, incluindo uma apresentação de uma hora que fiz no grupo de usuários BrightonPython (que se transformou em uma apresentação mais curta para 140 pessoas na DataScienceLondon).
Se você usar algo como LogisticRegression (onde obtém uma probabilidade para cada classificação), você pode escolher apenas as classificações confiáveis e, dessa forma, pode forçar a alta precisão negociando contra recall (para obter resultados corretos, mas menos deles). Você terá que ajustar isso ao seu sistema.
Aqui está uma possível abordagem algorítmica usando scikit-learn:
- Use um Contador Binário (não acho que contagens de termos em mensagens curtas adicionem muitas informações, pois a maioria das palavras ocorre apenas uma vez)
- Comece com um classificador de árvore de decisão. Ele terá um desempenho explicável (consulte Overfitting com uma árvore de decisão para um exemplo).
- Mover para regressão logística
- Investigue os erros gerados pelos classificadores (leia a saída exportada do DecisionTree ou olhe os coeficientes em LogisticRegression, trabalhe os tweets mal classificados de volta através do Vectorizer para ver como é a representação subjacente do Bag of Words - haverá menos tokens lá do que você começou no tweet bruto - há o suficiente para uma classificação?)
- Veja meu exemplo de código em https://github.com/ianozsvald/social_media_brand_disambiguator/blob/master/learn1.py para uma versão funcional desta abordagem
Coisas a considerar:
- Você precisa de um conjunto de dados maior. Estou usando 2.000 tweets rotulados (demorei cinco horas) e, no mínimo, você quer um conjunto equilibrado com> 100 por classe (veja a nota sobre ajuste abaixo)
- Melhore o tokeniser (muito fácil com scikit-learn) para manter # @ em tokens e talvez adicionar um detector de marca com letras maiúsculas (conforme notas do usuário @ user2425429)
- Considere um classificador não linear (como a sugestão de @oiez acima) quando as coisas ficarem mais difíceis. Pessoalmente, descobri que o LinearSVC tem um desempenho pior do que a regressão logística (mas isso pode ser devido ao espaço de recursos de alta dimensão que ainda não reduzi).
- Um tagger de classe gramatical específico para um tweet (na minha humilde opinião, não o de Standford como @Neil sugere - ele tem um desempenho ruim em gramática do Twitter pobre, na minha experiência)
- Assim que tiver muitos tokens, você provavelmente vai querer fazer alguma redução de dimensionalidade (eu não tentei isso ainda - veja minha postagem no blog LogisticRegression l1 l2 penisation)
Ré. sobreajuste. Em meu conjunto de dados com 2.000 itens, tenho um instantâneo de 10 minutos do Twitter de tweets da 'apple'. Cerca de 2/3 dos tweets são para a Apple Inc, 1/3 para outros usos da apple. Eu retiro um subconjunto equilibrado (cerca de 584 linhas, eu acho) de cada classe e faço a validação cruzada quíntupla para o treinamento.
Uma vez que tenho apenas uma janela de tempo de 10 minutos, tenho muitos tweets sobre o mesmo tópico, e é provavelmente por isso que meu classificador se sai tão bem em relação às ferramentas existentes - ele terá ajustes excessivos para os recursos de treinamento sem generalizar bem (enquanto o comercial existente ferramentas têm pior desempenho neste snapshop, mas de forma mais confiável em um conjunto mais amplo de dados). Estarei expandindo minha janela de tempo para testar isso como um trabalho subsequente.