Comment puis-je créer un modèle pour distinguer les tweets sur Apple (Inc.) des tweets sur la pomme (fruit)?


85

Voir ci-dessous 50 tweets sur "apple". J'ai étiqueté à la main les correspondances positives sur Apple Inc. Ils sont marqués comme 1 ci-dessous.

Voici quelques lignes:

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

Voici l'ensemble de données total: http://pastebin.com/eJuEb4eB

J'ai besoin de construire un modèle qui classe "Apple" (Inc). du reste.

Je ne cherche pas un aperçu général de l'apprentissage automatique, mais plutôt un modèle réel dans le code ( Python préféré).


18

1
Vous étiquetez vos données à la main, mais vous voulez des bibliothèques de cette taille. Est-ce supervisé ou non?
dan

1
Eddi, merci pour le commentaire. Voir l'e-mail de filtrage des e-mails a vraiment aidé quelque chose à cliquer dans mon cerveau. J'ai pu voir un exemple concret de ce que j'essayais de faire, juste appliqué différemment.
SAL

5
Reconnaissance d'entité nommée: nlp.stanford.edu/software/CRF-NER.shtml .
Neil McGuigan

1
Fascinant @NeilMcGuigan. J'ai collé une partie du texte de leur démo ( nlp.stanford.edu:8080/ner/process ) et j'ai été impressionné par la façon dont les différents modèles classaient les mots.
Ryan

Réponses:


39

Je le ferais comme suit:

  1. Divisez la phrase en mots, normalisez-les, construisez un dictionnaire
  2. Avec chaque mot, enregistrez le nombre de fois qu'ils sont apparus dans les tweets sur l'entreprise et le nombre de fois qu'ils sont apparus dans les tweets sur le fruit - ces tweets doivent être confirmés par un humain
  3. Lorsqu'un nouveau tweet arrive, recherchez chaque mot du tweet dans le dictionnaire, calculez un score pondéré - les mots fréquemment utilisés en relation avec l'entreprise obtiendraient un score d'entreprise élevé, et vice versa; des mots rarement utilisés, ou utilisés à la fois avec l'entreprise et le fruit, n'auraient pas beaucoup de points.

2
Merci pour votre réponse à ce sujet. Votre réponse en conjonction avec un commentaire ci-dessus m'a vraiment aidé à trouver une solution. Pouvez-vous m'aider à perfectionner cette solution?
SAL

10
Ceci est une description informelle de la classification bayésienne.
sanityinc

1
Je préfère "l'implémentation pseudo-code de la classification bayésienne" :)
AMADANON Inc.

73

Ce que vous recherchez s'appelle la reconnaissance d'entités nommées . C'est une technique statistique qui utilise (le plus souvent) des champs aléatoires conditionnels pour trouver des entités nommées, en se basant sur le fait d'avoir été formé pour apprendre des choses sur les entités nommées.

Essentiellement, il examine le contenu et le contexte du mot, (en regardant en arrière et en avant quelques mots), pour estimer la probabilité que le mot soit une entité nommée.

Un bon logiciel peut examiner d'autres caractéristiques des mots, telles que leur longueur ou leur forme (comme "Vcv" s'il commence par "voyelle-consonne-voyelle")

Une très bonne bibliothèque (GPL) est le NER de Stanford

Voici la démo: http://nlp.stanford.edu:8080/ner/

Quelques exemples de texte à essayer:

Je mangeais une pomme au siège d'Apple et j'ai pensé à Apple Martin, la fille du gars de Coldplay

(les classificateurs 3class et 4class font les choses correctement)


5
C'était vraiment intéressant. Est-il possible de voir le code pour english.conll.4class.distsim.crf.ser.gz? J'adorerais voir comment on construit quelque chose comme ça.
Ryan

Le code pour NER est open source, mais les données qu'ils ont utilisées dans les conférences CONLL ne le sont pas. Cependant, vous pouvez trouver le Reuters Corpus en ligne sur NIST.
Neil McGuigan

31

J'ai un système semi-fonctionnel qui résout ce problème, open source en utilisant scikit-learn, avec une série d'articles de blog décrivant ce que je fais. Le problème que j'aborde est la désambiguïsation du sens des mots (en choisissant l'une des multiples options de sens des mots ), qui n'est pas la même chose que la reconnaissance d'entités nommées. Mon approche de base est quelque peu compétitive avec les solutions existantes et (surtout) personnalisable.

Il existe des outils NER commerciaux existants (OpenCalais, DBPedia Spotlight et AlchemyAPI) qui pourraient vous donner un résultat commercial assez bon - essayez-les d'abord!

J'en ai utilisé certains pour un projet client (je consulte en NLP / ML à Londres), mais je n'étais pas satisfait de leur rappel ( précision et rappel ). Fondamentalement, ils peuvent être précis (quand ils disent "Ceci est Apple Inc", ils ont généralement raison), mais avec un faible rappel (ils disent rarement "Ceci est Apple Inc." même si pour un humain le tweet concerne évidemment Apple Inc.). J'ai pensé que ce serait un exercice intellectuellement intéressant de créer une version open source adaptée aux tweets. Voici le code actuel: https://github.com/ianozsvald/social_media_brand_disambiguator

Je note - je n'essaye pas de résoudre le problème généralisé de désambiguïsation du sens des mots avec cette approche, juste la marque désambiguïsation de la (entreprises, personnes, etc.) lorsque vous avez déjà leur nom. C'est pourquoi je pense que cette approche simple fonctionnera.

J'ai commencé cela il y a six semaines et il est écrit en Python 2.7 en utilisant scikit-learn. Il utilise une approche très basique. Je vectorise à l'aide d'un vectoriseur de comptage binaire (je ne compte que si un mot apparaît, pas combien de fois) avec 1 à 3  n-grammes . Je ne mets pas à l'échelle avec TF-IDF (TF-IDF est bien lorsque vous avez une longueur de document variable; pour moi, les tweets ne sont qu'une ou deux phrases, et mes résultats de test n'ont pas montré d'amélioration avec TF-IDF).

J'utilise le tokenizer de base qui est très basique mais étonnamment utile. Il ignore @ # (vous perdez donc un peu de contexte) et, bien sûr, ne développe pas une URL. Je m'entraîne ensuite en utilisant la régression logistique , et il semble que ce problème soit quelque peu linéairement séparable (beaucoup de termes pour une classe n'existent pas pour l'autre). Actuellement, j'évite tout raclage / nettoyage (j'essaie la chose la plus simple possible qui pourrait fonctionner).

Le code a un fichier README complet, et vous devriez pouvoir ingérer vos tweets relativement facilement, puis suivre mes suggestions de test.

Cela fonctionne pour Apple car les gens ne mangent ni ne boivent d'ordinateurs Apple, et nous ne tapons ni ne jouons avec des fruits, de sorte que les mots sont facilement divisés en une catégorie ou une autre. Cette condition peut ne pas tenir lorsque l'on considère quelque chose comme #definance pour l'émission de télévision (où les gens utilisent également #definance en relation avec le printemps arabe, les matchs de cricket, la révision d'examen et un groupe de musique). Des approches plus intelligentes pourraient bien être nécessaires ici.

J'ai une série d'articles de blog décrivant ce projet, y compris une présentation d'une heure que j'ai donnée au groupe d'utilisateurs BrightonPython (qui s'est transformée en une présentation plus courte pour 140 personnes à DataScienceLondon).

Si vous utilisez quelque chose comme LogisticRegression (où vous obtenez une probabilité pour chaque classification), vous ne pouvez choisir que les classifications fiables, et de cette façon, vous pouvez forcer une haute précision en échangeant contre le rappel (vous obtenez ainsi des résultats corrects, mais moins nombreux). Vous devrez l'adapter à votre système.

Voici une approche algorithmique possible utilisant scikit-learn:

  • Utilisez un vecteur de décompte binaire (je ne pense pas que le nombre de termes dans les messages courts ajoute beaucoup d'informations car la plupart des mots n'apparaissent qu'une seule fois)
  • Commencez avec un classificateur d'arbre de décision. Il aura des performances explicables (voir Surajustement avec un arbre de décision pour un exemple).
  • Passer à la régression logistique
  • Examinez les erreurs générées par les classificateurs (lisez la sortie exportée de DecisionTree ou regardez les coefficients dans LogisticRegression, repassez les tweets mal classés via le Vectorizer pour voir à quoi ressemble la représentation sous-jacente de Bag of Words - il y aura moins de jetons que vous avez commencé dans le tweet brut - y en a-t-il assez pour une classification?)
  • Regardez mon exemple de code sur https://github.com/ianozsvald/social_media_brand_disambiguator/blob/master/learn1.py pour une version fonctionnelle de cette approche

Choses à considérer:

  • Vous avez besoin d'un plus grand ensemble de données. J'utilise 2000 tweets étiquetés (cela m'a pris cinq heures), et au minimum vous voulez un ensemble équilibré avec> 100 par classe (voir la note sur l'ajustement ci-dessous)
  • Améliorez le tokeniser (très facile avec scikit-learn) pour garder # @ dans les jetons, et peut-être ajouter un détecteur de marque en majuscule (comme le note user @ user2425429)
  • Considérez un classificateur non linéaire (comme la suggestion de @ oiez ci-dessus) lorsque les choses se compliquent. Personnellement, j'ai trouvé que LinearSVC faisait pire que la régression logistique (mais cela peut être dû à l'espace de fonctionnalités de haute dimension que je n'ai pas encore réduit).
  • Une partie spécifique aux tweets du tagueur de discours (à mon humble avis, pas celle de Standford comme le suggère @Neil - elle fonctionne mal sur une mauvaise grammaire Twitter selon mon expérience)
  • Une fois que vous avez beaucoup de jetons, vous voudrez probablement faire une réduction de dimensionnalité (je n'ai pas encore essayé cela - voir mon article de blog sur la pénalisation de LogisticRegression l1 l2)

Ré. sur-ajustement. Dans mon ensemble de données avec 2000 éléments, j'ai un instantané de 10 minutes sur Twitter des tweets «apple». Environ 2/3 des tweets sont pour Apple Inc, 1/3 pour d'autres usages Apple. Je tire un sous-ensemble équilibré (environ 584 lignes je pense) de chaque classe et fais une validation croisée de cinq fois pour la formation.

Comme je n'ai qu'une fenêtre de temps de 10 minutes, j'ai beaucoup de tweets sur le même sujet, et c'est probablement pourquoi mon classificateur se débrouille si bien par rapport aux outils existants - il aura sur-ajusté les fonctionnalités de formation sans bien généraliser (alors que le commercial existant les outils fonctionnent moins bien sur ce snapshop, mais de manière plus fiable sur un ensemble plus large de données). Je vais élargir ma fenêtre de temps pour tester cela comme un travail ultérieur.


Je n'ai pas eu le plaisir de parcourir votre code et d'essayer de dupliquer / émuler / éduquer, mais je vous dois des excuses pour ne pas avoir accordé les 50 points complets de la prime. J'étais absent de SO pendant le week-end et j'ai raté la date limite pour l'attribuer. Heureusement, la communauté SO est intervenue et a jugé bon de vous attribuer 25 points.
Ryan

1
Pas de problème :-) Le code, le README et les articles du blog devraient vous donner une idée de mon approche. C'est délibérément simple mais semble fonctionner correctement.
Ian Ozsvald

12

Vous pouvez faire ce qui suit:

  1. Faites un dict de mots contenant leur nombre d'occurrences dans les tweets liés aux fruits et à l'entreprise. Cela peut être réalisé en lui donnant quelques exemples de tweets dont nous connaissons l'inclinaison.

  2. En utilisant suffisamment de données antérieures, nous pouvons connaître la probabilité qu'un mot apparaisse dans un tweet à propos de apple inc.

  3. Multipliez les probabilités individuelles des mots pour obtenir la probabilité de tout le tweet.

Un exemple simplifié:

p_f = Probabilité de tweets de fruits.

p_w_f = Probabilité qu'un mot apparaisse dans un tweet de fruits.

p_t_f = Probabilité combinée de tous les mots du tweet sur un tweet de fruits = p_w1_f * p_w2_f * ...

p_f_t = Probabilité de fruit étant donné un tweet particulier.

p_c, p_w_c, p_t_c, p_c_t sont des valeurs respectives pour l'entreprise.

Un lisseur laplacien de valeur 1 est ajouté pour éliminer le problème de la fréquence zéro des nouveaux mots qui ne sont pas là dans notre base de données.

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"

9

Si vous ne rencontrez pas de problème lors de l'utilisation d'une bibliothèque externe, je vous recommande scikit-learn car il peut probablement le faire mieux et plus rapidement que tout ce que vous pourriez coder vous-même. Je ferais juste quelque chose comme ça:

Construisez votre corpus. J'ai fait la liste des compréhensions pour plus de clarté, mais en fonction de la façon dont vos données sont stockées, vous devrez peut-être faire différentes choses:

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)

L'important est que vous vous retrouvez avec deux listes qui ressemblent à ceci:

([['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])

Les [1, 1, 0, 0] représentent les étiquettes positives et négatives.

Ensuite, vous créez un pipeline! Pipeline est une classe scikit-learn qui facilite l'enchaînement des étapes de traitement de texte afin que vous n'ayez à appeler qu'un seul objet lors de l'apprentissage / de la prédiction:

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

À l'intérieur du pipeline, il y a trois étapes de traitement. Le CountVectorizer tokenise les mots, les divise, les compte et transforme les données en une matrice clairsemée. Le TfidfTransformer est facultatif, et vous voudrez peut-être le supprimer en fonction de la note de précision (faire des tests de validation croisée et une recherche de grille pour les meilleurs paramètres est un peu impliqué, donc je ne vais pas y entrer ici). Le LinearSVC est un algorithme de classification de texte standard.

Enfin, vous prédisez la catégorie des tweets:

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

Encore une fois, le tweet doit être dans une liste, j'ai donc supposé qu'il entrait la fonction sous forme de chaîne.

Mettez tout cela dans une classe ou autre, et vous avez terminé. Du moins, avec cet exemple très basique.

Je n'ai pas testé ce code, il peut donc ne pas fonctionner si vous faites simplement un copier-coller, mais si vous souhaitez utiliser scikit-learn, cela devrait vous donner une idée de par où commencer.

EDIT: essayé d'expliquer les étapes plus en détail.


6

L'utilisation d'un arbre de décision semble fonctionner assez bien pour ce problème. Au moins, il produit une précision plus élevée qu'un classificateur bayésien naïf avec les fonctionnalités que j'ai choisies.

Si vous voulez jouer avec certaines possibilités, vous pouvez utiliser le code suivant, qui nécessite l'installation de nltk. Le livre nltk est également disponible gratuitement en ligne, vous voudrez peut-être lire un peu comment tout cela fonctionne réellement: 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()

1
Comment cela marche-t-il? Je ne vois pas vos "fonctionnalités choisies" dans votre code. Choisit-il automatiquement les fonctionnalités en fonction de l'ensemble d'entraînement? Ou est-il stocké dict()ailleurs? Je pense que si l'ensemble de formation est assez grand, un ordinateur ne devrait-il pas être capable de comprendre les fonctionnalités lui-même? (non supervisé?)
Ryan

2
Les fonctionnalités sont extraites à l'aide de la fonction tweet_features. Il supprime essentiellement les URL des tweets, puis crée un dict de fonctionnalité dont les entrées lisent quelque chose comme 'hasBigram (foo, bar)' = True.
Paul Dubs

1
Alors, 'hasBigram(foo,bar)' = Trueoù la chaîne de tweet comprend-elle foo bar? Donc, il construit des bigrammes et des trigrammes pour chaque tweet et le signale dans la fonction positive dict()? Par conséquent, étant donné le tweet, "alpha beta gamma delta"il construira des bigrammes dict () pour alpha,beta; beta,gamma; and gamma,delta;et des trigrammes pour alpha,beta,gammaet beta,gamma,delta? Et à partir des bi et tri grammes positifs et négatifs donnés, l'arbre de décision ou les classificateurs bayes peuvent faire leur magie?
Ryan

2
Exactement. Lorsque vous utilisez le classificateur bayes, vous pouvez également obtenir les fonctionnalités les plus utiles en appelant "show_most_informative_features ()" dessus.
Paul Dubs

Paul, j'ai construit une version PHP brute de ceci et vous avez tout à fait raison. C'est un moyen très efficace de créer un dictionnaire pondéré. Je pense que cela pourrait facilement évoluer sans avoir à créer manuellement tous les mots-clés. J'ai hâte d'en savoir plus sur la façon de faire cela dans une bibliothèque d'apprentissage automatique standard.
Ryan

5

Merci pour les commentaires jusqu'ici. Voici une solution de travail que j'ai préparée avec PHP. Je serais toujours intéressé d'entendre des autres une approche plus algorithmique de cette même solution.

<?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;
}
?>

Les sorties ci-dessus:

           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.

4

Dans tous les exemples que vous avez donnés, Apple (inc) était soit appelé A pple soit apple inc , donc un moyen possible pourrait être de rechercher:

  • un «A» majuscule dans Apple

  • un "inc" après la pomme

  • des mots / expressions comme "OS", "système d'exploitation", "Mac", "iPhone", ...

  • ou une combinaison d'entre eux


1
Dans la fonction, j'ai fait un strtolower pour filtrer les lettres majuscules. Un peu brut, mais ça a marché.
SAL

@SAL Je ne m'attendais pas à ce que ce soit très utile, mais si vous avez une limite de temps, alors ...
user2425429

4

Pour simplifier un peu les réponses basées sur les champs aléatoires conditionnels ... le contexte est énorme ici. Vous voudrez choisir dans ces tweets qui montrent clairement à Apple la société contre Apple le fruit. Permettez-moi de présenter ici une liste de fonctionnalités qui pourraient vous être utiles pour commencer. Pour plus d'informations, recherchez la segmentation des phrases nominales et quelque chose appelé étiquettes BIO. Voir ( http://www.cis.upenn.edu/~pereira/papers/crf.pdf )

Mots environnants: créez un vecteur de caractéristiques pour le mot précédent et le mot suivant, ou si vous voulez plus de caractéristiques, peut-être les 2 mots précédents et les 2 suivants. Vous ne voulez pas trop de mots dans le modèle ou il ne correspondra pas très bien aux données. Dans le traitement du langage naturel, vous voudrez garder cela aussi général que possible.

Les autres fonctionnalités à tirer des mots environnants sont les suivantes:

Si le premier caractère est une majuscule

Si le dernier caractère du mot est un point

La partie du discours du mot (Rechercher une partie du balisage de la parole)

Le texte lui-même du mot

Je ne le conseille pas, mais pour donner plus d'exemples de fonctionnalités spécifiquement pour Apple:

WordIs (Apple)

NextWordIs (Inc.)

Tu obtiens le point. Pensez à la reconnaissance d'entités nommées comme décrivant une séquence, puis utilisez des mathématiques pour indiquer à un ordinateur comment calculer cela.

Gardez à l'esprit que le traitement du langage naturel est un système basé sur un pipeline. En règle générale, vous divisez les choses en phrases, passez à la tokenisation, puis effectuez une partie du balisage vocal ou même de l'analyse des dépendances.

Tout cela pour vous donner une liste des fonctionnalités que vous pouvez utiliser dans votre modèle pour identifier ce que vous recherchez.


3

Il existe une très bonne bibliothèque pour traiter du texte en langage naturel en Python appelée nltk. Vous devriez y jeter un œil.

Une stratégie que vous pourriez essayer est de regarder les n-grammes (groupes de mots) avec le mot «pomme» en eux. Certains mots sont plus susceptibles d'être utilisés à côté de "pomme" lorsque vous parlez du fruit, d'autres lorsque vous parlez de l'entreprise, et vous pouvez les utiliser pour classer les tweets.


1
Merci Manetheran. Je ne suis pas l'affiche originale, mais je suis également intéressé par la réponse. Pour la prime, je recherche du code (même en utilisant nltk) qui peut m'aider à démarrer dans la bonne direction avec une tâche d'apprentissage automatique "bonjour le monde". La pomme (inc) contre la pomme (fruit) semble être une affectation parfaite.
Ryan

3

Utilisez LibShortText . Cet utilitaire Python a déjà été réglé pour fonctionner pour de courtes tâches de catégorisation de texte, et il fonctionne bien. Le maximum que vous aurez à faire est d'écrire une boucle pour choisir la meilleure combinaison d'indicateurs. Je l'ai utilisé pour faire une classification supervisée des actes de parole dans les e-mails et les résultats étaient jusqu'à 95-97% précis (lors de la validation croisée 5 fois!).

Et il vient des créateurs de LIBSVM et LIBLINEAR dont l' implémentation de la machine vectorielle de support (SVM) est utilisée dans sklearn et cran, vous pouvez donc être raisonnablement assuré que leur implémentation n'est pas boguée.


2

Créez un filtre AI pour distinguer Apple Inc (la société) de la pomme (le fruit). Puisqu'il s'agit de tweets, définissez votre ensemble d'entraînement avec un vecteur de 140 champs, chaque champ étant le caractère écrit dans le tweet à la position X (0 à 139). Si le tweet est plus court, donnez simplement une valeur pour être vide.

Ensuite, construisez un ensemble d'entraînement suffisamment grand pour obtenir une bonne précision (subjective à votre goût). Attribuez une valeur de résultat à chaque tweet, un tweet Apple Inc obtient 1 (vrai) et un tweet pomme (fruit) obtient 0. Ce serait un cas d' apprentissage supervisé dans une régression logistique .

C'est l'apprentissage automatique, est généralement plus facile à coder et fonctionne mieux. Il doit apprendre de l'ensemble que vous lui donnez, et il n'est pas codé en dur.

Je ne connais pas Python , donc je ne peux pas écrire le code pour cela, mais si vous deviez prendre plus de temps pour la logique et la théorie de l'apprentissage automatique, vous voudrez peut-être regarder la classe que je suis.

Essayez le cours Coursera Machine Learning par Andrew Ng . Vous apprendrez l'apprentissage automatique sur MATLAB ou Octave , mais une fois que vous aurez les bases, vous serez en mesure d'écrire l'apprentissage automatique dans n'importe quelle langue si vous comprenez les mathématiques simples (simples en régression logistique).

Autrement dit, obtenir le code de quelqu'un ne vous permettra pas de comprendre ce qui se passe dans le code d'apprentissage automatique. Vous voudrez peut-être investir quelques heures sur le sujet pour voir ce qui se passe réellement.


Merci Fawar. J'espérais du code sur ce "bonjour le monde" dans ce but précis - pour apprendre comment fonctionne ML. Je vais cependant chercher la classe. Cela semble bon.
Ryan

0

Je recommanderais d'éviter les réponses suggérant la reconnaissance des entités. Parce que cette tâche est d'abord une classification de texte et une reconnaissance d'entité en second lieu (vous pouvez le faire sans la reconnaissance d'entité du tout).

Je pense que le chemin le plus rapide vers les résultats sera spacy + prodigy . Spacy a bien pensé un modèle pour la langue anglaise, vous n'avez donc pas à créer le vôtre. Alors que prodigy permet de créer rapidement des ensembles de données d'entraînement et d'ajuster le modèle Spacy en fonction de vos besoins.

Si vous avez suffisamment d'échantillons, vous pouvez avoir un modèle décent en 1 jour.


En même temps, spaCyest-ce que le nercomposant pipeline est- il utile pour cette classification? Je suppose que leur modèle peut reconnaître Apple(car c'est l'une des entreprises les plus grandes et les plus connues au monde) bien mieux qu'un modèle que vous pouvez créer en un jour.
Szymon Maszke

@Szymon: NER peut aider ou non. Si je comprends bien, vous souhaitez utiliser des entités nommées (le fait qu'elles soient présentes dans le texte) pour être une fonctionnalité de la tâche de classification principale. Apparemment, le NER n'aura pas une précision de 100% car il y a un niveau élevé d'ambiguïté. Ainsi, le modèle de classification principal décidera dans quelles circonstances il fera confiance à cette fonctionnalité. Il peut s'avérer (je pense que c'est très probable) qu'un modèle de classification de base donnera un poids très faible aux résultats du modèle NER. Et cela signifie que vous passerez du temps sur NER, qui n'est (presque) pas utilisé.
Dim

Pas ce que je voulais dire. Créez simplement à spacy.Docpartir de chaque texte, parcourez leurs doc.entsNER avec et vérifiez si un NER a un .textattribut égal à Apple. Fait amusant, leur premier exemple consiste en Apple.
Szymon Maszke

Et si quelqu'un voulait créer un modèle, cela impliquerait très probablement des RNN / CNN et autres, les régler en conséquence, trouver une architecture, des types de cellules, etc., je ne pense pas que des modèles plus faciles géreraient bien la désambiguïsation et le contexte. Pourquoi vous faciliter la vie (à moins que vous ne vouliez apprendre quelque chose en cours de route), si quelqu'un l'a déjà fait pour vous?
Szymon Maszke

@SzymonMaszke votre modèle est plus compliqué et plus difficile à former. Pour que votre modèle fonctionne dans le but mentionné, vous devez non seulement trouver un élément de réseau, mais également le trouver à un endroit correct (jeton). Avec le modèle de catégorisation, je vous suggère d'optimiser le modèle pour votre objectif principal - identifier qu'il s'agit d'une entreprise Apple ou d'un fruit Apple. C'est plus facile à entraîner et donc très probablement plus précis.
Dim
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.