NLPx

Tales of Data Science

История об LDA2vec: взболтать, но не смешивать

catdog_word2vec_cropped

UPD: В английской версии этого поста оставили очень ценный комментарий, и теперь я вижу, что я слишком заострил внимание на различиях LDA и word2vec, а они с алгоритмической точки зрения не так уж и сильно отличаются. Поэтому я несколько изменил первоначальную версию текста. Кстати, рекомендую прочитать презентацию товарища Голдберга про word2vec.

Буквально только что, когда уже хотел взяться за написание текста про конференцию (как обещал в предыдущем посте), я обнаружил совсем недавно созданный гибридный алгоритм, который хитрым образом берет лучшее (по крайней мере, должен брать лучшее) из известного алгоритма тематического моделирования LDA (Латентное размещение Дирихле) и из чуть менее известного инструмента языкового моделирования word2vec (никак не расшифровывается, но про него я писал ранее).

Вы также можете прочитать этот текст на английском

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

В чем фишка?

Размышления на тему

homer2_lda2vec

Из LDA и word2vec автором инструмента lda2vec (Крис Муди его зовут, если что) были взяты разные идеи.

Идея, которую lda2vec взял из LDA — это его «глобальность», то есть возможность выделять из документов темы, которые могут быть легко (хотя и не всегда) интерпретированы человеком. Кроме того, LDA, в отличие от word2vec воспринимает набор разных документов именно как набор документов, а не как одну большую строку слов.

Из word2vec была взята идея «локальности» — т.е. идея возможности создавать векторные представления слов на небольших промежутках текста, так называемых «окнах».

Вообще, можно говорить о том, что word2vec предсказывает слова локально — т.е. при данном одном слове он предсказывает близлежащее слово. В то же время LDA предсказывает глобально — предсказывает слово относительно глобального контекста (всего набора документов).

LDA_image2

Типичный вектор word2vec представляет собой плотный вектор вещественных чисел, в то время как вектор LDA — разреженный вектор вероятностей слов принадлежать к теме. Разреженность вектора выражается в том, что большая часть значений в векторе будет равна нулю — за счет этого получается большая интерпретируемость модели. Плотный же вектор word2vec не может похвастаться такой же степенью интерпретируемости, но сильно выигрывает в гибкости (плотнее вектор — больше степеней свободы).

lda2vec_image

Каким же образом можно объединить эти, казалось бы, необъединяемые идеи?

UPD: На самом деле не такие уж они необъединяемые. Товарищ Голдберг проделал хорошую работу, доступно объяснив, что подход, лежащий в основе word2vec, может быть немного переинтерпретирован и сведен к чему-то до ужаса похожему на SVD, которое Singular Value Decomposition.

В то же время и LDA относится к SVD самым непосредственным образом:

  1. SVD — стандартная математическая техника
  2. LSI (Латентное семантическое индексирование) — просто применение SVD в задаче информационного поиска (или извлечения информации в общем)
  3. LSA (Латентный семантический анализ) — это просто LSI, приложенное к решению задач автоматической обработки естественного языка
  4. PLSA (Вероятностный латентный семантический анализ) — это улучшение LSA
  5. 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 соответствующим авторам книг. И в итоге выходит, что теоретически возможно использование этих связанных с авторами векторов для предсказывания каких-нибудь скрытых параметров, скажем, известности автора.

А если кратко?

homer-deep-thought_lda2vecВ объяснениях выше я не затрагивал особенные сложности, но все это может быть не очень понятно, а главное — скучновато. Поэтому можно сказать проще и уложиться в несколько пунктов.

Итак, о чем говорилось выше?

  • 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

Называются они не совсем по-человечески, но вполне понятно, о чем каждая из них.

Результаты я оценивал по двум субъективным критериям (с объективными было возиться лень, извините):

  1. Количество тем, которые я с первого взгляда смогу однозначно соотнести с реальными темами. Совпадающие темы я буду писать в скобках после списка слов, характеризующих тему LDA или lda2vec, например, (sci.med).
  2. Количество тем, которые хорошо выглядят, т.е. которым вполне можно подобрать адекватное название (пусть даже не совпадающее ни с одним из реальных). Такие темы я буду помечать тегом (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 на GitHub

Обсуждение lda2vec на Ycombinator

Презентация lda2vec на slideshare

 

4,474 просмотров всего, 4 просмотров сегодня

Rate this post

Leave a Reply

3 Comments on "История об LDA2vec: взболтать, но не смешивать"


Guest
Николай
7 months 26 days ago

Очень интересный обзор. Вы предполагаете, что это будет лучше работать с точки зрения сегментирования клиентов по-всей видимости в достаточно общие категории (спорт, литература, кино, например), но если речь идёт о кластеризации более частных проблем взаимодействия клиент-компания (вопросы по конкретной услуге, товару и т.д) так ли эффективен будет lda2vec по сравнению с LDA или doc2vec, что вы думаете? Спасибо.

7 months 18 days ago

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

Guest
Николай
7 months 16 days ago

Спасибо. Безусловно согласен с тем, что данные — определяющий момент, но надеюсь попробовать эффективность lda2vec и вернуться сюда с ответом.