BigARTM CLI

Приложение bigartm.exe

Приложение bigartm.exe (в Unix — просто bigartm) — самостоятельный бинарик, работающий по следующему алгоритму:

  1. Распарсить корпус и создать батчи
  2. Загрузить словарь, если он указан
  3. Инициализировать или загрузить модель
  4. Сделать определенное число итераций EM алгоритма
  5. При последнем проходе по корпусу вывести в файл тематические профили документов (вектора $\theta$)
  6. Вывести модель/словарь в файлы

Самостоятельный бинарник

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

Для сборки самостоятельного бинарика gcc нужно передавать флаг -static. В cmake нужно прописать что-то такое:

SET(CMAKE_EXE_LINKER_FLAGS "-static")

Ключи консольного приложения

  • --rand-seed <seed>: инициализация генератора случайных чисел, гарантируется что приложение отрабатывает с одинаковым результатом при одинаковом значении seed. По-умолчанию выбирается по таймеру (случайно).
  • --response-file <file>: текстовый файл содержащий ключи коммандной строки данного бинарного файла (bigartm.exe). В отличии от коммандной строки, файл response-file может состоять из нескольких строк. Это может быть полезно при ограничениях операционной системы на длину коммандной строки, или для удобства редактирования параметров запуска.

1. Corpus / Batches

Парсинг корпуса и создание батчей:

  • --read-vw-corpus <file/url>: источник, из которого поступает корпус в формате Vowpal Wabbit
  • --read-uci-docword <file/url>: источник, из которого поступает корпус в формате UCI Bag-of-Words
  • --read-uci-vocab <file/url>: источник, из которого поступает словарь формата UCI Bag-of-Words

Минус (-) в <file/url> означает stdin, может быть указан локальный файл; в дальнейшем хочется добавить поддержку hdfs и других сетевых протоколов.

  • --batch-size <N>: число документов в одном батче

Чтение батчей, подготовленных заранее:

  • --use-batches <batches-path>: путь к батчам, использовать заранее подготовленные батчи

По умолчанию считается, что подготовленные батчи отсутствуют и сырой корпус читается из stdin в формате Vowpal Wabbit.

2. Dictionary

Использование существующего словаря:

  • --use-dictionary <dictionary-file>: использовать словарь, загруженный из файла в бинарном формате
  • настройки динамического словаря (в случае если он меняется), мин частота, макс число токенов

Если не указана опция использования существующего словаря, то по-умолчанию создается новый словарь.

Ключи фильтрации токенов при создании словаря. Основная идея: ключи ограничивают снизу (min) и сверху (max) либо частоту появления токенов (документная — df, токенная — tf), либо их квантили — (документная — dfq, токенная — tfq). Если ключу указано целое число >= 1 — значение воспринимается как <N>, если ключу указано вещественное число < 1, либо число со знаком процента на конце — значение воспринимается как <P>.

  • --dictionary-min-df <N/P>: фильтровать токены, встречающиеся в менее чем N документах / менее чем P% документов
  • --dictionary-max-df <N/P>: фильтровать токены, встречающиеся в более чем N документах / более чем P% документов
  • --dictionary-min-dfq <N/P>: фильтровать N токенов / P% токенов, встречающихся в наименьшем числе документов
  • --dictionary-max-dfq <N/P>: фильтровать (#Tokens - N) токенов / (100 - P)% токенов, встречающихся в наибольшем числе документов
  • аналогичные ключи для term frequency: --dictionary-min/max-tf/tfq

Примеры:

  • --dictionary-min-tfq 20
  • --dictionary-max-df 30%
  • --dictionary-max-dfq 0.98

3. Model

На этой фазе происходит создание модели: модель может быть загружена из файла, либо инициализирована по словарю.

  • --load-model <model-file>: загрузить модель из файла

Если не указана опция загрузки модели, то модель инициализируется.

  • --topics <N>: создать N тем, имеющих названия topic_0,...,topic_(N-1)
  • --topics <group>:<n>,...,<group>:<n>: создать группы тем, для каждой группы создается соответствующее число тем с названиями вида <group>_<k>; если у группы не указан размер, то создается группа из одной темы
  • (*) --initialize <scheme>: инициализировать матрицу $\Phi$ одной из схем; пока у нас только одна схема инициализации — команда не нужна

Пример: bigartm ... --topics 100 — создать 100 тем; bigartm ... --topics objective:100,background:3,thrash — создать 100 целевых тем (objective), 3 фоновые темы (background) и 1 специальную трэш-тему.

4. Learning Options

Для обучения модели используется EM-алгоритм.

  • -p <N> или --num-collection-passes <N>: число проходов по корпусу, по умолчанию N=1

E-шаг

На E-шаге оцениваются вектора $\theta$

  • --inner-iterations-count <N>: число итераций внутреннего цикла (оптимизация векторов theta)

M-шаг

На M-шаге производится обновление модели, в он-лайн алгоритме вес обновления берется из выражения $w = (\tau_0 + \text{update-count})^{-\kappa}$, где параметр $\text{update-count}$ равен числу обработанных батчей. Значения по-умолчанию для параметров обновления взяты из статьи Хоффмана.

  • --update-every <N>: производить обновление модели каждые N батчей; если не указано, то используется офф-лайн алгоритм
  • --tau0 <F>: параметр из выражения для веса обновления; по-умолчанию tau0=1024
  • --kappa <F>: показатель степени в выражении для веса обновления; по-умолчанию kappa=0.7

Модальности

  • --use-modalities <modality>:<w>,...,<modality>:<w>: использовать только указанные модальности, назначив им соответствующие веса; если опция не указана то используются все модальности с весом 1, у модальности может быть не указан вес — по-умолчанию считается равным 1

Пример: bigartm ... --use-modalities words,author:10,link:0.2 — будет обучена модель с модальностями words (вес 1.0), author (вес 10.0), link (вес 0.2).

Регуляризаторы

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

--regularizer "<weight> <regularizer-constructor> [#<topics>] [@<modalities>] [!<dictionaries>]"

Кавычки обязательны: это два поля в массиве argv — ключ и его значение. Конструктор регуляризатора — название регуляризатора, которое может содержать параметры (если появятся регуляризаторы с параметрами).

Регуляризатор SparseSmooth(Phi/Theta)Regularizer настоятельно предлагаю сделать двумя регуляризаторами, у которых веса действуют в разные (по знаку) стороны: smoothPhi/sparsePhi, smoothTheta/sparseTheta.

Примеры:

  • --regularizer "0.1 smoothPhi"
  • --regularizer "25.0 sparseTheta"
  • --regularizer "10 decorrelation @words"
  • --regularizer "0.1 specific(x,y) #topic1,topic2 @words,author !dictionary"

Функционалы качества

Предустановленные наборы функционалов качества контролируются ключем --score-level <N>. Возможны следующие варианты:

  • --score-level 0 - функционалы качества не вычисляются
  • --score-level 1 - на каждой итерации вычисляются и отображаются Perplexity, ThetaSparsity и PhiSparsity
  • --score-level 2 - на последней итерации дополнительно выводятся функционалы TopTokens и ThetaSnippet
  • --score-level 3 - на каждой итерации дополнительно выводятся функционалы группы TopicKernel (средний размер, чистота и контрастность тематических ядер)

По умолчанию используется опция --score-level 2.

Для более детельной настройки функционалов качества можно использовать ключи --score и --final-score, синтакс которых аналогичен ключу --regularizer:

--score "<score-constructor> [#<topics>] [@<modalities>] [!<dictionaries>]"

--final-score "<score-constructor> [#<topics>] [@<modalities>] [!<dictionaries>]"

Функционалы качества, добавленные с помощью опции --score, будут отображаться после каждой итерации; функционалы качества, добавленные с помощью опции --final-scores --- лишь после последный итерации.

Конструктор регуляризатора — название функционала качества, которое может содержать параметры. Например, в конструкторе TopTokens указывается желаемое количество слов каждой темы, в конструкторе ThetaSnippet — количество документов, в конструкторе TopicKernel — вещественный параметр Probability Mass Threshold.

Использование любого из ключей --score или --final-score автоматически выключает все предустановленные функционалы качества (--score-level 0).

Доступные типы функционалов качества: Perplexity,SparsityTheta,SparsityPhi,TopTokens,ThetaSnippet,TopicKernel.

Примеры:

  • --score "Perplexity !dictionary"
  • --score "SparsityTheta #objective"
  • --score "SparsityPhi #background @words"
  • --score "TopTokens(7) @words "
  • --score "ThetaSnippet(7)"
  • --score "TopicKernel(0.2) #objective"

Multicore Mode

  • --threads <N>: число потоков в которых производить обучение, по умолчанию N=1

Distributed Mode

Пока не нужно реализовывать.

5. Output

  • --save-model <model-file>: по окончанию обучения записать модель в файл
  • --save-dictionary <dictionary-file>: вывести словарь в файл
  • --save-batches <batches-path>: при первом чтении генерировать батчи и записывать по назначению; если не указано, то батчи пишутся во временный каталог, который удаляется перез завершением работы bigartm
  • --write-predictions <predictions-file>: вывести тематические профили документов с последнего прохода по коллекции, в формате CSV. Возможность вывода в stdout!
  • --write-model-readable <model-csv-file>: по окончанию обучения записать модель в текстовый файл в формате CSV

Ключам --write-* можно указывать значение - — это будет означать что писать нужно в stdout.

Пояснение: принцип использования write/use/load

  • --read / --write призвано работать с некоторой потоковой информацией в текстовом формате, которую можно читать из stdin и записывать в stdout посредством специального значения - (минус)
  • --use / --save используется для работы со статичным объектом (словарь, набор батчей), который не изменяется в результате работы программы; статичный объект либо созается и потом сохраняется посредством save, либо он загружается из файла посредством use
  • --load / --save используется для объектов, которые меняются к концу выполнения программы; при помощи load мы загружаем такой объект, затем мы его меняем, сохраняем новую версию посредством save

Информационный вывод и логирование

Информационный вывод должен производиться исключительно в stderr, поскольку в stdout может подаваться результат — тематические профили документов.

Что выводить в stderr

Пример вывода в stderr:

$ bigartm --read-corpus ...  # (запуск команды)
bigartm --read-corpus ... (исходная команда: склеенный полный argv[])

Parsing corpus: <corpus-path> -> <batches-dir> (или tmp если не указано --save-batches), <N> docs per batch
Iter 1: batches=123 (сколько батчей обработали), update_weight=0.123 (какой вес был на этой итерации), perplexity=12312.123
Iter 2: batches=246, update_weight=0.112, perplexity=9234.12
...
Iter 50: ...

Topic snippet:
<Phi matrix snippet>

Идеи

Что еще выводить в stderr:

  • число проходов
  • число обработанных документов
  • метрики качества
    • перплексия
    • разреженность по модальностям
  • способы подсчета метрик: hold-out / progressive-validation
  • логарифмический вывод (как в vw)

Форматы файлов

Текстовые форматы

Формат корпуса Vowpal Wabbit (--read-vw-corpus)

Формат корпуса UCI Bag-of-Words (--read-uci-docword)

Формат словаря UCI Bag-of-Words (--read-uci-vocab)

Человекочитаемая модель (--write-model-readable)

Предсказания (--write-predictions)

Бинарные форматы

В бинарные файлы записыватюся protobuf-сообщения.

  • Модель
  • Словарь

Примеры использования

На этих примерах нужно протестировать новое CLI, а в конечном счете – сделать подробное описание этих примеров в документации.

1. Эксперимент на датасетах UCI Bag-of-Words

Предположим, что мы загрузили данные с UCI в каталог data.

Обучение ванильной модели PLSA

bigartm \
    --read-uci-docword data/docword.enron.txt \
    --read-uci-vocab data/vocab.enron.txt \
    --topics 50 \
    --num-collection-passes 30 \
    --save-model enron_50topics.model \
    --write-predictions enron_50topics.theta.txt \
    --write-model-readable enron_50topics.phi.txt

Инициализируем модель для корпуса nytimes несколькими итерациями без регуляризаторов, создадим 100 тем с префиксом topic (целевые темы) и 3 темы noise (шумовые):

bigartm \
    --read-uci-docword data/docword.nytimes.txt \
    --read-uci-vocab data/vocab.nytimes.txt \
    --batch-size 1000 \
    --topics "topic:100,noise:3" \ # создает 103 темы: topic_0,topic_1,...,topic_99,noise_0,...,noise_2
    --num-collection-passes 5 \
    --update-every 5 \
    --save-model nytimes_100topics_3noise.init.model \
    --save-batches nytimes.batches \ # название каталога с батчами, который необходимо создать
    --save-dictionary nytimes.dict \ # словарь в бинарном формате
    --threads 8

Продолжим обучение модели. Теперь включаем регуляризаторы; шумовые темы будут сглаживаться, а целевые — разреживаться и декоррелироваться:

bigartm \
    --use-dictionary nytimes.dict \
    --use-batches nytimes.batches \
    --load-model nytimes_100topics_3noise.init.model \
    --regularizer "0.5 smoothPhi #noise" \
    --regularizer "0.5 sparsePhi #topic" \
    --regularizer "0.5 smoothTheta #noise" \
    --regularizer "0.5 sparseTheta #topic" \
    --regularizer "1000 decorrelation #topic" \
    --num-collection-passes 50 \
    --update-every 3 # детальная настройка итераций
    --tau0 128 \  
    --kappa 0.5 \
    --save-model nytimes_100topics_3noise.model \
    --write-predictions nytimes_100topics_3noise.theta.txt \
    --write-model-readable nytimes_100topics_3noise.phi.txt \
    --threads 32

2. Обучение модели мультиязычной Википедии и использование для разметки документов

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

Для обучения тематической модели был подготовлен мультиязычный корпуc в построчном формате vw, его положили в партицированном виде в HDFS (как результат работы MapReduce задачи, к примеру):

hdfs -cat wikipedia_corpus/part_00001

  page_2342123 |en computer:2 device:3 mouse input |ru мышь:2 устройство компьютер |es ratón dispositivo:3 computadora:2
  page_5645623 |en crusade:4 heretics:2 jerusalem |fr croisades:3 hérétique:2
  ...

Инициализируем модель и словарь, корпус подается на вход через stdin:

hdfs -cat wikipedia_corpus/\* | bigartm \
    --dictionary-min-df 3 \   # брать слово если оно нашлось не менее чем в 3х документах
    --dictionary-max-df 30% \ #  ... не более чем в 30% документов
    --read-vw-corpus - \ # минус значит что читать из stdin
    --topics topic:1000 \
    --use-modalities en,ru,fr,es,de,it \
    --save-batches wikipedia.batches \
    --save-dictionary wikipedia.dict \
    --save-model wikipedia_1k_topics.initial.model

Теперь обучим хорошую модель, параллельно:

bigartm \
    --use-batches wikipedia.batches \
    --load-model wikipedia_1k_topics.initial.model \
    --num-collection-passes 100 \
    --regularizer "0.5 sparsePhi #topic" \
    --kappa 0.8 \
    --write-model wikipedia_1k_topics.model \
    --write-model-readable wikipedia_1k_topics.phi.txt \
    --threads 32

Ура, теперь можем использовать модель для разметки документов по темам:

echo "new_document |ru пхнглуи мглвнафх рльех вгахнагл фхтагн ктулху" | bigartm  \
    --load-model wikipedia_1k_topics.model \
    --read-vw-corpus - \     # прочитать корпус из stdin 
    --write-predictions - # записать предсказания в stdout

  new_document    0    0    0    0.3    0    0    0    ...    0    0.1    0

В таком виде BigARTM можно использовать для разметки произвольно большого набора документов при помощи MapReduce.

3. Позиционирование CLI и Python API

  • Командный интерфейс удобен для того чтобы запускать обучение.
  • Python API удобно для того чтобы работать с обученной моделью: посмотреть, повизуализировать, дообучить с хитрой траекторией регуляризаторов.

Пакетирование

Пакет для Debian

В идеале BigARTM пользователь должен не собирать из исходников, а устанавливать вот таким образом: apt-get install bigartm

Что нужно при этом установить:

  • SO: /usr/lib/bigartm.so
  • CLI: /usr/bin/bigartm
  • Python-пакет: /usr/lib/python2.7/site-packages

Руководство по созданию deb-пакетов