UPD: В английской версии этого поста оставили очень ценный комментарий, и теперь я вижу, что я слишком заострил внимание на различиях LDA и word2vec, а они с алгоритмической точки зрения не так уж и сильно отличаются. Поэтому я несколько изменил первоначальную версию текста. Кстати, рекомендую прочитать презентацию товарища Голдберга про word2vec.
Буквально только что, когда уже хотел взяться за написание текста про конференцию (как обещал в предыдущем посте), я обнаружил совсем недавно созданный гибридный алгоритм, который хитрым образом берет лучшее (по крайней мере, должен брать лучшее) из известного алгоритма тематического моделирования LDA (Латентное размещение Дирихле) и из чуть менее известного инструмента языкового моделирования word2vec (никак не расшифровывается, но про него я писал ранее).
Вы также можете прочитать этот текст на английском
И сейчас я расскажу вам историю об lda2vec и моих попытках поиграться с реализацией и сравнить ее с алгоритмом LDA. Итак, однажды в студеную зимнюю пору…
В чем фишка?
Размышления на тему
Из LDA и word2vec автором инструмента lda2vec (Крис Муди его зовут, если что) были взяты разные идеи.
Идея, которую lda2vec взял из LDA — это его «глобальность», то есть возможность выделять из документов темы, которые могут быть легко (хотя и не всегда) интерпретированы человеком. Кроме того, LDA, в отличие от word2vec воспринимает набор разных документов именно как набор документов, а не как одну большую строку слов.
Из word2vec была взята идея «локальности» — т.е. идея возможности создавать векторные представления слов на небольших промежутках текста, так называемых «окнах».
Вообще, можно говорить о том, что word2vec предсказывает слова локально — т.е. при данном одном слове он предсказывает близлежащее слово. В то же время LDA предсказывает глобально — предсказывает слово относительно глобального контекста (всего набора документов).
Типичный вектор word2vec представляет собой плотный вектор вещественных чисел, в то время как вектор LDA — разреженный вектор вероятностей слов принадлежать к теме. Разреженность вектора выражается в том, что большая часть значений в векторе будет равна нулю — за счет этого получается большая интерпретируемость модели. Плотный же вектор word2vec не может похвастаться такой же степенью интерпретируемости, но сильно выигрывает в гибкости (плотнее вектор — больше степеней свободы).
Каким же образом можно объединить эти, казалось бы, необъединяемые идеи?
UPD: На самом деле не такие уж они необъединяемые. Товарищ Голдберг проделал хорошую работу, доступно объяснив, что подход, лежащий в основе word2vec, может быть немного переинтерпретирован и сведен к чему-то до ужаса похожему на SVD, которое Singular Value Decomposition.
В то же время и LDA относится к SVD самым непосредственным образом:
- SVD — стандартная математическая техника
- LSI (Латентное семантическое индексирование) — просто применение SVD в задаче информационного поиска (или извлечения информации в общем)
- LSA (Латентный семантический анализ) — это просто LSI, приложенное к решению задач автоматической обработки естественного языка
- PLSA (Вероятностный латентный семантический анализ) — это улучшение LSA
- LDA (Скрытое/Латентное размещение Дирихле) — улучшение PLSA
Таким образом, можно думать о разнице LDA и word2vec в терминах выбора гиперпараметров и их применения к разным задачам (для моделирования отношений документ-слово или отношений слово-слово). При этом алгоритмически (так сказать, по modus operandi) они очень близки.
Для того, чтобы иметь возможность предсказывать слово как локально, так и глобально, автор применяет подход, сходный подходу из paragraph2vec (он же doc2vec) — когда к каждому вектору слова прибавляется метка (label) о принадлежности его определенному документу. Однако в случае lda2vec используется не метка, а разреженный вектор LDA. Затем к получившемуся в результате сложения вектору можно прибавлять различные заранее известные категориальные признаки и уже потом рассчитывать распределение слов по темам.
Таким образом, когда мы говорим о предсказывании слов в тексте, то каждое последующее слово предсказывается не только исходя из их наиболее вероятного расположения в контексте, как в word2vec:
P(Vout|Vin)
но и исходя из вероятности этих слов встречаться друг с другом в определенной теме и с определенными признаками:
P(Vout|Vin+Vdoc+Vfeature)
где
Vdoc — грубо говоря вектор вероятностей принадлежать к темам для входного слова
Vfeature — некий категориальный признак
Вообще, подход очень интересный и потенциально открывает возможности использовать его для обучения с учителем, вводя заранее известные категориальные переменные в обучаемую модель.
С помощью этого подхода можно (в теории) делать модели для обучения с учителем — например, модель для оценки известности авторов книг. Для каждого слова мы складываем вектор этого слова из word2vec и вектор LDA, добавляем туда какие-нибудь известные категориальные признаки (например, год издания или название издательства). Получившийся вектор используется для «присваивания» тем LDA соответствующим авторам книг. И в итоге выходит, что теоретически возможно использование этих связанных с авторами векторов для предсказывания каких-нибудь скрытых параметров, скажем, известности автора.
А если кратко?
В объяснениях выше я не затрагивал особенные сложности, но все это может быть не очень понятно, а главное — скучновато. Поэтому можно сказать проще и уложиться в несколько пунктов.
Итак, о чем говорилось выше?
- Word2vec моделирует отношения слово-слово, в то время как LDA моделирует отношения документ-слово
- Модель lda2vec пытается совместить лучшие элементы обеих вышеуказанных моделей в один фреймворк.
- Модель lda2vec создана с целью построения как тем на основе документов, так и тем на основе слов (одновременно), при этом теоретически возможно использование модели для обучения с учителем, чтобы создавать т.н. supervised темы с учетом различных параметров.
А зачем это кому-нибудь должно понадобиться?
- Этот подход должен улучшить качество тематического моделирования
- Эта штука должна прийтись ко двору бизнесу, которому очень интересно более качественно типизировать своих клиентов на основании их отзывов, покупок и всякого такого (например, вот этот покупатель — на 60% любитель спорта и на 40% — любитель выпить).
Сравниваем Lda2vec с LDA
Какие тестовые данные?
В качестве тестового набора данных автор использует набор данных «Twenty newsgroups» из библиотеки scikit-learn (sklearn.datasets). Набор данных состоит из 18000 текстов на 20 различных тем. Данные разбиты на два набора — тренировочный и тестовый. Для примера в lda2vec автор использует тренировочный набор данных.
В наборе данных присутствует 20 тем:
- comp.graphics
- comp.os.ms-windows.misc
- comp.sys.ibm.pc.hardware
- comp.sys.mac.hardware
- comp.windows.x
- rec.autos
- rec.motorcycles
- rec.sport.baseball
- rec.sport.hockey
- sci.crypt
- sci.electronics
- sci.med
- sci.space
- misc.forsale
- talk.politics.misc
- talk.politics.guns
- talk.politics.mideast
- talk.religion.misc
- alt.atheism
- soc.religion.christian
Называются они не совсем по-человечески, но вполне понятно, о чем каждая из них.
Результаты я оценивал по двум субъективным критериям (с объективными было возиться лень, извините):
- Количество тем, которые я с первого взгляда смогу однозначно соотнести с реальными темами. Совпадающие темы я буду писать в скобках после списка слов, характеризующих тему LDA или lda2vec, например, (sci.med).
- Количество тем, которые хорошо выглядят, т.е. которым вполне можно подобрать адекватное название (пусть даже не совпадающее ни с одним из реальных). Такие темы я буду помечать тегом (looks ok).
Автор в своем репозитории на GitHub приводит следующие результаты работы lda2vec:
- topic 0 out_of_vocabulary hicnet x/ oname hiv pts lds eof_not_ok
- topic 1 out_of_vocabulary hiv vitamin infections candida foods infection dyer diet patients (sci.med) (looks ok)
- topic 2 out_of_vocabulary duo adb c650 centris lciii motherboard fpu vram simm (looks ok)
- topic 3 yeast candida judas infections vitamin foods scholars greek tyre
- topic 4 jupiter lebanese lebanon karabakh israeli israelis comet roby hezbollah hernlem (talk.politics.mideast) (looks ok)
- topic 5 xfree86 printer speedstar font jpeg imake deskjet pov fonts borland (looks ok)
- topic 6 nubus 040 scsi-1 scsi-2 pds israelis 68040 lebanese powerpc livesey
- topic 7 colormap cursor xterm handler pixmap gcc xlib openwindows font expose (comp.graphics) (looks ok)
- topic 8 out_of_vocabulary circuits magellan voltage outlet circuit grounding algorithm algorithms polygon
- topic 9 amp alomar scsi-1 scsi-2 68040 mhz connectors hz wiring (looks ok)
- topic 10 astronomical astronomy telescope larson jpl satellites aerospace visualization redesign (sci.space) (looks ok)
- topic 11 homicides homicide handgun ># firearms cramer guns minorities gun rushdie (talk.politics.guns) (looks ok)
- topic 12 out_of_vocabulary koresh adl bullock atf batf fbi davidians waco nra
- topic 13 stephanopoulos stimulus keenan vat prize lopez gainey
- topic 14 bike dod# lyme :> corn gt behanna cview bmw bikes (rec.motorcycles) (looks ok)
- topic 15 out_of_vocabulary algorithm 80-bit ciphers cipher plaintext encrypted escrow ciphertext decrypt (sci.crypt) (looks ok)
- topic 16 riders bike rider jody satan eternal helmet riding god ra
- topic 17 stephanopoulos sumgait secretary karina q senator serbs azerbaijani (talk.politics.misc) (looks ok)
- topic 18 out_of_vocabulary tires anonymity tire brake plaintext ciphertext ciphers helmet
- topic 19 m»`@(«`@(«`@(«`@(«`@(«`@(«`@(«`@(«` max>’ax>’ax>’ax>’ax>’ax>’ax>’ax>’ax pts pt det 55.0 $ tor nyi
Результаты пока довольно грязные, однако для некоторых тем lda2vec можно найти соответствия в реальных темах. Я. например, сразу смог соотнести 8 тем, при этом 11 тем выглядят вполне нормально (включая те, для которых я нашел соответствия).
А теперь сравним эти результаты с результатами работы простого алгоритма LDA в реализации gensim. Я написал быстрый скрипт, где не вход в LDA подаются тексты в том же объеме и с почти той же предобработкой и сходным количеством итераций алгоритма (вы можете взять его у меня на GitHub и попробовать):
- topic 0: game team play player win season last hockey score run (rec.sport.hockey) (looks ok)
- topic 1: nasa gov jpl nec dseg power run center cool research
- topic 2: government war tax insurance cramer arm law militia health bear
- topic 3: armenian turkish law muslim jew greek turk government armenia jewish (talk.politics.mideast) (looks ok)
- topic 4: believe christian mean science exist bible truth reason book belief (alt.atheism) (looks ok)
- topic 5: drive washington mail mac space please hard thank computer disk
- topic 6: file run thank version mit mouse help card graphic ibm (looks ok)
- topic 7: key encryption clipper government phone public chip netcom clinton information (sci.crypt) (looks ok)
- topic 8: jesu christian believe life day tell live law love christ (soc.religion.christian) (looks ok)
- topic 9: scsi drive bit card ide mac file color controller bus (comp.sys.mac.hardware) (looks ok)
- topic 10: pitt food bank msg gordon keith water cause geb caltech
- topic 11: car drive buy dealer israeli navy price mile virginia really
- topic 12: thank drive usa cleveland please sale mail cwru computer monitor
- topic 13: max uiuc value manager nasa cso men show set number
- topic 14: space bike nasa list ride launch orbit motorcycle image data
- topic 15: price sale file org access uucp help bob net maynard
- topic 16: key chip clipper bit encryption law government technology toronto alaska (looks ok)
- topic 17: gun israel israeli arab kill weapon firearm attack american control (talk.politics.guns) (looks ok)
- topic 18: van chi uchicago win helmet princeton access det rutger tor
- topic 19: jim government drug never isc udel fbi cwru case morality (talk.politics.misc) (looks ok)
LDA показывает приблизительно такие же результаты — я сразу соотнес 8 тем, при этом 11 тем выглядят вполне адекватными (включая те, для которых я нашел соответствия). Это говорит о том, что в текущей версии lda2vec качество тематического моделирования приблизительно такое же, как и у обычного LDA (если увеличивать итерации и там, и там — качество должно вырасти). Это неплохо, однако я ожидал чего-то более веселого.
Безусловно, кому-то может показаться, что количество тем, которые можно однозначно соотнести и вообще хорошо выглядящих тем на самом деле меньше (или больше), но все равно видно, что качество тематического моделирования более-менее одинаковое.
Как его попробовать самому?
Устанавливаем сам lda2vec
Lda2vec можно скачать с GitHub-репозитория его автора, распаковать в какую-нибудь папку, затем запустить setup.py с помощью команды (в командной оболочке, само собой):
sudo python /path-to-lda2vec-package/lda2vec/setup.py install
где /path-to-lda2vec-package/ — путь к распакованному вами архиву с lda2vec.
Если вы устанавливаете lda2vec не в стандартную директорию, где хранятся все библиотеки питона, то вам необходимо прописать в sys.path путь к папке с lda2vec.
Например, в моем случае:
import sys sys.path.append('/home/torselllo/lda2vec/') print sys.path >>['/usr/lib/python2.7', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages', '/usr/lib/pymodules/python2.7', '/home/torselllo/lda2vec/']
И можно запускать. Но не забудьте установить зависимости!
Устанавливаем зависимости
Чтобы самостоятельно попробовать lda2vec, необходимо установить зависимости — NumPy, Chainer и spaCy:
- NumPy — это расширение языка Python, добавляющее поддержку больших многомерных массивов и матриц, вместе с большой библиотекой высокоуровневых математических функций для операций с этими массивами.
- Chainer — это фреймворк для работы с нейросетями для глубокого (и не очень) обучения
- spaCy — это библиотека для обработки естественного языка, славящаяся (по мнению ее авторов) скоростью и точностью работы
Установить их проще всего можно с помощью pip
Обходим возможные проблемы со spaCy
Нужно заметить, что spaCy — достаточно хитрая штука в плане установки. Например, если просто установить ее с помощью pip, а затем запустить lda2vec — может произойти интересная вещь — вы получите ошибку ввода-вывода:
>> IOError: /usr/local/lib/python2.7/dist-packages/spacy/en/data/vocab/strings.json.
Попытавшись выяснить причину ошибки, вы быстро узнаете, что по вышеуказанному пути просто ничего нет. Зайдя на официальный сайт spaCy, вы поймете, что еще нужно установить модель для английского языка с помощью следующей команды в командной оболочке:
sudo python -m spacy.en.download
Будьте осторожны — модель качается с официального репозитория и весит 519.05MB
Казалось бы — просто, но не очевидно, особенно если устанавливаешь в качестве зависимости и не посещаешь перед этим официальный сайт.
Проблемы могут продолжиться, если модель скачается в другую директорию (а она это может!). В моем случае она скачалась в директорию
/usr/local/lib/python2.7/dist-packages/spacy/data/en_default-1.0.7
а искать ее lda2vec продолжала в
/usr/local/lib/python2.7/dist-packages/spacy/en/data/
Исправить это можно небольшим грязным хаком — переместить модель туда, где ее будут искать! Сделать это можно с помощью классической команды mv, которая не только перемещает, но и переименовывает. В моем случае я сделал так:
sudo mv /usr/local/lib/python2.7/dist-packages/spacy/data/en_default-1.0.7 /usr/local/lib/python2.7/dist-packages/spacy/en/data/
Дальше можно запускать пример. Но, если вы не собираетесь применять расчеты на GPU (которые работают в 10 раз быстрее, чем расчеты на CPU), потому что у вас видеокарта, не поддерживающая работу библиотеки CUDA (не NVidia GeForce, например), то будьте осторожны — в нынешней версии (26 января 2016) реализация lda2vec очень долго сходится. К примеру, на 500 входных документов все это дело считалось час (core i5 2МГц, 2 Гб ОЗУ). На всех 18 000 текстов считалось больше 12 часов, а потом мне надоело и я выключил, так и не доведя дело до конца, каюсь.
Заключение
Это была история об lda2vec, интересном подходе и реализации этого подхода, который я попробовал и сравнил с обычным LDA. Подход интересный и, кажется, достаточно перспективный, хотя в данную минуту выглядит не полностью убедительно.
На всякий случай сообщаю, что данная минута — это 30 января 2016 года.
Ссылки
Официальная документация по lda2vec
Обсуждение lda2vec на Ycombinator
Презентация lda2vec на slideshare
22,105 просмотров всего, 1 просмотров сегодня
Очень интересный обзор. Вы предполагаете, что это будет лучше работать с точки зрения сегментирования клиентов по-всей видимости в достаточно общие категории (спорт, литература, кино, например), но если речь идёт о кластеризации более частных проблем взаимодействия клиент-компания (вопросы по конкретной услуге, товару и т.д) так ли эффективен будет lda2vec по сравнению с LDA или doc2vec, что вы думаете? Спасибо.
Я думаю, что lda2vec (как и многие его коллеги, вроде sence2vec и прочие тувеки) как гибридный алгоритм теоретически способен определять и более узкие темы, если данных будет достаточно много — в том числе и достаточно много данных по каждой конкретной услуге-товару (сбалансированная выборка). Однако в текущем его состоянии значительное увеличение качества пока не заметно. Вообще, я по опыту знаю, что когда речь идет об очень специфичных объектах для обработки, то там не обойтись без значительного количества ручной работы и множества эвристик — просто кластеризация/тематическое моделирование на исходных данных покажет так себе результаты. Т.е. не видя данных, я не готов однозначно… Read more »
Спасибо. Безусловно согласен с тем, что данные — определяющий момент, но надеюсь попробовать эффективность lda2vec и вернуться сюда с ответом.