Wie kann ich ein Modell erstellen, um Tweets über Apple (Inc.) von Tweets über Apfel (Obst) zu unterscheiden?


84

Siehe unten für 50 Tweets über "Apfel". Ich habe die positiven Übereinstimmungen mit Apple Inc. von Hand beschriftet. Sie sind unten als 1 gekennzeichnet.

Hier sind ein paar Zeilen:

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

Hier ist der Gesamtdatensatz: http://pastebin.com/eJuEb4eB

Ich muss ein Modell erstellen, das "Apple" (Inc) klassifiziert. von dem Rest.

Ich suche keinen allgemeinen Überblick über maschinelles Lernen, sondern ein aktuelles Modell im Code ( Python bevorzugt).


17

1
Sie beschriften Ihre Daten von Hand, möchten jedoch skalierbare Bibliotheken. Ist das überwacht oder unbeaufsichtigt?
Dan

1
Eddi, danke für den Kommentar. Die E-Mail-Filterung von E-Mails hat mir wirklich geholfen, etwas in meinem Gehirn anzuklicken. Ich konnte ein reales Beispiel dafür sehen, was ich versuchte, nur anders angewendet.
SAL

4
Erkennung benannter Entitäten: nlp.stanford.edu/software/CRF-NER.shtml .
Neil McGuigan

1
Faszinierende @NeilMcGuigan. Ich habe einen Teil des Textes in ihre Demo eingefügt ( nlp.stanford.edu:8080/ner/process ) und war beeindruckt, wie verschiedene Modelle die Wörter klassifizierten.
Ryan

Antworten:


38

Ich würde es wie folgt machen:

  1. Teilen Sie den Satz in Wörter auf, normalisieren Sie sie und erstellen Sie ein Wörterbuch
  2. Speichern Sie mit jedem Wort, wie oft sie in Tweets über das Unternehmen vorkamen und wie oft sie in Tweets über die Frucht vorkamen - diese Tweets müssen von einem Menschen bestätigt werden
  3. Wenn ein neuer Tweet eingeht, suchen Sie jedes Wort im Tweet im Wörterbuch, berechnen Sie eine gewichtete Punktzahl - Wörter, die häufig in Bezug auf das Unternehmen verwendet werden, erhalten eine hohe Unternehmensbewertung und umgekehrt. Wörter, die selten verwendet werden oder sowohl für die Firma als auch für die Früchte verwendet werden, haben keine große Punktzahl.

2
Vielen Dank für Ihre Antwort darauf. Ihre Antwort in Verbindung mit einem Kommentar oben hat mir wirklich geholfen, eine Lösung zu finden. Können Sie mir helfen, diese Lösung zu verbessern?
SAL

9
Dies ist eine informelle Beschreibung der Bayes'schen Klassifikation.
Sanityinc

1
Ich bevorzuge "Pseudocode-Implementierung der Bayes'schen Klassifikation" :)
AMADANON Inc.

72

Was Sie suchen, heißt Named Entity Recognition . Es ist eine statistische Technik, die (am häufigsten) bedingte Zufallsfelder verwendet , um benannte Entitäten zu finden, basierend darauf, dass sie geschult wurden, um etwas über benannte Entitäten zu lernen.

Im Wesentlichen wird der Inhalt und der Kontext des Wortes betrachtet (wobei einige Wörter vor- und zurückgeschaut werden), um die Wahrscheinlichkeit abzuschätzen, dass das Wort eine benannte Entität ist.

Gute Software kann andere Merkmale von Wörtern wie ihre Länge oder Form betrachten (wie "Vcv", wenn es mit "Vokal-Konsonant-Vokal" beginnt).

Eine sehr gute Bibliothek (GPL) ist Stanfords NER

Hier ist die Demo: http://nlp.stanford.edu:8080/ner/

Einige Beispieltexte zum Ausprobieren:

Ich aß einen Apfel in der Apple-Zentrale und dachte an Apple Martin, die Tochter des Coldplay-Typen

(Die Klassifikatoren 3 und 4 machen es richtig)


4
Das war wirklich interessant. Ist es möglich, den Code für anzuzeigen english.conll.4class.distsim.crf.ser.gz? Ich würde gerne sehen, wie man so etwas baut.
Ryan

Der Code für NER ist Open Source, die Daten, die sie in den CONLL-Konferenzen verwendet haben, jedoch nicht. Sie finden den Reuters Corpus jedoch online bei NIST.
Neil McGuigan

29

Ich habe ein semi-funktionierendes System, das dieses Problem löst, Open-Source mit Scikit-Learn, mit einer Reihe von Blog-Posts, die beschreiben, was ich tue. Das Problem, das ich anpacke, ist die Wortsinn-Disambiguierung (Auswahl einer von mehreren Wortsinn- Optionen), die nicht mit der Erkennung benannter Entitäten identisch ist. Mein grundlegender Ansatz ist mit bestehenden Lösungen etwas konkurrenzfähig und (entscheidend) anpassbar.

Es gibt einige vorhandene kommerzielle NER-Tools (OpenCalais, DBPedia Spotlight und AlchemyAPI), mit denen Sie möglicherweise ein ausreichend kommerzielles Ergebnis erzielen - probieren Sie diese zuerst aus!

Ich habe einige davon für ein Kundenprojekt verwendet (ich berate mich mit NLP / ML in London), war aber mit ihrem Rückruf ( Präzision und Rückruf ) nicht zufrieden . Grundsätzlich können sie präzise sein (wenn sie sagen "Dies ist Apple Inc", sind sie normalerweise korrekt), aber mit geringem Rückruf (sie sagen selten "Dies ist Apple Inc", obwohl der Tweet für einen Menschen offensichtlich von Apple Inc handelt). Ich dachte, es wäre eine intellektuell interessante Übung, eine Open-Source-Version zu erstellen, die auf Tweets zugeschnitten ist. Hier ist der aktuelle Code: https://github.com/ianozsvald/social_media_brand_disambiguator

Ich werde beachten Sie - ich versuche nicht , das verallgemeinerte Disambiguierung Problem bei diesem Ansatz, nur zu lösen Marke Begriffsklärung (Unternehmen, Menschen, etc.) , wenn Sie bereits ihren Namen haben. Deshalb glaube ich, dass dieser einfache Ansatz funktionieren wird.

Ich habe vor sechs Wochen damit begonnen und es ist in Python 2.7 mit scikit-learn geschrieben. Es verwendet einen sehr grundlegenden Ansatz. Ich vektorisiere mit einem Binärzählvektorisierer (ich zähle nur, ob ein Wort erscheint, nicht wie oft) mit 1-3  n-Gramm . Ich skaliere nicht mit TF-IDF (TF-IDF ist gut, wenn Sie eine variable Dokumentlänge haben; für mich sind die Tweets nur ein oder zwei Sätze, und meine Testergebnisse zeigten keine Verbesserung mit TF-IDF).

Ich benutze den einfachen Tokenizer, der sehr einfach, aber überraschend nützlich ist. Es ignoriert @ # (so dass Sie etwas Kontext verlieren) und erweitert natürlich keine URL. Ich trainiere dann mit logistischer Regression und es scheint, dass dieses Problem etwas linear trennbar ist (viele Begriffe für eine Klasse existieren für die andere nicht). Momentan vermeide ich jegliches Stemming / Reinigen (ich versuche die einfachste mögliche Sache, die funktionieren könnte).

Der Code hat eine vollständige README-Datei, und Sie sollten in der Lage sein, Ihre Tweets relativ einfach aufzunehmen und dann meinen Testvorschlägen zu folgen.

Dies funktioniert für Apple, da die Leute weder Apple-Computer essen oder trinken, noch Obst tippen oder damit spielen, sodass die Wörter leicht in die eine oder andere Kategorie unterteilt werden können. Diese Bedingung gilt möglicherweise nicht, wenn Sie etwas wie #definance für die TV-Show in Betracht ziehen (wo Leute #definance auch in Bezug auf den Arabischen Frühling, Cricket-Matches, Prüfungsrevisionen und eine Musikband verwenden). Hier sind möglicherweise klügere Ansätze erforderlich.

Ich habe eine Reihe von Blog-Posts , die dieses Projekt beschreiben, einschließlich einer einstündigen Präsentation, die ich bei der BrightonPython-Benutzergruppe gehalten habe (die zu einer kürzeren Präsentation für 140 Personen bei DataScienceLondon wurde).

Wenn Sie so etwas wie LogisticRegression verwenden (wobei Sie für jede Klassifizierung eine Wahrscheinlichkeit erhalten), können Sie nur die zuverlässigen Klassifizierungen auswählen. Auf diese Weise können Sie eine hohe Präzision erzwingen, indem Sie gegen den Rückruf handeln (damit Sie korrekte Ergebnisse erhalten, aber weniger davon). Sie müssen dies auf Ihr System abstimmen.

Hier ist ein möglicher algorithmischer Ansatz mit Scikit-Learn:

  • Verwenden Sie einen Binary CountVectorizer (ich glaube nicht, dass Termzählungen in Kurznachrichten viele Informationen hinzufügen, da die meisten Wörter nur einmal vorkommen).
  • Beginnen Sie mit einem Entscheidungsbaumklassifikator. Die Leistung ist erklärbar ( ein Beispiel finden Sie unter Überanpassung mit einem Entscheidungsbaum ).
  • Wechseln Sie zur logistischen Regression
  • Untersuchen Sie die von den Klassifizierern generierten Fehler (lesen Sie die exportierte Ausgabe des DecisionTree oder sehen Sie sich die Koeffizienten in LogisticRegression an, arbeiten Sie die falsch klassifizierten Tweets durch den Vectorizer zurück, um festzustellen, wie die zugrunde liegende Bag of Words-Darstellung aussieht - dort gibt es weniger Token als Du hast mit dem rohen Tweet angefangen - gibt es genug für eine Klassifizierung?)
  • In meinem Beispielcode unter https://github.com/ianozsvald/social_media_brand_disambiguator/blob/master/learn1.py finden Sie eine funktionierende Version dieses Ansatzes

Dinge, die man beachten muss:

  • Sie benötigen einen größeren Datensatz. Ich verwende 2000 beschriftete Tweets (ich habe fünf Stunden gebraucht) und mindestens ein ausgewogenes Set mit> 100 pro Klasse (siehe Hinweis zur Überanpassung unten).
  • Verbessern Sie den Tokeniser (sehr einfach mit Scikit-Learn), um # @ in Token zu behalten, und fügen Sie möglicherweise einen Detektor für Großbuchstaben hinzu (wie Benutzer @ user2425429 feststellt).
  • Betrachten Sie einen nichtlinearen Klassifikator (wie der obige Vorschlag von @ oiez), wenn es schwieriger wird. Persönlich stellte ich fest, dass LinearSVC schlechter abschneidet als die logistische Regression (dies kann jedoch an dem hochdimensionalen Merkmalsraum liegen, den ich noch nicht reduziert habe).
  • Ein tweet-spezifischer Teil des Sprach-Taggers (meiner bescheidenen Meinung nach nicht Standfords, wie @Neil vorschlägt - meiner Erfahrung nach funktioniert er bei schlechter Twitter-Grammatik schlecht).
  • Sobald Sie viele Token haben, möchten Sie wahrscheinlich eine gewisse Reduzierung der Dimensionalität vornehmen (ich habe dies noch nicht versucht - siehe meinen Blog-Beitrag zur Bestrafung von LogisticRegression l1 l2).

Re. Überanpassung. In meinem Datensatz mit 2000 Elementen habe ich einen 10-minütigen Schnappschuss von Twitter von "Apfel" -Tweets. Etwa 2/3 der Tweets sind für Apple Inc, 1/3 für andere Apple-Zwecke. Ich ziehe eine ausgewogene Teilmenge (ungefähr 584 Zeilen, glaube ich) jeder Klasse heraus und mache eine fünffache Kreuzvalidierung für das Training.

Da ich nur ein Zeitfenster von 10 Minuten habe, habe ich viele Tweets zum gleichen Thema, und dies ist wahrscheinlich der Grund, warum mein Klassifikator im Vergleich zu vorhandenen Tools so gut abschneidet - er passt zu den Trainingsfunktionen, ohne gut zu verallgemeinern (während der vorhandene Werbespot) Tools schneiden in diesem Snapshop schlechter ab, jedoch zuverlässiger für einen größeren Datensatz. Ich werde mein Zeitfenster erweitern, um dies als nachfolgende Arbeit zu testen.


Ich hatte nicht das Vergnügen, Ihren Code durchzusehen und zu versuchen, ihn zu duplizieren / zu emulieren / zu erziehen, aber ich schulde Ihnen eine Entschuldigung dafür, dass Sie nicht die vollen 50 Punkte des Kopfgeldes vergeben haben. Ich war über das Wochenende von SO weg und habe die Frist für die Vergabe verpasst. Zum Glück hat die SO-Community eingegriffen und es für angebracht gehalten, Ihnen 25 Punkte zu verleihen.
Ryan

1
Kein Problem :-) Der Code, die README-Datei und die Blog-Beiträge sollten Ihnen eine Vorstellung von meinem Ansatz geben. Es ist absichtlich einfach, scheint aber in Ordnung zu sein.
Ian Ozsvald

11

Sie können Folgendes tun:

  1. Machen Sie ein Diktat aus Wörtern, die die Anzahl ihrer Vorkommen in Tweets zu Früchten und Unternehmen enthalten. Dies kann erreicht werden, indem man einige Beispiel-Tweets füttert, deren Neigung wir kennen.

  2. Mit genügend vorherigen Daten können wir die Wahrscheinlichkeit ermitteln, mit der ein Wort in einem Tweet über apple inc. Vorkommt.

  3. Multiplizieren Sie einzelne Wahrscheinlichkeiten von Wörtern, um die Wahrscheinlichkeit des gesamten Tweets zu erhalten.

Ein vereinfachtes Beispiel:

p_f = Wahrscheinlichkeit von Frucht-Tweets.

p_w_f = Wahrscheinlichkeit, dass ein Wort in einem Frucht-Tweet vorkommt.

p_t_f = Kombinierte Wahrscheinlichkeit, dass alle Wörter in einem Tweet einen Frucht-Tweet enthalten = p_w1_f * p_w2_f * ...

p_f_t = Wahrscheinlichkeit von Früchten bei einem bestimmten Tweet.

p_c, p_w_c, p_t_c, p_c_t sind entsprechende Werte für das Unternehmen.

Ein Laplace-Glätter mit dem Wert 1 wird hinzugefügt, um das Problem der Nullhäufigkeit neuer Wörter zu beseitigen, die nicht in unserer Datenbank vorhanden sind.

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

Wenn Sie kein Problem mit der Verwendung einer externen Bibliothek haben, würde ich scikit-learn empfehlen , da dies wahrscheinlich besser und schneller möglich ist als alles, was Sie selbst codieren könnten. Ich würde einfach so etwas machen:

Bauen Sie Ihren Korpus. Ich habe das Listenverständnis aus Gründen der Übersichtlichkeit durchgeführt, aber je nachdem, wie Ihre Daten gespeichert sind, müssen Sie möglicherweise verschiedene Dinge tun:

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)

Das Wichtigste ist, dass Sie am Ende zwei Listen haben, die so aussehen:

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

Die [1, 1, 0, 0] repräsentieren die positiven und negativen Bezeichnungen.

Dann erstellen Sie eine Pipeline! Pipeline ist eine Scikit-Lernklasse, die es einfach macht, Textverarbeitungsschritte miteinander zu verketten, sodass Sie beim Training / Vorhersagen nur ein Objekt aufrufen müssen:

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

Innerhalb der Pipeline gibt es drei Verarbeitungsschritte. Der CountVectorizer markiert die Wörter, teilt sie auf, zählt sie und wandelt die Daten in eine spärliche Matrix um. Der TfidfTransformer ist optional und kann je nach Genauigkeitsbewertung entfernt werden (Kreuzvalidierungstests und eine Rastersuche nach den besten Parametern sind etwas kompliziert, daher werde ich hier nicht darauf eingehen). Der LinearSVC ist ein Standardalgorithmus zur Textklassifizierung.

Schließlich sagen Sie die Kategorie der Tweets voraus:

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

Auch hier muss der Tweet in einer Liste enthalten sein, daher habe ich angenommen, dass er die Funktion als Zeichenfolge eingibt.

Setzen Sie all diese in eine Klasse oder was auch immer, und Sie sind fertig. Zumindest mit diesem sehr einfachen Beispiel.

Ich habe diesen Code nicht getestet, daher funktioniert er möglicherweise nicht, wenn Sie nur kopieren und einfügen. Wenn Sie jedoch scikit-learn verwenden möchten, sollten Sie eine Vorstellung davon haben, wo Sie anfangen sollen.

BEARBEITEN: versuchte die Schritte genauer zu erklären.


6

Die Verwendung eines Entscheidungsbaums scheint für dieses Problem recht gut zu funktionieren. Zumindest erzeugt es eine höhere Genauigkeit als ein naiver Bayes-Klassifikator mit meinen gewählten Merkmalen.

Wenn Sie mit einigen Möglichkeiten herumspielen möchten, können Sie den folgenden Code verwenden, für den nltk installiert sein muss. Das nltk-Buch ist auch online frei verfügbar. Lesen Sie daher ein wenig darüber, wie dies alles tatsächlich funktioniert: 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
wie funktioniert das? Ich sehe Ihre "ausgewählten Funktionen" nicht in Ihrem Code. Wählt es automatisch Funktionen basierend auf dem Trainingssatz aus? Oder ist es dict()woanders gespeichert ? Ich denke, wenn das Trainingsset groß genug ist, sollte ein Computer dann nicht in der Lage sein, die Funktionen selbst herauszufinden? (unbeaufsichtigt?)
Ryan

2
Die Funktionen werden mit der Funktion tweet_features extrahiert. Grundsätzlich werden die URLs aus den Tweets entfernt und anschließend ein Feature-Dikt erstellt, dessen Einträge etwa "hasBigram (foo, bar)" = True lauten.
Paul Dubs

1
Also 'hasBigram(foo,bar)' = Truewo tweet Zeichenfolge enthält foo bar? Also werden Bigrams und Trigramme für jeden Tweet erstellt und im positiven Feature markiert dict()? Daher wird der Tweet angesichts des Tweets "alpha beta gamma delta"dict () Bigrams für alpha,beta; beta,gamma; and gamma,delta;und Trigramme für alpha,beta,gammaund beta,gamma,delta? Und aus den gegebenen positiven und negativen Bi- und Tri-Gramm können die Entscheidungsbaum- oder Bayes-Klassifikatoren ihre Magie entfalten?
Ryan

2
Genau. Wenn Sie den Bayes-Klassifikator verwenden, können Sie die nützlichsten Funktionen auch erhalten, indem Sie "show_most_informative_features ()" darauf aufrufen.
Paul Dubs

Paul, ich habe eine grobe PHP-Version davon gebaut und du bist absolut korrekt. Dies ist eine sehr effiziente Methode zum Erstellen eines gewichteten Wörterbuchs. Ich denke, dies könnte leicht skaliert werden, ohne dass alle Schlüsselwörter manuell erstellt werden müssen. Ich freue mich darauf, mehr darüber zu erfahren, wie dies in einer Standardbibliothek für maschinelles Lernen funktioniert.
Ryan

5

Vielen Dank für die bisherigen Kommentare. Hier ist eine funktionierende Lösung, die ich mit PHP vorbereitet habe. Ich wäre immer noch daran interessiert, von anderen einen algorithmischeren Ansatz für dieselbe Lösung zu hören.

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

Die obigen Ausgaben:

           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

In allen Beispielen, die Sie angegeben haben, wurde Apple (inc) entweder als A pple oder apple inc bezeichnet . Ein möglicher Weg könnte also darin bestehen, nach folgenden Elementen zu suchen:

  • eine Hauptstadt "A" in Apple

  • ein "inc" nach Apfel

  • Wörter / Sätze wie "OS", "Betriebssystem", "Mac", "iPhone", ...

  • oder eine Kombination von ihnen


1
In der Funktion habe ich einen Strtolower gemacht, um die Großbuchstaben herauszufiltern. Ein bisschen grob, aber es hat funktioniert.
SAL

@SAL Ich habe nicht erwartet, dass es sehr nützlich ist, aber wenn Sie ein Zeitlimit haben, dann ...
user2425429

4

Um Antworten basierend auf bedingten Zufallsfeldern ein wenig zu vereinfachen ... ist der Kontext hier riesig. Sie sollten in diesen Tweets herausgreifen, die Apple die Firma gegen Apfel die Frucht deutlich zeigen. Lassen Sie mich hier eine Liste von Funktionen skizzieren, die für Sie zunächst nützlich sein könnten. Weitere Informationen finden Sie unter Chunking von Nominalphrasen und BIO-Labels. Siehe ( http://www.cis.upenn.edu/~pereira/papers/crf.pdf )

Umgebende Wörter: Erstellen Sie einen Merkmalsvektor für das vorherige und das nächste Wort, oder wenn Sie weitere Merkmale wünschen, möglicherweise für die vorherigen 2 und die nächsten 2 Wörter. Sie möchten nicht zu viele Wörter im Modell haben oder es passt nicht sehr gut zu den Daten. In der Verarbeitung natürlicher Sprache möchten Sie dies so allgemein wie möglich halten.

Weitere Funktionen, die Sie aus den umgebenden Wörtern erhalten können, sind:

Ob das erste Zeichen eine Hauptstadt ist

Ob das letzte Zeichen im Wort ein Punkt ist

Der Teil der Sprache des Wortes (Teil der Sprachkennzeichnung nachschlagen)

Der Text selbst des Wortes

Ich rate nicht dazu, aber um weitere Beispiele für Funktionen speziell für Apple zu nennen:

WordIs (Apple)

NextWordIs (Inc.)

Du verstehst, worum es geht. Stellen Sie sich die Erkennung benannter Entitäten so vor, dass sie eine Sequenz beschreibt und dann mithilfe von Mathematik einem Computer mitteilt, wie diese zu berechnen ist.

Beachten Sie, dass die Verarbeitung natürlicher Sprache ein Pipeline-basiertes System ist. In der Regel teilen Sie Dinge in Sätze auf, wechseln zur Tokenisierung und führen dann einen Teil der Sprachkennzeichnung oder sogar der Analyse von Abhängigkeiten durch.

Dies ist alles, um eine Liste der Funktionen zu erhalten, die Sie in Ihrem Modell verwenden können, um zu identifizieren, wonach Sie suchen.


3

Es gibt eine wirklich gute Bibliothek für die Verarbeitung von Text in natürlicher Sprache in Python namens nltk. Sie sollten es sich ansehen.

Eine Strategie, die Sie versuchen könnten, besteht darin, n-Gramm (Wortgruppen) mit dem Wort "Apfel" zu betrachten. Einige Wörter werden eher neben "Apfel" verwendet, wenn über die Frucht gesprochen wird, andere, wenn über das Unternehmen gesprochen wird, und Sie können diese verwenden, um Tweets zu klassifizieren.


1
Danke Manetheran. Ich bin nicht das Originalplakat, aber ich interessiere mich auch für die Antwort. Für das Kopfgeld suche ich nach Code (der sogar verwendet wird nltk), der mir helfen kann, mit einer maschinellen Lernaufgabe "Hallo Welt" in die richtige Richtung zu starten. Der Apfel (inc) gegen Apfel (Obst) scheint eine perfekte Aufgabe zu sein.
Ryan

3

Verwenden Sie LibShortText . Dieses Python- Dienstprogramm wurde bereits für kurze Textkategorisierungsaufgaben optimiert und funktioniert gut. Das Maximum, das Sie tun müssen, ist, eine Schleife zu schreiben, um die beste Kombination von Flags auszuwählen. Ich habe es verwendet, um eine überwachte Klassifizierung von Sprechhandlungen in E-Mails durchzuführen, und die Ergebnisse waren bis zu 95-97% genau (während der 5-fachen Kreuzvalidierung!).

Und es kommt von den Herstellern von LIBSVM und LIBLINEAR, deren Implementierung von Support Vector Machine (SVM) in sklearn und cran verwendet wird, sodass Sie ziemlich sicher sein können, dass ihre Implementierung nicht fehlerhaft ist.


2

Erstellen Sie einen AI-Filter, um Apple Inc (das Unternehmen) von Apple (der Frucht) zu unterscheiden. Da es sich um Tweets handelt, definieren Sie Ihren Trainingssatz mit einem Vektor von 140 Feldern, wobei jedes Feld das Zeichen ist, das in den Tweet an Position X (0 bis 139) geschrieben wurde. Wenn der Tweet kürzer ist, geben Sie einfach einen Wert für leer an.

Bauen Sie dann ein Trainingsset, das groß genug ist, um eine gute Genauigkeit zu erzielen (subjektiv nach Ihrem Geschmack). Weisen Sie jedem Tweet einen Ergebniswert zu, ein Apple Inc- Tweet erhält 1 (wahr) und ein Apple-Tweet (Obst) erhält 0. Dies wäre ein Fall von überwachtem Lernen in einer logistischen Regression .

Das ist maschinelles Lernen, ist im Allgemeinen einfacher zu codieren und bietet eine bessere Leistung. Es muss aus dem Set lernen, das Sie ihm geben, und es ist nicht fest codiert.

Ich kenne Python nicht , daher kann ich den Code dafür nicht schreiben, aber wenn Sie sich mehr Zeit für die Logik und Theorie des maschinellen Lernens nehmen, möchten Sie vielleicht die Klasse betrachten, der ich folge.

Probieren Sie den Coursera- Kurs Maschinelles Lernen von Andrew Ng . Sie werden maschinelles Lernen auf MATLAB oder Octave lernen , aber sobald Sie die Grundlagen erreicht haben, können Sie maschinelles Lernen in jeder Sprache schreiben, wenn Sie die einfache Mathematik verstehen (einfach in logistischer Regression).

Das heißt, wenn Sie den Code von jemandem erhalten, können Sie nicht verstehen, was im Code für maschinelles Lernen vor sich geht. Vielleicht möchten Sie ein paar Stunden in das Thema investieren, um zu sehen, was wirklich los ist.


Danke Fawar. Ich hatte auf Code für diese "Hallo Welt" gehofft, um genau zu diesem Zweck zu erfahren - wie ML funktioniert. Ich werde die Klasse aber nachschlagen. Sieht gut aus.
Ryan

0

Ich würde empfehlen, Antworten zu vermeiden, die auf eine Entitätserkennung hindeuten. Da es sich bei dieser Aufgabe zunächst um eine Textklassifizierung und dann um eine Entitätserkennung handelt (Sie können dies überhaupt ohne Entitätserkennung tun).

Ich denke , dass der schnellste Weg zu den Ergebnissen wird spacigen + sein Wunder . Spacy hat ein gut durchdachtes Modell für die englische Sprache, sodass Sie kein eigenes Modell erstellen müssen. Während Prodigy es ermöglicht, schnell Trainingsdatensätze zu erstellen und das Spacy-Modell an Ihre Bedürfnisse anzupassen.

Wenn Sie genug Proben haben, können Sie in 1 Tag ein anständiges Modell haben.


Zur gleichen Zeit, spaCyhat nerPipeline-Komponente, wäre es nicht vorteilhaft für diese Klassifizierung? Ich gehe davon aus, dass ihr Modell Apple(da es eines der größten und bekanntesten Unternehmen der Welt ist) viel besser erkennen kann als ein Modell, das Sie an einem Tag entwickeln können.
Szymon Maszke

@ Enzymon: NER kann helfen oder nicht. Soweit ich weiß, möchten Sie benannte Entitäten (die Tatsache, dass sie im Text vorhanden sind) als Feature für die Hauptklassifizierungsaufgabe verwenden. Anscheinend wird NER keine 100% ige Genauigkeit aufweisen, da ein hohes Maß an Mehrdeutigkeit besteht. Das Hauptklassifizierungsmodell entscheidet also, unter welchen Umständen es dieser Funktion vertraut. Es kann sich herausstellen (ich denke, es ist sehr wahrscheinlich), dass ein grundlegendes Klassifizierungsmodell den Ergebnissen des NER-Modells ein sehr geringes Gewicht verleiht. Und das bedeutet, dass Sie Zeit mit NER verbringen, das (fast) nicht verwendet wird.
Dim

Nicht was ich meinte. Erstellen Sie einfach spacy.Docaus jedem Text, durchlaufen Sie die NERs mit doc.entsund überprüfen Sie, ob ein NER ein .textAttribut hat , das gleich ist Apple. Lustige Tatsache, ihr erstes Beispiel besteht aus Apple.
Szymon Maszke

Und wenn jemand ein Modell erstellen wollte, würde es höchstwahrscheinlich RNNs / CNNs und dergleichen beinhalten, sie entsprechend abstimmen, Architektur, Zelltypen usw. finden. Ich denke nicht, dass einfachere Modelle Disambiguierung und Kontext gut handhaben würden. Warum sollten Sie Ihr Leben leichter machen (es sei denn, Sie möchten unterwegs etwas lernen), wenn es bereits jemand für Sie getan hat?
Szymon Maszke

@SzymonMaszke Ihr Modell ist komplizierter und schwieriger zu trainieren. Damit Ihr Modell für den genannten Zweck funktioniert, müssen Sie nicht nur einen NE finden, sondern ihn auch an der richtigen Stelle finden (Token). Mit dem Kategorisierungsmodell, das Sie vorschlagen, optimieren Sie das Modell für Ihr Kernziel - identifizieren Sie es als Apple-Unternehmen oder Apple-Frucht. Das ist einfacher zu trainieren und daher höchstwahrscheinlich genauer.
Dim
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.