Como posso construir um modelo para distinguir tweets sobre Apple (Inc.) de tweets sobre apple (frutas)?

85

Veja abaixo 50 tweets sobre "apple". Identifiquei manualmente as correspondências positivas sobre a Apple Inc. Elas estão marcadas como 1 abaixo.

Aqui estão algumas linhas:

1|“@chrisgilmer: Apple targets big business with new iOS 7 features http://bit.ly/15F9JeF ”. Finally.. A corp iTunes account!
0|“@Zach_Paull: When did green skittles change from lime to green apple? #notafan” @Skittles
1|@dtfcdvEric: @MaroneyFan11 apple inc is searching for people to help and tryout all their upcoming tablet within our own net page No.
0|@STFUTimothy have you tried apple pie shine?
1|#SuryaRay #India Microsoft to bring Xbox and PC games to Apple, Android phones: Report: Microsoft Corp... http://dlvr.it/3YvbQx  @SuryaRay

Aqui está o conjunto de dados total: http://pastebin.com/eJuEb4eB

Preciso construir um modelo que classifique "Apple" (Inc). do resto.

Não estou procurando uma visão geral do aprendizado de máquina, em vez disso, estou procurando um modelo real no código ( Python de preferência).

SAL
fonte
18
Você basicamente quer isso: en.wikipedia.org/wiki/Bayesian_spam_filtering
eddi
1
Você rotula seus dados manualmente, mas deseja bibliotecas dessa escala. Isso é supervisionado ou não supervisionado?
dan
1
Eddi, obrigado pelo comentário. Ver o email de filtragem de e-mail realmente ajudou algo a clicar em meu cérebro. Pude ver um exemplo da vida real do que estava tentando fazer, mas aplicado de forma diferente.
SAL
5
Reconhecimento de entidade nomeada: nlp.stanford.edu/software/CRF-NER.shtml .
Neil McGuigan
1
Fascinante @NeilMcGuigan. Colei parte do texto na demonstração ( nlp.stanford.edu:8080/ner/process ) e fiquei impressionado com a forma como os diferentes modelos classificaram as palavras.
Ryan

Respostas:

39

Eu faria da seguinte forma:

  1. Divida a frase em palavras, normalize-as, construa um dicionário
  2. A cada palavra, armazene quantas vezes eles ocorreram em tweets sobre a empresa e quantas vezes apareceram em tweets sobre a fruta - esses tweets devem ser confirmados por um humano
  3. Quando um novo tweet chega, encontre cada palavra no tweet no dicionário, calcule uma pontuação ponderada - palavras que são usadas com frequência em relação à empresa obteriam uma pontuação alta da empresa e vice-versa; palavras raramente usadas, ou usadas tanto com a empresa quanto com a fruta, não teriam muita pontuação.
AMADANON Inc.
fonte
2
Obrigado por sua resposta sobre isso. Sua resposta em conjunto com um comentário acima realmente me ajudou a encontrar uma solução. Você pode me ajudar a aprimorar essa solução?
SAL
10
Esta é uma descrição informal da classificação bayesiana.
sanityinc
1
Eu prefiro "implementação de pseudo-código da classificação Bayesiana" :)
AMADANON Inc.
73

O que você está procurando é chamado de Reconhecimento de Entidade Nomeada . É uma técnica estatística que (mais comumente) usa campos aleatórios condicionais para encontrar entidades nomeadas, com base em ter sido treinado para aprender coisas sobre entidades nomeadas.

Essencialmente, ele analisa o conteúdo e o contexto da palavra, (olhando algumas palavras para trás e para a frente), para estimar a probabilidade de que a palavra seja uma entidade nomeada.

Um bom software pode analisar outras características das palavras, como seu comprimento ou forma (como "Vcv" se começar com "Vogal-consoante-vogal")

Uma biblioteca muito boa (GPL) é o NER de Stanford

Aqui está a demonstração: http://nlp.stanford.edu:8080/ner/

Alguns exemplos de texto para experimentar:

Eu estava comendo uma maçã na sede da Apple e pensei em Apple Martin, a filha do cara do Coldplay

(os classificadores 3class e 4class acertam)

Neil McGuigan
fonte
5
Isso foi muito interessante. É possível visualizar o código de english.conll.4class.distsim.crf.ser.gz? Adoraria ver como alguém constrói algo assim.
Ryan
O código para NER é open source, mas os dados que eles usaram nas conferências CONLL não são. No entanto, você pode encontrar o Reuters Corpus online no NIST.
Neil McGuigan
31

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.

Ian Ozsvald
fonte
Não tive o prazer de examinar seu código e tentar duplicar / emular / educar, mas devo a você um pedido de desculpas por não conceder os 50pts completos da recompensa. Eu estive longe do SO no fim de semana e perdi o prazo para premiá-lo. Felizmente, a comunidade SO interveio e achou por bem conceder a você 25 pontos.
Ryan
1
Sem problemas :-) O código, README e postagens do blog devem dar uma ideia sobre minha abordagem. É deliberadamente simples, mas parece funcionar bem.
Ian Ozsvald
12

Você pode fazer o seguinte:

  1. Faça um ditado de palavras contendo sua contagem de ocorrência em tweets relacionados a frutas e empresas. Isso pode ser conseguido alimentando-o com alguns tweets de amostra cuja inclinação conhecemos.

  2. Usando dados anteriores suficientes, podemos descobrir a probabilidade de uma palavra ocorrer em um tweet sobre a apple inc.

  3. Multiplique as probabilidades individuais de palavras para obter a probabilidade de todo o tweet.

Um exemplo simplificado:

p_f = Probabilidade de tweets de frutas.

p_w_f = Probabilidade de uma palavra ocorrer em um tweet de frutas.

p_t_f = Probabilidade combinada de todas as palavras no tweet ocorrerem um tweet de fruta = p_w1_f * p_w2_f * ...

p_f_t = Probabilidade de fruta em um determinado tweet.

p_c, p_w_c, p_t_c, p_c_t são os respectivos valores da empresa.

Um suavizador laplaciano de valor 1 é adicionado para eliminar o problema de frequência zero de novas palavras que não estão em nosso banco de dados.

old_tweets = {'apple pie sweet potatoe cake baby https://vine.co/v/hzBaWVA3IE3': '0', ...}
known_words = {}
total_company_tweets = total_fruit_tweets =total_company_words = total_fruit_words = 0

for tweet in old_tweets:
    company = old_tweets[tweet]
    for word in tweet.lower().split(" "):
        if not word in known_words:
            known_words[word] = {"company":0, "fruit":0 }
        if company == "1":
            known_words[word]["company"] += 1
            total_company_words += 1
        else:
            known_words[word]["fruit"] += 1
            total_fruit_words += 1

    if company == "1":
        total_company_tweets += 1
    else:
        total_fruit_tweets += 1
total_tweets = len(old_tweets)

def predict_tweet(new_tweet,K=1):
    p_f = (total_fruit_tweets+K)/(total_tweets+K*2)
    p_c = (total_company_tweets+K)/(total_tweets+K*2)
    new_words = new_tweet.lower().split(" ")

    p_t_f = p_t_c = 1
    for word in new_words:
        try:
            wordFound = known_words[word]
        except KeyError:
            wordFound = {'fruit':0,'company':0}
        p_w_f = (wordFound['fruit']+K)/(total_fruit_words+K*(len(known_words)))
        p_w_c = (wordFound['company']+K)/(total_company_words+K*(len(known_words)))
    p_t_f *= p_w_f
    p_t_c *= p_w_c

    #Applying bayes rule
    p_f_t = p_f * p_t_f/(p_t_f*p_f + p_t_c*p_c)
    p_c_t = p_c * p_t_c/(p_t_f*p_f + p_t_c*p_c)
    if p_c_t > p_f_t:
        return "Company"
    return "Fruit"
Sudipta
fonte
9

Se você não tiver problemas ao usar uma biblioteca externa, recomendo o scikit-learn, pois ele provavelmente pode fazer isso melhor e mais rápido do que qualquer coisa que você possa codificar sozinho. Eu apenas faria algo assim:

Construa seu corpus. Fiz as compreensões da lista para maior clareza, mas dependendo de como seus dados são armazenados, pode ser necessário fazer coisas diferentes:

def corpus_builder(apple_inc_tweets, apple_fruit_tweets):
    corpus = [tweet for tweet in apple_inc_tweets] + [tweet for tweet in apple_fruit_tweets]
    labels = [1 for x in xrange(len(apple_inc_tweets))] + [0 for x in xrange(len(apple_fruit_tweets))]
    return (corpus, labels)

O importante é que você acaba com duas listas parecidas com esta:

([['apple inc tweet i love ios and iphones'], ['apple iphones are great'], ['apple fruit tweet i love pie'], ['apple pie is great']], [1, 1, 0, 0])

O [1, 1, 0, 0] representa os rótulos positivos e negativos.

Então, você cria um Pipeline! Pipeline é uma classe scikit-learn que torna mais fácil encadear as etapas de processamento de texto para que você só precise chamar um objeto ao treinar / prever:

def train(corpus, labels)
    pipe = Pipeline([('vect', CountVectorizer(ngram_range=(1, 3), stop_words='english')),
                        ('tfidf', TfidfTransformer(norm='l2')),
                        ('clf', LinearSVC()),])
    pipe.fit_transform(corpus, labels)
    return pipe

Dentro do pipeline, existem três etapas de processamento. O CountVectorizer simboliza as palavras, divide-as, conta-as e transforma os dados em uma matriz esparsa. O TfidfTransformer é opcional e você pode querer removê-lo dependendo da classificação de precisão (fazer testes de validação cruzada e uma pesquisa de grade para os melhores parâmetros é um pouco complicado, então não vou entrar no assunto aqui). O LinearSVC é um algoritmo de classificação de texto padrão.

Finalmente, você prevê a categoria de tweets:

def predict(pipe, tweet):
    prediction = pipe.predict([tweet])
    return prediction

Novamente, o tweet precisa estar em uma lista, então presumi que ele estava inserindo a função como uma string.

Coloque todos eles em uma classe ou qualquer outra coisa e pronto. Pelo menos, com este exemplo básico.

Não testei este código, então pode não funcionar se você apenas copiar e colar, mas se você quiser usar o scikit-learn, ele deve dar uma ideia de por onde começar.

EDIT: tente explicar as etapas em mais detalhes.

oiez
fonte
6

Usar uma árvore de decisão parece funcionar muito bem para esse problema. Pelo menos ele produz uma precisão maior do que um classificador bayes ingênuo com minhas características escolhidas.

Se você quiser brincar com algumas possibilidades, pode usar o código a seguir, que requer a instalação do nltk. O livro nltk também está disponível gratuitamente online, então você pode querer ler um pouco sobre como tudo isso realmente funciona: http://nltk.googlecode.com/svn/trunk/doc/book/ch06.html

#coding: utf-8
import nltk
import random
import re

def get_split_sets():
    structured_dataset = get_dataset()
    train_set = set(random.sample(structured_dataset, int(len(structured_dataset) * 0.7)))
    test_set = [x for x in structured_dataset if x not in train_set]

    train_set = [(tweet_features(x[1]), x[0]) for x in train_set]
    test_set = [(tweet_features(x[1]), x[0]) for x in test_set]
    return (train_set, test_set)

def check_accurracy(times=5):
    s = 0
    for _ in xrange(times):
        train_set, test_set = get_split_sets()
        c = nltk.classify.DecisionTreeClassifier.train(train_set)
        # Uncomment to use a naive bayes classifier instead
        #c = nltk.classify.NaiveBayesClassifier.train(train_set)
        s += nltk.classify.accuracy(c, test_set)

    return s / times


def remove_urls(tweet):
    tweet = re.sub(r'http:\/\/[^ ]+', "", tweet)
    tweet = re.sub(r'pic.twitter.com/[^ ]+', "", tweet)
    return tweet

def tweet_features(tweet):
    words = [x for x in nltk.tokenize.wordpunct_tokenize(remove_urls(tweet.lower())) if x.isalpha()]
    features = dict()
    for bigram in nltk.bigrams(words):
        features["hasBigram(%s)" % ",".join(bigram)] = True
    for trigram in nltk.trigrams(words):
        features["hasTrigram(%s)" % ",".join(trigram)] = True  
    return features

def get_dataset():
    dataset = """copy dataset in here
"""
    structured_dataset = [('fruit' if x[0] == '0' else 'company', x[2:]) for x in dataset.splitlines()]
    return structured_dataset

if __name__ == '__main__':
    print check_accurracy()
Paul Dubs
fonte
1
Como é que isso funciona? Não vejo seus "recursos escolhidos" em seu código. Ele escolhe automaticamente os recursos com base no conjunto de treinamento? Ou está armazenado em dict()outro lugar? Acho que se um conjunto de treinamento for grande o suficiente, um computador não deveria ser capaz de descobrir os recursos por si só? (sem supervisão?)
Ryan
2
Os recursos são extraídos usando a função tweet_features. Basicamente, ele remove os urls dos tweets e, em seguida, cria um dict de recurso cujas entradas são lidas como 'hasBigram (foo, bar)' = True.
Paul Dubs
1
Então, 'hasBigram(foo,bar)' = Trueonde a string do tweet inclui foo bar? Então, ele cria bigramas e trigramas para cada tweet e os sinaliza no recurso positivo dict()? Portanto, dado o tweet "alpha beta gamma delta",, ele criará dict () bigrams para alpha,beta; beta,gamma; and gamma,delta;e trigramas para alpha,beta,gammae beta,gamma,delta? E a partir dos bi e tri gramas positivos e negativos dados, os classificadores da árvore de decisão ou bayes podem fazer sua mágica?
Ryan
2
Exatamente. Ao usar o classificador bayes, você também pode obter os recursos mais úteis chamando "show_most_informative_features ()" nele.
Paul Dubs
Paul, eu construí uma versão crua do php disso e você está absolutamente correto. Esta é uma maneira supereficiente de construir um dicionário ponderado. Acho que isso poderia escalar facilmente sem a necessidade de construir manualmente todas as palavras-chave. Estou ansioso para aprender mais sobre como fazer isso dentro de uma biblioteca de aprendizado de máquina padrão.
Ryan
5

Obrigado pelos comentários até agora. Aqui está uma solução de trabalho que preparei com PHP. Ainda estou interessado em ouvir de outras pessoas uma abordagem mais algorítmica para essa mesma solução.

<?php

// Confusion Matrix Init
$tp = 0;
$fp = 0;
$fn = 0;
$tn = 0;
$arrFP = array();
$arrFN = array();

// Load All Tweets to string
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://pastebin.com/raw.php?i=m6pP8ctM');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$strCorpus = curl_exec($ch);
curl_close($ch);

// Load Tweets as Array
$arrCorpus = explode("\n", $strCorpus);
foreach ($arrCorpus as $k => $v) {
    // init
    $blnActualClass = substr($v,0,1);
    $strTweet = trim(substr($v,2));

    // Score Tweet
    $intScore = score($strTweet);

    // Build Confusion Matrix and Log False Positives & Negatives for Review
    if ($intScore > 0) {
        if ($blnActualClass == 1) {
            // True Positive
            $tp++;
        } else {
            // False Positive
            $fp++;
            $arrFP[] = $strTweet;
        }
    } else {
        if ($blnActualClass == 1) {
            // False Negative
            $fn++;
            $arrFN[] = $strTweet;
        } else {
            // True Negative
            $tn++;
        }
    }
}

// Confusion Matrix and Logging
echo "
           Predicted
            1     0
Actual 1   $tp     $fp
Actual 0    $fn    $tn

";

if (count($arrFP) > 0) {
    echo "\n\nFalse Positives\n";
    foreach ($arrFP as $strTweet) {
        echo "$strTweet\n";
    }
}

if (count($arrFN) > 0) {
    echo "\n\nFalse Negatives\n";
    foreach ($arrFN as $strTweet) {
        echo "$strTweet\n";
    }
}

function LoadDictionaryArray() {
    $strDictionary = <<<EOD
10|iTunes
10|ios 7
10|ios7
10|iPhone
10|apple inc
10|apple corp
10|apple.com
10|MacBook
10|desk top
10|desktop
1|config
1|facebook
1|snapchat
1|intel
1|investor
1|news
1|labs
1|gadget
1|apple store
1|microsoft
1|android
1|bonds
1|Corp.tax
1|macs
-1|pie
-1|clientes
-1|green apple
-1|banana
-10|apple pie
EOD;

    $arrDictionary = explode("\n", $strDictionary);
    foreach ($arrDictionary as $k => $v) {
        $arr = explode('|', $v);
        $arrDictionary[$k] = array('value' => $arr[0], 'term' => strtolower(trim($arr[1])));
    }
    return $arrDictionary;
}

function score($str) {
    $str = strtolower($str);
    $intScore = 0;
    foreach (LoadDictionaryArray() as $arrDictionaryItem) {
        if (strpos($str,$arrDictionaryItem['term']) !== false) {
            $intScore += $arrDictionaryItem['value'];
        }
    }
    return $intScore;
}
?>

Os resultados acima:

           Predicted
            1     0
Actual 1   31     1
Actual 0    1    17


False Positives
1|Royals apple #ASGame @mlb @ News Corp Building http://instagram.com/p/bBzzgMrrIV/


False Negatives
-1|RT @MaxFreixenet: Apple no tiene clientes. Tiene FANS// error.... PAGAS por productos y apps, ergo: ERES CLIENTE.
SAL
fonte
4

Em todos os exemplos que você deu, Apple (inc) foi referido como A pple ou apple inc , portanto, uma maneira possível seria pesquisar:

  • um "A" maiúsculo na Apple

  • um "inc" depois da maçã

  • palavras / frases como "OS", "sistema operacional", "Mac", "iPhone", ...

  • ou uma combinação deles

user2425429
fonte
1
Na função fiz um strtolower para filtrar as letras maiúsculas. Um pouco grosseiro, mas funcionou.
SAL
@SAL Eu não esperava que fosse muito útil, mas se você tiver um limite de tempo, então ...
user2425429
4

Para simplificar um pouco as respostas com base em campos aleatórios condicionais ... o contexto é enorme aqui. Você vai querer escolher aqueles tweets que mostram claramente a Apple a empresa versus a maçã a fruta. Deixe-me esboçar uma lista de recursos aqui que podem ser úteis para você começar. Para obter mais informações, pesquise agrupamento de frases nominais e algo chamado rótulos BIO. Veja ( http://www.cis.upenn.edu/~pereira/papers/crf.pdf )

Palavras circundantes: Construa um vetor de características para a palavra anterior e a próxima ou, se desejar mais características, talvez as 2 palavras anteriores e as próximas 2. Você não quer muitas palavras no modelo ou não corresponderá muito bem aos dados. No Processamento de Linguagem Natural, você vai querer manter isso o mais geral possível.

Outros recursos para obter a partir das palavras ao redor incluem o seguinte:

Se o primeiro caractere é maiúsculo

Se o último caractere da palavra é um ponto

A classe gramatical da palavra (procurar marcação de classe gramatical)

O próprio texto da palavra

Não aconselho isso, mas para dar mais exemplos de recursos especificamente para a Apple:

WordIs (Apple)

NextWordIs (Inc.)

Você entendeu. Pense no reconhecimento de entidade nomeada como uma descrição de uma sequência e, em seguida, use um pouco de matemática para dizer a um computador como calculá-la.

Lembre-se de que o processamento de linguagem natural é um sistema baseado em pipeline. Normalmente, você divide as coisas em frases, passa para a tokenização e, em seguida, faz a marcação de classes gramaticais ou mesmo a análise de dependência.

Isso tudo para obter uma lista de recursos que você pode usar em seu modelo para identificar o que está procurando.

Adam Gibson
fonte
3

Existe uma biblioteca muito boa para processar texto em linguagem natural em Python, chamada nltk. Você deveria dar uma olhada nisso.

Uma estratégia que você pode tentar é olhar para n-gramas (grupos de palavras) com a palavra "maçã" neles. Algumas palavras são mais prováveis ​​de serem usadas ao lado de "maçã" quando se fala sobre a fruta, outras quando se fala sobre a empresa, e você pode usá-las para classificar tweets.

Scott Ritchie
fonte
1
Obrigado Manetheran. Não sou o autor da postagem original, mas também estou interessado na resposta. Para a recompensa, estou procurando algum código (mesmo usando nltk) que pode me ajudar a começar na direção certa com uma tarefa de aprendizado de máquina "hello world". A maçã (inc) vs. maçã (fruta) parece uma atribuição perfeita.
Ryan
3

Use LibShortText . Este utilitário Python já foi ajustado para funcionar em tarefas curtas de categorização de texto e funciona bem. O máximo que você terá que fazer é escrever um loop para escolher a melhor combinação de sinalizadores. Usei-o para fazer a classificação de atos de fala supervisionados em e-mails e os resultados foram até 95-97% precisos (durante a validação cruzada de 5 vezes!).

E vem dos fabricantes de LIBSVM e LIBLINEAR, cuja implementação de máquina de vetores de suporte (SVM) é usada em sklearn e cran, então você pode estar razoavelmente seguro de que sua implementação não tem bugs.

Pushpendre
fonte
2

Faça um filtro AI para distinguir a Apple Inc (a empresa) da maçã (a fruta). Como são tweets, defina seu conjunto de treinamento com um vetor de 140 campos, cada campo sendo o caractere escrito no tweet na posição X (0 a 139). Se o tweet for mais curto, basta dar um valor para estar em branco.

Em seguida, construa um conjunto de treinamento grande o suficiente para obter uma boa precisão (subjetiva ao seu gosto). Atribua um valor de resultado a cada tweet, um tweet da Apple Inc obtém 1 (verdadeiro) e um tweet da maçã (fruta) obtém 0. Seria um caso de aprendizagem supervisionada em uma regressão logística .

Isso é aprendizado de máquina, geralmente é mais fácil de codificar e tem melhor desempenho. Ele tem que aprender com o conjunto que você fornece e não está codificado.

Não conheço Python , então não posso escrever o código para ele, mas se você dedicar mais tempo à lógica e teoria do aprendizado de máquina, talvez queira dar uma olhada na aula que estou seguindo.

Experimente o curso Coursera Machine Learning de Andrew Ng . Você aprenderá o aprendizado de máquina no MATLAB ou Octave , mas depois de obter o básico, será capaz de escrever o aprendizado de máquina em qualquer linguagem se você entender a matemática simples (simples em regressão logística).

Ou seja, obter o código de alguém não o tornará capaz de entender o que está acontecendo no código de aprendizado de máquina. Você pode querer investir algumas horas no assunto para ver o que realmente está acontecendo.

Fawar
fonte
Obrigado Fawar. Eu esperava algum código neste "hello world" para esse propósito exato - aprender como o ML funciona. Eu vou procurar a classe embora. Parece bom.
Ryan
0

Eu recomendaria evitar respostas que sugiram o reconhecimento de entidade. Porque esta tarefa é primeiro uma classificação de texto e depois o reconhecimento de entidade (você pode fazer isso sem o reconhecimento de entidade).

Acho que o caminho mais rápido para os resultados será spacy + prodigy . Spacy tem um modelo bem pensado para o idioma inglês, então você não precisa construir o seu próprio. Enquanto o prodígio permite criar rapidamente conjuntos de dados de treinamento e ajustar o modelo de espaço para suas necessidades.

Se você tiver amostras suficientes, pode ter um modelo decente em 1 dia.

Dim
fonte
Ao mesmo tempo, spaCytem nercomponente de pipeline, não seria benéfico para esta classificação? Presumo que o modelo deles pode reconhecer Apple(por ser uma das maiores e mais conhecidas empresas do mundo) muito melhor do que um modelo que você pode criar em um dia.
Szymon Maszke
@Szymon: NER pode ou não ajudar. Pelo que entendi, você deseja usar entidades nomeadas (o fato de que estão presentes no texto) como um recurso para a tarefa de classificação principal. Aparentemente, o NER não terá 100% de precisão, pois há um alto nível de ambigüidade. Portanto, o modelo de classificação principal decidirá em quais circunstâncias ele confiará nesse recurso. Pode acontecer (acho que é muito provável) que um modelo básico de classificação dê um peso muito baixo aos resultados do modelo NER. E isso significa que você vai gastar tempo no NER, que (quase) não é usado.
Dim
Não é o que eu quis dizer. Basta criar a spacy.Docpartir de cada texto, iterar sobre seus NERs com doc.entse verificar se algum NER possui .textatributo igual a Apple. Curiosidade, seu primeiro exemplo consiste na Apple.
Szymon Maszke
E se alguém quisesse fazer um modelo, provavelmente envolveria RNNs / CNNs e afins, ajustá-los de acordo, encontrar arquitetura, tipos de células etc., não acho que modelos mais fáceis lidariam bem com desambiguação e contexto. Por que tornar sua vida mais fácil (a menos que você queira aprender algo ao longo do caminho), se alguém já fez isso por você?
Szymon Maszke
@SzymonMaszke seu modelo é mais complicado e mais difícil de treinar. Para que seu modelo funcione para o propósito mencionado, você precisa não apenas encontrar um NE, mas também encontrá-lo no local correto (token). Com o modelo de categorização, sugiro que você otimize o modelo para seu objetivo principal - identifique se é uma empresa Apple ou uma fruta Apple. É mais fácil de treinar e, portanto, provavelmente será mais preciso.
Dim