Ниже вы найдете 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 ).
Ответы:
Я бы сделал это так:
источник
То, что вы ищете, называется распознаванием именованных сущностей . Это статистический метод, который (наиболее часто) использует условные случайные поля для поиска именованных сущностей, основываясь на том, что они были обучены узнавать что-то об именованных сущностях.
По сути, он смотрит на содержание и контекст слова (оглядываясь назад и вперед на несколько слов), чтобы оценить вероятность того, что слово является именованным объектом.
Хорошее программное обеспечение может анализировать другие особенности слов, такие как их длина или форма (например, «Vcv», если оно начинается с «гласный-согласный-гласный»).
Очень хорошая библиотека (GPL) - это Стэнфордский NER
Вот демонстрация: http://nlp.stanford.edu:8080/ner/
Пример текста, который стоит попробовать:
(классификаторы 3 и 4 класса правильно понимают)
источник
english.conll.4class.distsim.crf.ser.gz
? Я бы хотел посмотреть, как можно построить что-то подобное.У меня есть частично работающая система, которая решает эту проблему, с открытым исходным кодом с использованием 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:
Что нужно учитывать:
Re. переоснащение. В моем наборе данных с 2000 элементами у меня есть 10-минутный снимок «яблочных» твитов из Twitter. Около 2/3 твитов адресовано Apple Inc, 1/3 - другим пользователям Apple. Я выбираю сбалансированное подмножество (я думаю, около 584 строк) каждого класса и делаю пятикратную перекрестную проверку для обучения.
Поскольку у меня есть только 10-минутное временное окно, у меня много твитов на ту же тему, и, вероятно, именно поэтому мой классификатор работает так хорошо по сравнению с существующими инструментами - он будет переоснащен функциями обучения без хороших обобщений (тогда как существующий коммерческий инструменты работают хуже в этом снапшопе, но более надежно для более широкого набора данных). Я буду расширять свое временное окно, чтобы проверить это в качестве последующей работы.
источник
Вы можете сделать следующее:
Составьте диктовку слов, указав их количество в твитах о фруктах и компаниях. Этого можно добиться, скармлив ему несколько примеров твитов, наклон которых нам известен.
Используя достаточное количество предыдущих данных, мы можем выяснить вероятность появления слова в твите о apple inc.
Умножьте отдельные вероятности слов, чтобы получить вероятность всего твита.
Упрощенный пример:
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"
источник
Если у вас нет проблем с использованием сторонней библиотеки, я бы порекомендовал 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, он должен дать вам представление о том, с чего начать.
РЕДАКТИРОВАТЬ: попытался более подробно объяснить шаги.
источник
Использование дерева решений, кажется, вполне подходит для решения этой проблемы. По крайней мере, он обеспечивает более высокую точность, чем наивный байесовский классификатор с выбранными мной функциями.
Если вы хотите поэкспериментировать с некоторыми возможностями, вы можете использовать следующий код, который требует установки 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()
источник
dict()
где-то еще? Я думаю, что если тренировочная выборка достаточно велика, не должен ли компьютер сам определять особенности? (без присмотра?)'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
? А из заданных положительных и отрицательных би и триграмм дерево решений или классификаторы Байеса могут творить чудеса?Спасибо за комментарии. Вот рабочее решение, которое я подготовил с помощью 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.
источник
Во всех приведенных вами примерах Apple (inc) упоминается как A pple или apple inc , поэтому возможный способ поиска:
заглавная буква "А" в яблоке
"inc" после яблока
слова / фразы, такие как «ОС», «операционная система», «Mac», «iPhone», ...
или их комбинация
источник
Чтобы немного упростить ответы на основе условных случайных полей ... контекст здесь огромен. Вы захотите выделить те твиты, которые ясно показывают, что Apple - компания, а яблоко - плод. Позвольте мне обрисовать здесь список функций, которые могут быть вам полезны для начала. Для получения дополнительной информации найдите разделение именных фраз и нечто, называемое BIO-метками. См. ( Http://www.cis.upenn.edu/~pereira/papers/crf.pdf )
Окружающие слова: создайте вектор признаков для предыдущего слова и следующего слова, или, если вам нужно больше функций, возможно, для предыдущих 2 и следующих 2 слов. Вы не хотите, чтобы в модели было слишком много слов, иначе она не будет очень хорошо соответствовать данным. В обработке естественного языка вы захотите сделать это как можно более общим.
Другие особенности, которые можно получить из окружающих слов, включают следующее:
Является ли первый символ заглавным
Является ли последний символ в слове точкой
Часть речи слова (Найдите часть пометки речи)
Сам текст слова
Я не советую этого, но приведу больше примеров функций специально для Apple:
WordIs (Apple)
NextWordIs (Inc.)
Вы уловили суть. Думайте о распознавании именованных сущностей как об описании последовательности, а затем с помощью математики, чтобы сообщить компьютеру, как это вычислить.
Имейте в виду, что обработка естественного языка - это конвейерная система. Как правило, вы разбиваете все на предложения, переходите к токенизации, а затем выполняете часть речевых тегов или даже синтаксический анализ зависимостей.
Это все, чтобы получить список функций, которые вы можете использовать в своей модели, чтобы определить, что вы ищете.
источник
Там действительно хорошая библиотека для обработки текстов на естественном языке в Python под названием
nltk
. Вы должны взглянуть на это.Одна из стратегий, которую вы можете попробовать, - это посмотреть на n-граммы (группы слов) со словом «яблоко» в них. Некоторые слова с большей вероятностью будут использоваться рядом с словом «яблоко» при разговоре о фруктах, другие - при разговоре о компании, и вы можете использовать их для классификации твитов.
источник
nltk
), который поможет мне начать в правильном направлении с задачей машинного обучения "привет, мир". Сравнение яблока (inc) и яблока (фрукта) кажется идеальным выбором.Используйте LibShortText . Эта утилита Python уже настроена для работы с задачами категоризации короткого текста, и она хорошо работает. Максимум, что вам нужно сделать, это написать цикл, чтобы выбрать лучшую комбинацию флагов. Я использовал его для контролируемой классификации речевых актов в электронных письмах, и результаты были точными до 95-97% (во время пятикратной перекрестной проверки!).
И он исходит от создателей LIBSVM и LIBLINEAR, чья реализация векторной машины поддержки (SVM) используется в sklearn и cran, так что вы можете быть разумно уверены, что их реализация не содержит ошибок.
источник
Сделайте фильтр AI, чтобы отличить Apple Inc (компания) от яблока (фрукта). Поскольку это твиты, определите свой обучающий набор с вектором из 140 полей, каждое поле - это символ, записанный в твите в позиции X (от 0 до 139). Если твит короче, просто укажите значение, чтобы он был пустым.
Затем создайте тренировочный набор, достаточно большой, чтобы получить хорошую точность (субъективно на ваш вкус). Присвойте значение результата каждому твиту, твит Apple Inc получит 1 (истина), а яблочный твит (фрукт) - 0. Это будет случай контролируемого обучения в логистической регрессии .
То есть машинное обучение, его проще кодировать и работать лучше. Он должен извлекать уроки из набора, который вы ему даете, и он не запрограммирован жестко.
Я не знаю Python , поэтому не могу написать для него код, но если вам нужно больше времени на логику и теорию машинного обучения, вы можете посмотреть класс, за которым я следую.
Попробуйте пройти курс Machine Learning на Coursera от Эндрю Нг . Вы изучите машинное обучение на MATLAB или Octave , но как только вы освоите основы, вы сможете писать машинное обучение на любом языке, если понимаете простую математику (простую в логистической регрессии).
То есть получение кода от кого-то не позволит вам понять, что происходит в коде машинного обучения. Вы можете потратить пару часов на эту тему, чтобы увидеть, что происходит на самом деле.
источник
Я бы рекомендовал избегать ответов, предполагающих распознавание сущностей. Потому что эта задача - во-первых, классификация текста, а во-вторых - распознавание сущностей (вы можете сделать это вообще без распознавания сущностей).
Я думаю, что самый быстрый путь к результату будет простор + вундеркинд . Spacy имеет хорошо продуманную модель для английского языка, поэтому вам не нужно создавать свою собственную. В то время как Prodigy позволяет быстро создавать наборы обучающих данных и точно настраивать пространственную модель для ваших нужд.
Если у вас будет достаточно образцов, вы сможете получить достойную модель за 1 день.
источник
spaCy
естьner
трубопроводная составляющая, разве это не будет выгодно для этой классификации? Я предполагаю, что их модель может распознатьApple
(поскольку это одна из самых крупных и известных компаний в мире) намного лучше, чем модель, которую вы можете придумать за один день.spacy.Doc
из каждого текста, переберите их NER с помощьюdoc.ents
и проверьте, имеет ли какой-либо NER.text
атрибут, равныйApple
. Интересный факт, их первый пример - Apple.