bigartm.exe
¶Приложение bigartm.exe
(в Unix — просто bigartm
) — самостоятельный бинарик, работающий по следующему алгоритму:
Бинарник не должен зависеть от динамически линкуемых библиотек. При переносе бинарника на другую машину он должен запускаться без дополнительных файлов и переменных окружения. Самостоятельность бинарика значительно упростит его использование на кластере для распределенного обучения модели и вывода тематических профилей документов.
Для сборки самостоятельного бинарика gcc
нужно передавать флаг -static
. В cmake
нужно прописать что-то такое:
SET(CMAKE_EXE_LINKER_FLAGS "-static")
--rand-seed <seed>
: инициализация генератора случайных чисел, гарантируется что приложение отрабатывает с одинаковым результатом при одинаковом значении seed. По-умолчанию выбирается по таймеру (случайно).--response-file <file>
: текстовый файл содержащий ключи коммандной строки данного бинарного файла (bigartm.exe
). В отличии от коммандной строки, файл response-file
может состоять из нескольких строк. Это может быть полезно при ограничениях операционной системы на длину коммандной строки, или для удобства редактирования параметров запуска.Парсинг корпуса и создание батчей:
--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.
Использование существующего словаря:
--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)% токенов, встречающихся в наибольшем числе документов--dictionary-min/max-tf/tfq
Примеры:
--dictionary-min-tfq 20
--dictionary-max-df 30%
--dictionary-max-dfq 0.98
На этой фазе происходит создание модели: модель может быть загружена из файла, либо инициализирована по словарю.
--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 специальную трэш-тему.
Для обучения модели используется EM-алгоритм.
-p <N>
или --num-collection-passes <N>
: число проходов по корпусу, по умолчанию N=1На E-шаге оцениваются вектора $\theta$
--inner-iterations-count <N>
: число итераций внутреннего цикла (оптимизация векторов theta)На 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"
--threads <N>
: число потоков в которых производить обучение, по умолчанию N=1Пока не нужно реализовывать.
--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.
--read
/ --write
призвано работать с некоторой потоковой информацией в текстовом формате, которую можно читать из stdin и записывать в stdout посредством специального значения -
(минус)--use
/ --save
используется для работы со статичным объектом (словарь, набор батчей), который не изменяется в результате работы программы; статичный объект либо созается и потом сохраняется посредством save
, либо он загружается из файла посредством use
--load
/ --save
используется для объектов, которые меняются к концу выполнения программы; при помощи load
мы загружаем такой объект, затем мы его меняем, сохраняем новую версию посредством save
Информационный вывод должен производиться исключительно в stderr, поскольку в stdout может подаваться результат — тематические профили документов.
Пример вывода в 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:
На этих примерах нужно протестировать новое CLI, а в конечном счете – сделать подробное описание этих примеров в документации.
Предположим, что мы загрузили данные с 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
По корпусу статей Википедии построим многоязычную тематическую модель, которую затем сможем использовать для категоризации произвольных страниц.
Для обучения тематической модели был подготовлен мультиязычный корпу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.