Как я могу построить модель, чтобы отличать твиты об Apple (Inc.) от твитов о яблоке (фруктах)?

85

Ниже вы найдете 50 твитов о «яблоке». Я вручную пометил положительные совпадения об Apple Inc. Они отмечены цифрой 1 ниже.

Вот пара строк:

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

Вот полный набор данных: http://pastebin.com/eJuEb4eB

Мне нужно построить модель, которая классифицирует «Apple» (Inc). от остальных.

Я не ищу общий обзор машинного обучения, я ищу реальную модель в коде ( предпочтительно Python ).

SAL
источник
18
Вы в основном хотите этого: en.wikipedia.org/wiki/Bayesian_spam_filtering
eddi
1
Вы вручную маркируете свои данные, но вам нужны масштабируемые библиотеки. Это под присмотром или без присмотра?
дан
1
Эдди, спасибо, за комментарий. Видите ли, электронная почта с фильтром почты действительно помогла чему-то щелкнуть в моем мозгу. Я смог увидеть реальный пример того, что я пытался сделать, просто применил по-другому.
SAL
5
Распознавание именованных сущностей: nlp.stanford.edu/software/CRF-NER.shtml .
Нил МакГиган
1
Очаровательный @NeilMcGuigan. Я вставил часть текста в их демонстрацию ( nlp.stanford.edu:8080/ner/process ) и был впечатлен тем, как разные модели классифицируют слова.
Ryan

Ответы:

39

Я бы сделал это так:

  1. Разбить предложение на слова, нормализовать их, составить словарь
  2. С каждым словом запоминайте, сколько раз они появлялись в твитах о компании и сколько раз они появлялись в твитах о фруктах - эти твиты должны быть подтверждены человеком.
  3. Когда приходит новый твит, найдите каждое слово в твите в словаре, вычислите взвешенную оценку - слова, которые часто используются в отношении компании, получат высокий балл компании, и наоборот; слова, которые используются редко или используются как с компанией, так и с фруктами, не будут иметь большого значения.
AMADANON Inc.
источник
2
Спасибо за ответ по этому поводу. Ваш ответ в сочетании с приведенным выше комментарием действительно помог мне найти решение. Вы можете помочь мне отточить это решение?
SAL
10
Это неформальное описание байесовской классификации.
sanityinc 06
1
Я предпочитаю «псевдокодовую реализацию байесовской классификации» :)
AMADANON Inc.
73

То, что вы ищете, называется распознаванием именованных сущностей . Это статистический метод, который (наиболее часто) использует условные случайные поля для поиска именованных сущностей, основываясь на том, что они были обучены узнавать что-то об именованных сущностях.

По сути, он смотрит на содержание и контекст слова (оглядываясь назад и вперед на несколько слов), чтобы оценить вероятность того, что слово является именованным объектом.

Хорошее программное обеспечение может анализировать другие особенности слов, такие как их длина или форма (например, «Vcv», если оно начинается с «гласный-согласный-гласный»).

Очень хорошая библиотека (GPL) - это Стэнфордский NER

Вот демонстрация: http://nlp.stanford.edu:8080/ner/

Пример текста, который стоит попробовать:

Я ел яблоко в штаб-квартире Apple и думал об Эппл Мартин, дочери парня из Coldplay.

(классификаторы 3 и 4 класса правильно понимают)

Нил МакГиган
источник
5
Это было действительно интересно. Можно ли просмотреть код english.conll.4class.distsim.crf.ser.gz? Я бы хотел посмотреть, как можно построить что-то подобное.
Ryan
Код для NER имеет открытый исходный код, а данные, которые они использовали в конференциях CONLL, - нет. Однако вы можете найти Reuters Corpus в Интернете в NIST.
Нил МакГиган
31

У меня есть частично работающая система, которая решает эту проблему, с открытым исходным кодом с использованием scikit-learn, с серией сообщений в блогах, описывающих то, что я делаю. Проблема, которую я пытаюсь решить, - это устранение неоднозначности смысла слова (выбор одного из нескольких вариантов смысла слова ), что отличается от распознавания именованных сущностей. Мой основной подход в некоторой степени конкурирует с существующими решениями и (что очень важно) настраивается.

Существуют некоторые существующие коммерческие инструменты NER (OpenCalais, DBPedia Spotlight и AlchemyAPI), которые могут дать вам достаточно хороший коммерческий результат - попробуйте сначала!

Я использовал некоторые из них для клиентского проекта (я консультируюсь с использованием NLP / ML в Лондоне), но меня не удовлетворил их отзыв ( точность и отзыв ). В основном они могут быть точными (когда они говорят «Это Apple Inc», они обычно правы), но с низким уровнем запоминания (они редко говорят «Это Apple Inc», хотя для человека твит явно касается Apple Inc). Я подумал, что было бы интеллектуально интересным упражнением создать версию с открытым исходным кодом, адаптированную для твитов. Вот текущий код: https://github.com/ianozsvald/social_media_brand_disambiguator

Замечу - я не пытаюсь решить общую проблему устранения неоднозначности в словах с помощью этого подхода, а просто пытаюсь устранить неоднозначность бренда (компании, люди и т.д.), когда у вас уже есть их имя. Вот почему я считаю, что такой простой подход сработает.

Я начал это шесть недель назад, и он написан на Python 2.7 с использованием scikit-learn. Он использует очень простой подход. Я векторизирую с помощью векторизатора двоичного счета (я считаю только то, появляется ли слово, а не сколько раз) с 1-3  н-граммами . Я не масштабируюсь с TF-IDF (TF-IDF хорош, когда у вас есть переменная длина документа; для меня твиты состоят только из одного или двух предложений, и мои результаты тестирования не показали улучшения с TF-IDF).

Я использую базовый токенизатор, который очень прост, но на удивление полезен. Он игнорирует @ # (поэтому вы теряете некоторый контекст) и, конечно, не расширяет URL-адрес. Затем я тренируюсь с использованием логистической регрессии , и мне кажется, что эта проблема в некоторой степени линейно разделима (много терминов для одного класса не существует для другого). В настоящее время я избегаю любых стеммингов / чисток (я пробую «Простейшую возможную вещь, которая может сработать»).

В коде есть полный README, и вы сможете относительно легко воспринимать свои твиты, а затем следовать моим предложениям для тестирования.

Это работает для Apple, поскольку люди не едят и не пьют компьютеры Apple, мы не печатаем и не играем с фруктами, поэтому слова легко разделить на ту или иную категорию. Это условие может не выполняться при рассмотрении чего-то вроде #definance для телешоу (где люди также используют #definance в отношении арабской весны, матчей по крикету, пересмотра экзаменов и музыкальной группы). Здесь вполне могут потребоваться более умные подходы.

У меня есть серия сообщений в блоге, описывающих этот проект, включая часовую презентацию, которую я провел в группе пользователей BrightonPython (которая превратилась в более короткую презентацию для 140 человек в DataScienceLondon).

Если вы используете что-то вроде LogisticRegression (где вы получаете вероятность для каждой классификации), вы можете выбрать только достоверные классификации, и таким образом вы можете добиться высокой точности, торгуя против отзыва (так что вы получите правильные результаты, но их будет меньше). Вам нужно будет настроить это на свою систему.

Вот возможный алгоритмический подход с использованием scikit-learn:

  • Используйте двоичный CountVectorizer (я не думаю, что счетчик терминов в коротких сообщениях добавляет много информации, поскольку большинство слов встречается только один раз)
  • Начните с классификатора дерева решений. У него будет объяснимая производительность (см. Пример в разделе « Переоснащение деревом решений» ).
  • Перейти к логистической регрессии
  • Исследуйте ошибки, сгенерированные классификаторами (прочтите экспортированный вывод DecisionTree или просмотрите коэффициенты в LogisticRegression, обработайте неправильно классифицированные твиты обратно через векторизатор, чтобы увидеть, как выглядит базовое представление Bag of Words - там будет меньше токенов, чем вы начали с сырого твита - достаточно ли этого для классификации?)
  • Посмотрите мой пример кода в https://github.com/ianozsvald/social_media_brand_disambiguator/blob/master/learn1.py, чтобы увидеть рабочую версию этого подхода.

Что нужно учитывать:

  • Вам нужен больший набор данных. Я использую 2000 помеченных твитов (у меня это заняло пять часов), и как минимум вам нужен сбалансированный набор с> 100 на класс (см. Примечание по переобучению ниже)
  • Улучшите токенизатор (очень просто с помощью scikit-learn), чтобы сохранить # @ в токенах, и, возможно, добавить детектор бренда с заглавной буквы (как отмечает user @ user2425429)
  • Рассмотрим нелинейный классификатор (например, предложение @ oiez выше), когда становится сложнее. Лично я обнаружил, что LinearSVC хуже, чем логистическая регрессия (но это может быть из-за многомерного пространства функций, которое мне еще предстоит уменьшить).
  • Часть речевого теггера, связанная с твитами (по моему скромному мнению, не у Стэндфорда, как предполагает @Neil - по моему опыту, он плохо работает при плохой грамматике Twitter)
  • Как только у вас будет много токенов, вы, вероятно, захотите немного уменьшить размерность (я еще не пробовал этого - см. Мое сообщение в блоге о наказании LogisticRegression l1 l2)

Re. переоснащение. В моем наборе данных с 2000 элементами у меня есть 10-минутный снимок «яблочных» твитов из Twitter. Около 2/3 твитов адресовано Apple Inc, 1/3 - другим пользователям Apple. Я выбираю сбалансированное подмножество (я думаю, около 584 строк) каждого класса и делаю пятикратную перекрестную проверку для обучения.

Поскольку у меня есть только 10-минутное временное окно, у меня много твитов на ту же тему, и, вероятно, именно поэтому мой классификатор работает так хорошо по сравнению с существующими инструментами - он будет переоснащен функциями обучения без хороших обобщений (тогда как существующий коммерческий инструменты работают хуже в этом снапшопе, но более надежно для более широкого набора данных). Я буду расширять свое временное окно, чтобы проверить это в качестве последующей работы.

Ян Озсвальд
источник
Я не имел удовольствия просматривать ваш код и пытаться скопировать / подражать / обучать, но я должен извиниться за то, что не присуждал полные 50 баллов награды. Я был далеко от SO на выходных и пропустил крайний срок, чтобы наградить его. К счастью, сообщество SO вмешалось и сочло возможным наградить вас 25 баллами.
Райан
1
Нет проблем :-) Код, README и сообщения в блогах должны дать вам представление о моем подходе. Это намеренно просто, но, похоже, работает нормально.
Ian Ozsvald 08
12

Вы можете сделать следующее:

  1. Составьте диктовку слов, указав их количество в твитах о фруктах и ​​компаниях. Этого можно добиться, скармлив ему несколько примеров твитов, наклон которых нам известен.

  2. Используя достаточное количество предыдущих данных, мы можем выяснить вероятность появления слова в твите о apple inc.

  3. Умножьте отдельные вероятности слов, чтобы получить вероятность всего твита.

Упрощенный пример:

p_f = Вероятность фруктовых твитов.

p_w_f = Вероятность появления слова в фруктовом твите.

p_t_f = Суммарная вероятность того, что все слова в твите представляют собой фруктовый твит = p_w1_f * p_w2_f * ...

p_f_t = Вероятность получения фруктов при конкретном твите.

p_c, p_w_c, p_t_c, p_c_t - соответствующие значения для компании.

Добавлен лапласианский сглаживатель со значением 1, чтобы устранить проблему нулевой частоты появления новых слов, которых нет в нашей базе данных.

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

Если у вас нет проблем с использованием сторонней библиотеки, я бы порекомендовал scikit-learn, поскольку он, вероятно, может сделать это лучше и быстрее, чем все, что вы могли бы кодировать самостоятельно. Я бы сделал что-то вроде этого:

Создайте свой корпус. Я составил список для ясности, но в зависимости от того, как хранятся ваши данные, вам могут потребоваться разные вещи:

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)

Важно то, что в итоге вы получите два списка, которые выглядят следующим образом:

([['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] представляют собой положительные и отрицательные метки.

Затем вы создаете конвейер! Pipeline - это класс scikit-learn, который упрощает объединение этапов обработки текста в цепочку, поэтому вам нужно вызывать только один объект при обучении / прогнозировании:

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

Внутри конвейера есть три этапа обработки. CountVectorizer токенизирует слова, разбивает их, считает и преобразует данные в разреженную матрицу. TfidfTransformer не является обязательным, и вы можете удалить его в зависимости от рейтинга точности (выполнение тестов перекрестной проверки и поиск по сетке лучших параметров требует некоторого внимания, поэтому я не буду здесь вдаваться в подробности). LinearSVC - это стандартный алгоритм классификации текста.

Наконец, вы прогнозируете категорию твитов:

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

Опять же, твит должен быть в списке, поэтому я предположил, что он вводит функцию как строку.

Поместите все это в класс или что-то еще, и все готово. По крайней мере, на этом очень простом примере.

Я не тестировал этот код, поэтому он может не работать, если вы просто скопируете и вставите, но если вы хотите использовать scikit-learn, он должен дать вам представление о том, с чего начать.

РЕДАКТИРОВАТЬ: попытался более подробно объяснить шаги.

Oiez
источник
6

Использование дерева решений, кажется, вполне подходит для решения этой проблемы. По крайней мере, он обеспечивает более высокую точность, чем наивный байесовский классификатор с выбранными мной функциями.

Если вы хотите поэкспериментировать с некоторыми возможностями, вы можете использовать следующий код, который требует установки nltk. Книга nltk также находится в свободном доступе в Интернете, так что вы можете немного прочитать о том, как все это на самом деле работает: 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
как это работает? Я не вижу ваших «выбранных функций» в вашем коде. Он автоматически выбирает функции на основе тренировочного набора? Или он хранится dict()где-то еще? Я думаю, что если тренировочная выборка достаточно велика, не должен ли компьютер сам определять особенности? (без присмотра?)
Райан
2
Функции извлекаются с помощью функции tweet_features. Он в основном удаляет URL-адреса из твитов, а затем создает функцию dict, записи которой читают что-то вроде hasBigram (foo, bar) '= True.
Paul Dubs
1
Так 'hasBigram(foo,bar)' = Trueгде же строка твита foo bar? Значит, он строит биграммы и триграммы для каждого твита и помечает их как положительные dict()? Поэтому, учитывая твит, "alpha beta gamma delta"он будет строить биграммы dict () для alpha,beta; beta,gamma; and gamma,delta;и триграммы для alpha,beta,gammaи beta,gamma,delta? А из заданных положительных и отрицательных би и триграмм дерево решений или классификаторы Байеса могут творить чудеса?
Ryan
2
В яблочко. При использовании классификатора Байеса вы также можете получить наиболее полезные функции, вызвав на нем "show_most_informative_features ()".
Paul Dubs
Пол, я создал грубую версию на php, и вы абсолютно правы. Это суперэффективный способ построения взвешенного словаря. Я думаю, что это можно легко масштабировать, не создавая вручную все ключевые слова. Я с нетерпением жду возможности узнать больше о том, как это сделать в стандартных библиотеках машинного обучения.
Ryan
5

Спасибо за комментарии. Вот рабочее решение, которое я подготовил с помощью PHP. Мне все равно было бы интересно услышать от других о более алгоритмическом подходе к этому же решению.

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

Вышеуказанные выходы:

           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
источник
4

Во всех приведенных вами примерах Apple (inc) упоминается как A pple или apple inc , поэтому возможный способ поиска:

  • заглавная буква "А" в яблоке

  • "inc" после яблока

  • слова / фразы, такие как «ОС», «операционная система», «Mac», «iPhone», ...

  • или их комбинация

user2425429
источник
1
В функции я сделал strtolower, чтобы отфильтровать заглавные буквы. Немного грубо, но это сработало.
SAL
@SAL Я не ожидал, что это будет очень полезно, но если у вас есть ограничение по времени, тогда ...
user2425429 02
4

Чтобы немного упростить ответы на основе условных случайных полей ... контекст здесь огромен. Вы захотите выделить те твиты, которые ясно показывают, что Apple - компания, а яблоко - плод. Позвольте мне обрисовать здесь список функций, которые могут быть вам полезны для начала. Для получения дополнительной информации найдите разделение именных фраз и нечто, называемое BIO-метками. См. ( Http://www.cis.upenn.edu/~pereira/papers/crf.pdf )

Окружающие слова: создайте вектор признаков для предыдущего слова и следующего слова, или, если вам нужно больше функций, возможно, для предыдущих 2 и следующих 2 слов. Вы не хотите, чтобы в модели было слишком много слов, иначе она не будет очень хорошо соответствовать данным. В обработке естественного языка вы захотите сделать это как можно более общим.

Другие особенности, которые можно получить из окружающих слов, включают следующее:

Является ли первый символ заглавным

Является ли последний символ в слове точкой

Часть речи слова (Найдите часть пометки речи)

Сам текст слова

Я не советую этого, но приведу больше примеров функций специально для Apple:

WordIs (Apple)

NextWordIs (Inc.)

Вы уловили суть. Думайте о распознавании именованных сущностей как об описании последовательности, а затем с помощью математики, чтобы сообщить компьютеру, как это вычислить.

Имейте в виду, что обработка естественного языка - это конвейерная система. Как правило, вы разбиваете все на предложения, переходите к токенизации, а затем выполняете часть речевых тегов или даже синтаксический анализ зависимостей.

Это все, чтобы получить список функций, которые вы можете использовать в своей модели, чтобы определить, что вы ищете.

Адам Гибсон
источник
3

Там действительно хорошая библиотека для обработки текстов на естественном языке в Python под названием nltk. Вы должны взглянуть на это.

Одна из стратегий, которую вы можете попробовать, - это посмотреть на n-граммы (группы слов) со словом «яблоко» в них. Некоторые слова с большей вероятностью будут использоваться рядом с словом «яблоко» при разговоре о фруктах, другие - при разговоре о компании, и вы можете использовать их для классификации твитов.

Скотт Ричи
источник
1
Спасибо, Манетеран. Я не автор оригинального постера, но меня тоже интересует ответ. Ради щедрости я ищу код (даже использующий nltk), который поможет мне начать в правильном направлении с задачей машинного обучения "привет, мир". Сравнение яблока (inc) и яблока (фрукта) кажется идеальным выбором.
Ryan
3

Используйте LibShortText . Эта утилита Python уже настроена для работы с задачами категоризации короткого текста, и она хорошо работает. Максимум, что вам нужно сделать, это написать цикл, чтобы выбрать лучшую комбинацию флагов. Я использовал его для контролируемой классификации речевых актов в электронных письмах, и результаты были точными до 95-97% (во время пятикратной перекрестной проверки!).

И он исходит от создателей LIBSVM и LIBLINEAR, чья реализация векторной машины поддержки (SVM) используется в sklearn и cran, так что вы можете быть разумно уверены, что их реализация не содержит ошибок.

Пушпендре
источник
2

Сделайте фильтр AI, чтобы отличить Apple Inc (компания) от яблока (фрукта). Поскольку это твиты, определите свой обучающий набор с вектором из 140 полей, каждое поле - это символ, записанный в твите в позиции X (от 0 до 139). Если твит короче, просто укажите значение, чтобы он был пустым.

Затем создайте тренировочный набор, достаточно большой, чтобы получить хорошую точность (субъективно на ваш вкус). Присвойте значение результата каждому твиту, твит Apple Inc получит 1 (истина), а яблочный твит (фрукт) - 0. Это будет случай контролируемого обучения в логистической регрессии .

То есть машинное обучение, его проще кодировать и работать лучше. Он должен извлекать уроки из набора, который вы ему даете, и он не запрограммирован жестко.

Я не знаю Python , поэтому не могу написать для него код, но если вам нужно больше времени на логику и теорию машинного обучения, вы можете посмотреть класс, за которым я следую.

Попробуйте пройти курс Machine Learning на Coursera от Эндрю Нг . Вы изучите машинное обучение на MATLAB или Octave , но как только вы освоите основы, вы сможете писать машинное обучение на любом языке, если понимаете простую математику (простую в логистической регрессии).

То есть получение кода от кого-то не позволит вам понять, что происходит в коде машинного обучения. Вы можете потратить пару часов на эту тему, чтобы увидеть, что происходит на самом деле.

Фавар
источник
Спасибо, Фавар. Я надеялся найти какой-нибудь код в этом «привет, мир» именно для этой цели - чтобы узнать, как работает ML. Я поищу класс. Выглядит хорошо.
Ryan
0

Я бы рекомендовал избегать ответов, предполагающих распознавание сущностей. Потому что эта задача - во-первых, классификация текста, а во-вторых - распознавание сущностей (вы можете сделать это вообще без распознавания сущностей).

Я думаю, что самый быстрый путь к результату будет простор + вундеркинд . Spacy имеет хорошо продуманную модель для английского языка, поэтому вам не нужно создавать свою собственную. В то время как Prodigy позволяет быстро создавать наборы обучающих данных и точно настраивать пространственную модель для ваших нужд.

Если у вас будет достаточно образцов, вы сможете получить достойную модель за 1 день.

Тусклый
источник
В то же время, spaCyесть nerтрубопроводная составляющая, разве это не будет выгодно для этой классификации? Я предполагаю, что их модель может распознать Apple(поскольку это одна из самых крупных и известных компаний в мире) намного лучше, чем модель, которую вы можете придумать за один день.
Szymon Maszke
@Szymon: NER может помочь, а может и не помочь. Насколько я понимаю, вы хотите использовать именованные сущности (тот факт, что они присутствуют в тексте) в качестве функции для основной задачи классификации. Судя по всему, NER не будет иметь 100% точности из-за высокого уровня неоднозначности. Таким образом, основная модель классификации будет решать, при каких обстоятельствах она будет доверять этой функции. Может оказаться (я думаю, что это очень вероятно), что базовая модель классификации придаст очень низкий вес результатам модели NER. А это значит, что вы потратите время на NER, который (почти) не используется.
Dim
Не то, что я имел в виду. Просто создайте spacy.Docиз каждого текста, переберите их NER с помощью doc.entsи проверьте, имеет ли какой-либо NER .textатрибут, равный Apple. Интересный факт, их первый пример - Apple.
Szymon Maszke
И если кто-то захочет создать модель, он, скорее всего, будет включать RNN / CNN и тому подобное, настраивать их соответствующим образом, находить архитектуру, типы ячеек и т. Д. Я не думаю, что более простые модели хорошо справятся с устранением неоднозначности и контекстом. Зачем упрощать себе жизнь (если вы не хотите чему-то научиться по пути), если кто-то уже сделал это за вас?
Szymon Maszke
@SzymonMaszke, ваша модель сложнее и труднее обучается. Чтобы ваша модель работала для указанной цели, вам нужно не только найти сетевой элемент, но и найти его в нужном месте (токен). С помощью модели категоризации я предлагаю вам оптимизировать модель для вашей основной цели - определить, это компания Apple или фрукт Apple. Так легче тренировать, и поэтому, скорее всего, он будет более точным.
Dim