Jak zbudować model, aby odróżnić tweety o Apple (Inc.) od tweetów o jabłkach (owocach)?

85

Zobacz poniżej 50 tweetów na temat „Apple”. Odręcznie oznaczyłem pozytywne dopasowania dotyczące Apple Inc. Są one poniżej oznaczone jako 1.

Oto kilka linijek:

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

Oto całkowity zestaw danych: http://pastebin.com/eJuEb4eB

Muszę zbudować model klasyfikujący „Apple” (Inc). od reszty.

Nie szukam ogólnego przeglądu uczenia maszynowego, raczej szukam rzeczywistego modelu w kodzie ( preferowany Python ).

SAL
źródło
18
Zasadniczo chcesz tego: en.wikipedia.org/wiki/Bayesian_spam_filtering
eddi
1
Możesz ręcznie oznaczać swoje dane, ale chcesz, aby biblioteki były skalowane. Czy jest to nadzorowane czy nienadzorowane?
dan
1
Eddi, dzięki za komentarz. Zobaczcie, że e-maile z filtrowaniem poczty naprawdę pomogły w moim mózgu. Mogłem zobaczyć prawdziwy przykład tego, co próbowałem zrobić, po prostu zastosowałem go w inny sposób.
SAL
1
Fascynujące @NeilMcGuigan. Wkleiłem część tekstu z ich demo ( nlp.stanford.edu:8080/ner/process ) i byłem pod wrażeniem tego, jak różne modele klasyfikują słowa.
Ryan

Odpowiedzi:

39

Zrobiłbym to w następujący sposób:

  1. Podziel zdanie na słowa, znormalizuj je, zbuduj słownik
  2. Z każdym słowem zapisz ile razy pojawiły się one w tweetach o firmie, a ile razy pojawiły się w tweetach o owocach - te tweety muszą być potwierdzone przez człowieka
  3. Kiedy pojawia się nowy tweet, znajdź każde słowo w tweecie w słowniku, oblicz wynik ważony - słowa, które są często używane w odniesieniu do firmy, uzyskałyby wysoki wynik firmy i odwrotnie; słowa używane rzadko lub używane zarówno w towarzystwie, jak iw owocach, nie miałyby dużej punktacji.
AMADANON Inc.
źródło
2
Dziękuję za odpowiedź w tej sprawie. Twoja odpowiedź w połączeniu z komentarzem powyżej naprawdę pomogła mi znaleźć rozwiązanie. Czy możesz mi pomóc udoskonalić to rozwiązanie?
SAL
10
To jest nieformalny opis klasyfikacji bayesowskiej.
sanityinc
1
Wolę „implementację pseudokodu klasyfikacji bayesowskiej” :)
AMADANON Inc.
73

To, czego szukasz, nazywa się Rozpoznawanie nazwanych jednostek . Jest to technika statystyczna, która (najczęściej) wykorzystuje warunkowe pola losowe do znajdowania nazwanych jednostek na podstawie przeszkolenia w zakresie uczenia się o nazwanych jednostkach.

Zasadniczo analizuje zawartość i kontekst słowa (patrząc wstecz i do przodu kilka słów), aby oszacować prawdopodobieństwo, że słowo jest nazwaną jednostką.

Dobre oprogramowanie może analizować inne cechy słów, takie jak długość lub kształt (np. „Vcv”, jeśli zaczyna się od „samogłoska-spółgłoska-samogłoska”)

Bardzo dobrą biblioteką (GPL) jest NER Stanforda

Oto demo: http://nlp.stanford.edu:8080/ner/

Przykładowy tekst do wypróbowania:

Jadłem jabłko w siedzibie Apple i pomyślałem o Apple Martin, córce faceta z Coldplay

(klasyfikatory 3class i 4class dobrze to rozumieją)

Neil McGuigan
źródło
5
To było naprawdę interesujące. Czy można wyświetlić kod english.conll.4class.distsim.crf.ser.gz? Chciałbym zobaczyć, jak buduje się coś takiego.
Ryan,
Kod dla NER jest open source, ale dane, których użyli na konferencjach CONLL nie są. Jednak Reuters Corpus można znaleźć w Internecie pod adresem NIST.
Neil McGuigan,
31

Mam częściowo działający system, który rozwiązuje ten problem, oparty na otwartym kodzie źródłowym za pomocą scikit-learn, z serią postów na blogu opisujących to, co robię. Problem, z którym się zmagam, to ujednoznacznienie w sensie słów (wybranie jednej z wielu opcji sensu słów ), co nie jest tym samym, co Rozpoznawanie nazwanych jednostek. Moje podstawowe podejście jest nieco konkurencyjne w stosunku do istniejących rozwiązań i (co najważniejsze) można je dostosowywać.

Istnieje kilka istniejących komercyjnych narzędzi NER (OpenCalais, DBPedia Spotlight i AlchemyAPI), które mogą dać wystarczająco dobry wynik komercyjny - wypróbuj je najpierw!

Część z nich wykorzystałem do projektu klienta (konsultuję się przy użyciu NLP / ML w Londynie), ale nie byłem zadowolony z ich wycofania ( precyzja i przywołanie ). Zasadniczo mogą być precyzyjne (kiedy mówią „To jest Apple Inc”, zazwyczaj są poprawne), ale z niską pamięcią (rzadko mówią „To jest Apple Inc”, chociaż dla człowieka tweet dotyczy oczywiście Apple Inc). Pomyślałem, że zbudowanie wersji open source dostosowanej do tweetów byłoby interesującym intelektualnie ćwiczeniem. Oto aktualny kod: https://github.com/ianozsvald/social_media_brand_disambiguator

Zauważę - nie próbuję rozwiązywać uogólnionego problemu ujednoznaczniania sensu słów za pomocą tego podejścia, tylko ujednoznacznienie marki (firmy, ludzie itp.), Kiedy już masz ich nazwę. Dlatego uważam, że to proste podejście zadziała.

Zacząłem to sześć tygodni temu i jest napisane w Pythonie 2.7 przy użyciu scikit-learn. Wykorzystuje bardzo podstawowe podejście. Wektoryzuję za pomocą binarnego wektoryzatora liczenia (liczę tylko, czy pojawi się słowo, a nie ile razy) z 1-3  n-gramami . Nie skaluję z TF-IDF (TF-IDF jest dobry, gdy masz zmienną długość dokumentu; dla mnie tweety to tylko jedno lub dwa zdania, a moje wyniki testów nie wykazały poprawy z TF-IDF).

Używam podstawowego tokenizera, który jest bardzo prosty, ale zaskakująco przydatny. Ignoruje @ # (więc tracisz kontekst) i oczywiście nie rozwija adresu URL. Następnie trenuję przy użyciu regresji logistycznej i wydaje się, że ten problem jest nieco liniowy (wiele terminów dla jednej klasy nie istnieje dla drugiej). Obecnie unikam wszelkiego wyprowadzania / czyszczenia (próbuję najprostszej możliwej rzeczy, która może zadziałać).

Kod ma pełne README i powinieneś być w stanie stosunkowo łatwo przyswoić swoje tweety, a następnie postępować zgodnie z moimi sugestiami dotyczącymi testowania.

Działa to w przypadku Apple, ponieważ ludzie nie jedzą ani nie piją komputerów Apple, ani nie piszemy ani nie bawimy się owocami, więc słowa można łatwo podzielić na jedną lub drugą kategorię. Ten warunek może nie obowiązywać, gdy rozważa się coś w rodzaju #definance dla programu telewizyjnego (gdzie ludzie używają również #definance w odniesieniu do Arabskiej Wiosny, meczów krykieta, powtórzenia egzaminów i zespołu muzycznego). W tym przypadku może być wymagane podejście Cleverer.

Mam serię postów na blogu opisujących ten projekt, w tym godzinną prezentację, którą wygłosiłem na grupie użytkowników BrightonPython (która zamieniła się w krótszą prezentację dla 140 osób w DataScienceLondon).

Jeśli używasz czegoś takiego jak Regresja Logistyczna (gdzie uzyskujesz prawdopodobieństwo dla każdej klasyfikacji), możesz wybrać tylko pewne klasyfikacje iw ten sposób możesz wymusić wysoką precyzję, handlując przeciwko wycofaniu (dzięki czemu uzyskasz prawidłowe wyniki, ale ich mniej). Będziesz musiał dostroić to do swojego systemu.

Oto możliwe podejście algorytmiczne wykorzystujące scikit-learn:

  • Użyj Binary CountVectorizer (nie sądzę, aby liczba terminów w krótkich wiadomościach dodawała dużo informacji, ponieważ większość słów występuje tylko raz)
  • Zacznij od klasyfikatora drzewa decyzyjnego. Będzie miał możliwą do wyjaśnienia wydajność (zobacz przykład nadmiernego dopasowania za pomocą drzewa decyzyjnego ).
  • Przejdź do regresji logistycznej
  • Zbadaj błędy generowane przez klasyfikatory (przeczytaj wyeksportowane dane wyjściowe DecisionTree lub spójrz na współczynniki w LogisticRegression, przeprowadź błędnie sklasyfikowane tweety z powrotem przez Vectorizer, aby zobaczyć, jak wygląda podstawowa reprezentacja Bag of Words - będzie tam mniej tokenów niż zacząłeś w surowym tweecie - czy wystarczy na klasyfikację?)
  • Spójrz na mój przykładowy kod w https://github.com/ianozsvald/social_media_brand_disambiguator/blob/master/learn1.py, aby uzyskać działającą wersję tego podejścia

Rzeczy do rozważenia:

  • Potrzebujesz większego zbioru danych. Używam 2000 oznaczonych tweetów (zajęło mi to pięć godzin) i jako minimum chcesz zbalansowanego zestawu z> 100 na klasę (patrz uwaga o przeuczeniu poniżej)
  • Ulepsz tokeniser (bardzo łatwy dzięki scikit-learn), aby zachować # @ w tokenach i być może dodaj detektor marki z wielką literą (jako notatki user @ user2425429)
  • Rozważ nieliniowy klasyfikator (jak sugestia @ oiez powyżej), gdy sprawy stają się trudniejsze. Osobiście uważam, że LinearSVC radzi sobie gorzej niż regresja logistyczna (ale może to wynikać z wielowymiarowej przestrzeni funkcji, której jeszcze nie zmniejszyłem).
  • Specyficzna dla tweeta część taggera mowy (moim skromnym zdaniem nie Standforda, jak sugeruje @Neil - z mojego doświadczenia wynika, że ​​słabo działa na słabej gramatyce na Twitterze)
  • Gdy będziesz mieć dużo tokenów, prawdopodobnie zechcesz zmniejszyć wymiarowość (jeszcze tego nie próbowałem - zobacz mój wpis na blogu na temat kary LogisticRegression l1 l2)

Re. przeładowanie. W moim zbiorze danych zawierającym 2000 pozycji mam 10-minutową migawkę z Twittera tweetów „Apple”. Około 2/3 tweetów jest dla Apple Inc, 1/3 dla innych zastosowań Apple. Wyciągam zrównoważony podzbiór (myślę, że około 584 wierszy) z każdej klasy i przeprowadzam pięciokrotną weryfikację krzyżową na potrzeby treningu.

Ponieważ mam tylko 10-minutowe okno czasowe, mam wiele tweetów na ten sam temat i prawdopodobnie dlatego mój klasyfikator radzi sobie tak dobrze w porównaniu z istniejącymi narzędziami - będzie zbyt dobrze dopasowany do funkcji szkoleniowych bez dobrego uogólniania (podczas gdy istniejący komercyjny narzędzia działają gorzej w tym sklepie snapshop, ale bardziej niezawodnie w szerszym zestawie danych). Rozszerzę moje okno czasowe, aby przetestować to jako kolejną część pracy.

Ian Ozsvald
źródło
Nie miałem przyjemności przeglądać twojego kodu i próbować kopiować / naśladować / edukować, ale jestem ci winien przeprosiny za nie przyznanie pełnych 50 punktów nagrody. Byłem z dala od SO przez weekend i nie dotrzymałem terminu na przyznanie nagrody. Na szczęście społeczność SO wkroczyła i uznała za stosowne przyznać Ci 25 punktów.
Ryan,
1
Żaden problem :-) Kod, README i wpisy na blogu powinny dać ci wyobrażenie o moim podejściu. Jest to celowo proste, ale wydaje się działać poprawnie.
Ian Ozsvald
12

Możesz wykonać następujące czynności:

  1. Stwórz dyktando słów zawierających liczbę ich występowania w tweetach owocowych i firmowych. Można to osiągnąć, podając mu kilka przykładowych tweetów, których skłonności znamy.

  2. Korzystając z wystarczającej ilości wcześniejszych danych, możemy ustalić prawdopodobieństwo wystąpienia słowa w tweecie o Apple Inc.

  3. Pomnóż indywidualne prawdopodobieństwa słów, aby otrzymać prawdopodobieństwo całego tweeta.

Uproszczony przykład:

p_f = Prawdopodobieństwo tweetów owocowych.

p_w_f = Prawdopodobieństwo wystąpienia słowa w tweecie owocowym.

p_t_f = Połączone prawdopodobieństwo, że wszystkie słowa w tweecie wystąpią w tweecie owocowym = p_w1_f * p_w2_f * ...

p_f_t = Prawdopodobieństwo otrzymania owocu w danym tweecie .

p_c, p_w_c, p_t_c, p_c_t to odpowiednie wartości dla firmy.

Dodawany jest laplaciański wygładzacz o wartości 1, aby wyeliminować problem zerowej częstotliwości nowych słów, których nie ma w naszej bazie danych.

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
źródło
9

Jeśli nie masz problemu z używaniem zewnętrznej biblioteki, polecam scikit-learn, ponieważ prawdopodobnie może to zrobić lepiej i szybciej niż cokolwiek, co możesz sam kodować. Po prostu zrobiłbym coś takiego:

Zbuduj swój korpus. Zrobiłem listę składaną dla przejrzystości, ale w zależności od sposobu przechowywania danych może być konieczne wykonanie różnych czynności:

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)

Ważne jest to, że otrzymasz dwie listy, które wyglądają następująco:

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

[1, 1, 0, 0] reprezentują etykiety dodatnie i ujemne.

Następnie tworzysz Pipeline! Pipeline to klasa typu scikit-learning, która ułatwia łączenie etapów przetwarzania tekstu w łańcuchy, dzięki czemu podczas treningu / przewidywania wystarczy wywołać tylko jeden obiekt:

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

Wewnątrz potoku znajdują się trzy etapy przetwarzania. CountVectorizer tokenizuje słowa, dzieli je, zlicza i przekształca dane w rzadką macierz. TfidfTransformer jest opcjonalny i możesz chcieć go usunąć w zależności od oceny dokładności (przeprowadzanie testów walidacji krzyżowej i wyszukiwanie najlepszych parametrów w siatce jest trochę zaangażowane, więc nie będę się tutaj wdawać). LinearSVC to standardowy algorytm klasyfikacji tekstu.

Na koniec przewidujesz kategorię tweetów:

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

Znowu tweet musi znajdować się na liście, więc założyłem, że wpisuje funkcję jako ciąg.

Umieść je na zajęciach lub cokolwiek innego i gotowe. Przynajmniej w tym bardzo podstawowym przykładzie.

Nie testowałem tego kodu, więc może nie zadziałać, jeśli po prostu skopiujesz i wkleisz, ale jeśli chcesz użyć scikit-learn, powinno dać ci pomysł, od czego zacząć.

EDYCJA: próbowałem bardziej szczegółowo wyjaśnić kroki.

oiez
źródło
6

Wydaje się, że użycie drzewa decyzyjnego działa całkiem dobrze w przypadku tego problemu. Przynajmniej zapewnia wyższą dokładność niż naiwny klasyfikator Bayesa z wybranymi przeze mnie funkcjami.

Jeśli chcesz pobawić się niektórymi możliwościami, możesz użyć następującego kodu, który wymaga zainstalowania nltk. Książka nltk jest również dostępna bezpłatnie online, więc możesz przeczytać trochę o tym, jak to wszystko faktycznie działa: 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
źródło
1
jak to działa? Nie widzę w Twoim kodzie „wybranych funkcji”. Czy automatycznie wybiera funkcje na podstawie zestawu treningowego? Czy jest przechowywany w dict()innym miejscu? Myślę, że jeśli zestaw treningowy jest wystarczająco duży, czy komputer nie powinien być w stanie samodzielnie określić jego funkcji? (bez nadzoru?)
Ryan
2
Funkcje są wyodrębniane za pomocą funkcji tweet_features. Zasadniczo usuwa adresy URL z tweetów, a następnie tworzy dyktando funkcji, którego wpisy brzmią mniej więcej tak: „hasBigram (foo, bar)” = True.
Paul Dubs
1
Więc 'hasBigram(foo,bar)' = Truegdzie zawiera ciąg tweeta foo bar? Więc buduje bigramy i trygramy dla każdego tweeta i zaznacza go jako pozytywną cechę dict()? Dlatego biorąc pod uwagę tweet, "alpha beta gamma delta"utworzy dict () bigramy dla alpha,beta; beta,gamma; and gamma,delta;i trygramy dla alpha,beta,gammai beta,gamma,delta? A z podanych dodatnich i ujemnych bi i tri gramów, klasyfikatory w postaci drzewa decyzyjnego lub bayes mogą zrobić swoją magię?
Ryan,
2
Dokładnie. Używając klasyfikatora Bayesa, możesz również uzyskać najbardziej przydatne funkcje, wywołując na nim „show_most_informative_features ()”.
Paul Dubs,
Paul, stworzyłem prostą wersję php tego i masz całkowitą rację. Jest to bardzo skuteczny sposób tworzenia słownika ważonego. Myślę, że można to łatwo skalować bez konieczności ręcznego tworzenia wszystkich słów kluczowych. Nie mogę się doczekać, aby dowiedzieć się więcej o tym, jak to zrobić w standardowych bibliotekach uczenia maszynowego.
Ryan
5

Dziękuję za dotychczasowe komentarze. Oto działające rozwiązanie, które przygotowałem w PHP. Nadal chciałbym usłyszeć od innych bardziej algorytmiczne podejście do tego samego rozwiązania.

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

Powyższe wyniki:

           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
źródło
4

We wszystkich podanych przez Ciebie przykładach Apple (inc) było określane jako A pple lub apple inc , więc możliwym sposobem może być wyszukanie:

  • duże „A” w Apple

  • „inc” po jabłku

  • słowa / wyrażenia, takie jak „OS”, „system operacyjny”, „Mac”, „iPhone”, ...

  • lub ich połączenie

user2425429
źródło
1
W funkcji zrobiłem strtolower, aby odfiltrować wielkie litery. Trochę prymitywne, ale zadziałało.
SAL
@SAL Nie spodziewałem się, że będzie to bardzo przydatne, ale jeśli masz limit czasu, to ...
user2425429
4

Aby nieco uprościć odpowiedzi oparte na warunkowych polach losowych ... kontekst jest tutaj ogromny. Będziesz chciał wybrać w tych tweetach, które wyraźnie pokazują Apple, firmę kontra jabłko owoc. Pozwólcie, że przedstawię tutaj listę funkcji, które mogą być przydatne na początku. Aby uzyskać więcej informacji, poszukaj fragmentów wyrażeń rzeczownikowych i czegoś, co nazywa się etykietami BIO. Zobacz ( http://www.cis.upenn.edu/~pereira/papers/crf.pdf )

Otaczające słowa: stwórz wektor cech dla poprzedniego i następnego słowa lub, jeśli chcesz mieć więcej funkcji, na przykład dla poprzednich 2 i następnych 2 słów. Nie chcesz zbyt wielu słów w modelu lub nie będzie on dobrze pasował do danych. W przetwarzaniu języka naturalnego będziesz chciał, aby to było jak najbardziej ogólne.

Inne funkcje, które można uzyskać z otaczających słów, obejmują:

Czy pierwsza postać jest stolicą

Czy ostatni znak w słowie jest kropką

Część mowy słowa (Wyszukaj część oznaczania mowy)

Sam tekst słowa

Nie radzę tego, ale podaję więcej przykładów funkcji specjalnie dla Apple:

WordIs (Apple)

NextWordIs (Inc.)

Dostajesz punkt. Pomyśl o rozpoznawaniu nazwanych jednostek jako opisie sekwencji, a następnie używając matematyki, aby powiedzieć komputerowi, jak to obliczyć.

Należy pamiętać, że przetwarzanie języka naturalnego jest systemem opartym na potokach. Zazwyczaj dzielisz rzeczy na zdania, przechodzisz do tokenizacji, a następnie wykonujesz część tagowania mowy, a nawet parsowania zależności.

To wszystko po to, aby uzyskać listę funkcji, których możesz użyć w swoim modelu, aby zidentyfikować to, czego szukasz.

Adam Gibson
źródło
3

W Pythonie jest naprawdę dobra biblioteka do przetwarzania tekstu w języku naturalnym o nazwie nltk. Powinieneś się temu przyjrzeć.

Jedną ze strategii, którą możesz wypróbować, jest przyjrzenie się n-gramom (grupom słów) ze słowem „jabłko”. Niektórych słów częściej używa się obok słowa „jabłko”, gdy mówi się o owocach, innych, gdy mówi się o firmie, i można ich użyć do sklasyfikowania tweetów.

Scott Ritchie
źródło
1
Dzięki, Manetheran. Nie jestem oryginalnym plakatem, ale interesuje mnie też odpowiedź. Za nagrodę szukam kodu (nawet używającego nltk), który pomoże mi zacząć we właściwym kierunku dzięki zadaniu uczenia maszynowego „witaj świecie”. Apple (inc) kontra jabłko (owoc) wydaje się idealnym zadaniem.
Ryan,
3

Użyj LibShortText . To narzędzie Pythona zostało już dostrojone do pracy z zadaniami kategoryzacji krótkiego tekstu i działa dobrze. Maksymalne, które musisz zrobić, to napisać pętlę, aby wybrać najlepszą kombinację flag. Użyłem go do nadzorowanej klasyfikacji aktów mowy w e-mailach, a wyniki były dokładne do 95-97% (podczas 5-krotnej weryfikacji krzyżowej!).

I pochodzi od twórców LIBSVM i LIBLINEAR, których implementacja maszyny wektorów nośnych (SVM) jest używana w sklearn i cran, więc możesz mieć uzasadnioną pewność, że ich implementacja nie zawiera błędów.

Pushpendre
źródło
2

Utwórz filtr AI, aby odróżnić Apple Inc (firmę) od Apple (owoc). Ponieważ są to tweety, zdefiniuj zestaw treningowy za pomocą wektora 140 pól, z których każde jest znakiem wpisanym w tweecie na pozycji X (od 0 do 139). Jeśli tweet jest krótszy, podaj po prostu wartość pustą.

Następnie zbuduj zestaw treningowy wystarczająco duży, aby uzyskać dobrą dokładność (subiektywną do gustu). Przypisz wartość wyniku do każdego tweeta, tweet Apple Inc otrzyma 1 (prawda), a tweet jabłka (owoc) otrzyma 0. Byłby to przypadek nadzorowanego uczenia się w regresji logistycznej .

To jest uczenie maszynowe, które jest ogólnie łatwiejsze do kodowania i działa lepiej. Musi się uczyć z zestawu, który mu dajesz, i nie jest zakodowany na stałe.

Nie znam Pythona , więc nie mogę napisać do niego kodu, ale gdybyś poświęcił więcej czasu na logikę i teorię uczenia maszynowego, możesz spojrzeć na klasę, którą śledzę.

Wypróbuj kurs Coursera Machine Learning autorstwa Andrew Ng . Nauczysz się uczenia maszynowego na MATLAB-ie lub Octave , ale kiedy już opanujesz podstawy, będziesz w stanie pisać uczenie maszynowe w dowolnym języku, jeśli rozumiesz prostą matematykę (prostą w regresji logistycznej).

Oznacza to, że pobranie kodu od kogoś nie sprawi, że będziesz w stanie zrozumieć, co dzieje się w kodzie uczenia maszynowego. Możesz poświęcić kilka godzin na ten temat, aby zobaczyć, co się naprawdę dzieje.

Fawar
źródło
Dzięki Fawar. Miałem nadzieję, że na tym „witaj świecie” znajdę jakiś kod do tego właśnie celu - aby dowiedzieć się, jak działa ML. Jednak sprawdzę klasę. Wygląda dobrze.
Ryan,
0

Zalecałbym unikanie odpowiedzi sugerujących uznanie jednostek. Ponieważ to zadanie to najpierw klasyfikacja tekstu, a dopiero potem rozpoznawanie jednostek (możesz to zrobić w ogóle bez rozpoznawania jednostek).

Myślę, że najszybszą drogą do wyników będzie spacy + cudowne dziecko . Spacy ma dobrze przemyślany model języka angielskiego, więc nie musisz tworzyć własnego. Prodigy pozwala szybko tworzyć zestawy danych treningowych i dostosowywać model spacy do swoich potrzeb.

Jeśli masz wystarczająco dużo próbek, możesz mieć przyzwoity model w 1 dzień.

Ciemny
źródło
Jednocześnie, spaCyczy nerskładnik rurociągu nie byłby korzystny dla tej klasyfikacji? Zakładam, że ich model można rozpoznać Apple(bo to jedna z największych i najbardziej znanych firm na świecie) znacznie lepiej niż model, który można wymyślić w jeden dzień.
Szymon Maszke
@Szymon: NER może pomóc lub nie. Jak rozumiem, chcesz użyć nazwanych jednostek (fakt, że są one obecne w tekście) jako funkcji głównego zadania klasyfikacji. Najwyraźniej NER nie będzie miał 100% dokładności, ponieważ istnieje wysoki poziom niejednoznaczności. Zatem główny model klasyfikacji zadecyduje, w jakich okolicznościach będzie ufał tej funkcji. Może się okazać (myślę, że jest to bardzo prawdopodobne), że podstawowy model klasyfikacji nada bardzo małą wagę wynikom modelu NER. A to oznacza, że ​​spędzisz czas na NER, który jest (prawie) nie używany.
Dim
Nie to miałem na myśli. Po prostu utwórz spacy.Docz każdego tekstu, iteruj po ich NER-ach za pomocą doc.entsi sprawdź, czy którykolwiek NER ma .textatrybut równy Apple. Zabawne, że ich pierwszy przykład to Apple.
Szymon Maszke
A gdyby ktoś chciał stworzyć model, najprawdopodobniej obejmowałby on RNN / CNN i tym podobne, odpowiednio je dostroił, znalazł architekturę, typy komórek itp. Nie sądzę, aby łatwiejsze modele poradziły sobie dobrze z ujednoznacznieniem i kontekstem. Po co ułatwiać sobie życie (chyba, że ​​po drodze chcesz się czegoś nauczyć), skoro ktoś już to za Ciebie zrobił?
Szymon Maszke
@SzymonMaszke Twój model jest bardziej skomplikowany i trudniejszy do wytrenowania. Aby Twój model działał we wspomnianym celu, musisz nie tylko znaleźć NE, ale także znaleźć go w odpowiednim miejscu (żeton). Dzięki modelowi kategoryzacji, który proponuję, zoptymalizuj model pod kątem podstawowego celu - zidentyfikuj firmę Apple lub owoce Apple. To łatwiejsze do wyszkolenia i dlatego najprawdopodobniej będzie dokładniejsze.
Dim