[Python, Машинное обучение, Искусственный интеллект, Natural Language Processing] Краткость — сестра таланта: Как сделать Transformer/Summarizer на Trax
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
В новой курсеровской специализации «NLP» от deeplearning.ai в качестве библиотеки глубокого обучения используется Trax. В последнем курсе подробно разбирается механизм внимания и его использование в архитектуре Transformer, в том числе в таких «новеллах» как BERT и T5. Имея некоторое количество свободного времени специализацию можно пройти за несколько недель, что я собственно и сделал, соблазнившись возможностью построить собственный трансформер. Очень хотелось сделать модель, которая может работать с текстами на русском языке.Для эксперимента я выбрал саммаризатор, эта конструкция получает на вход статью и генерирует короткий текст с описанием сути. Summary может быть и просто заголовком. Попробую рассказать обо всём в деталях.Trax — полнофункциональная библиотека для глубокого обучения с фокусом на понятный код и быстрые вычисления. По синтаксису она в общем похожа на Keras, а модель на Trax можно сконвертировать в модель на Keras. Библиотека активно развивается и поддерживается командой Google Brain. Trax использует Tensorflow и является одной из библиотек в его экосистеме. Она работает на CPU, GPU и TPU, при этом используется одна и та же версия. Не буду говорить неправду, TPU я пока не попробовал.Transformer - архитектура глубоких нейронных сетей, представленная в 2017 году исследователями из Google Brain. Transformer предназначен для работы с последовательностями, в том числе текстовыми, но в отличие от архитектур на рекуррентных сетях, не требует обрабатывать последовательность по порядку. Сильно упрощая можно сказать, что если из архитектуры Seq2Seq на LSTM с механизмом внимания оставить только механизм внимания и добавить нейронную сеть прямого распространения (Feed Forward), то он и получится. Подробнее про трансформеры с картинками здесьна английском, здесьна русском.ДанныеВ качестве набора данных для эксперимента я решил использовать корпус новостей Lenta.Ru, свежую версию которого нашел на Kaggle. Корпус содержит более 800 тыс. новостных статей в формате (url, title, text, topic, tags, date). Если статья — это text, то summary для моей модели — title. Это законченное предложение, содержащее основную мысль новостной статьи. Конечно это не полное summary как, например, в англоязычном корпусе cnn_dailymail, но я подумал, что так даже интереснее.Процесс подготовки данных представлен на схеме:
Для начала я отфильтровал аномально короткие и аномально длинные статьи. Затем выделил из набора тексты и заголовки, преобразовал всё к нижнему регистру, сохранил в виде списка кортежей и в виде полного текста. Список кортежей разбил на две части — для обучения (train) и оценки (eval). Далее написал «бесконечный» генератор, который дойдя до конца списка, перемешивает его и начинает сначала. Неприятно же, когда генератор «заканчивается» где-то в середине эпохи. Это важно прежде всего для оценочного набора, я взял всего 5% от общего количества статей, примерно 36 тысяч пар.На основе полного текста я обучил токенайзер, а в качестве токенов использовал части слов. Проблема токенизации или сегментации на целые слова заключается в том, что некоторые слова в тексте встречаются редко, возможно единственный раз, и таких слов очень много, а размер словаря конечен и хочется его сделать не очень большим, чтобы поместиться в память виртуальной машины. Приходится заменять некоторые слова именованными шаблонами, часто использовать заполнитель для слов, которых в словаре нет и даже использовать специальные техники вроде pointer-generator. А разбиение на подслова позволяет сделать токенайзер с небольшим по объему словарем, который еще и работает практически без потерь информации.Для такой сегментации существует несколько сравнительно честных способов, познакомиться с ними можно например здесь. Я выбрал модель на основе Byte Pair Encoding (BPE), реализованную в библиотеке sentencepiece. BPE – способ кодирования текста со сжатием. Для кодирования часто повторяющейся последовательности символов используется символ, которого нет в исходной последовательности. Всё тоже самое и при сегментации, только последовательность часто встречающихся символов становится новым токеном, и так пока не будет достигнут заданный размер словаря. Мой словарь содержит 16000 токенов.Пример сегментированного текста['▁ученые', '▁придума', 'ли', '▁новый', '▁способ', '▁взаимо', 'действия', '▁с', '▁граф', 'ен', 'ом', ',', '▁который', '▁позволяет', '▁избавиться', '▁от', '▁"', 'сли', 'па', 'ющихся', '"', '▁ли', 'стов', '.', '▁статья', '▁ученых', '▁появилась', '▁в', '▁журнале', '▁ac', 's', '▁n', 'an', 'o', ',', '▁а', '▁ее', '▁крат', 'кое', '▁из', 'ложение', '▁приво', 'дится', '▁на', '▁сайте', '▁северо', '-', 'запа', 'дного', '▁университета', ',', '▁сотрудники', '▁которого', '▁принимали', '▁участие', '▁в', '▁работе', '.']Видно, что разбиваются даже слова на латинице, а знаки препинания кодируются как отдельные токены, просто мечта, а не токенайзер. Знак нижнего подчеркивания обозначает начало слова. Обучается модель благодаря вот такой нехитрой конструкции:
import sentencepiece as spm
spm.SentencePieceTrainer.train('--input=full_text.txt \
--pad_id=0 --bos_id=-1 --eos_id=1 --unk_id=2 \
--model_prefix=bpe --vocab_size=16000 --model_type=bpe')
Результат — два файла: словарь для контроля и модель, которую можно загрузить в обертку токенайзера. Для выбранной мной модели статья и заголовок должны быть преобразованы в последовательности целых чисел и объединены с разделением служебными токенами EOS :1 и PAD :0 (конец последовательности и заполнитель).После преобразования последовательность помещается в корзину фиксированной длинны. У меня их три: 256, 512 и 1024. Последовательности в корзине автоматически дополняются заполнителями до фиксированной длинны и собираются в пакеты (batches). Количество последовательностей в пакете зависит от корзины, соответственно 16, 8, 4. Рефлексия по поводу последовательностей длиннее 512 токеновТрудно представить, что 2000 символов могут дать что-то длиннее 512 токенов, но на всякий случай сделал три корзины. А длиннее 1024 не может быть в принципе из-за фильтра в пайплайне.Сегментация и конкатенация выполняются в пайплайне trax:
input_pipeline = trax.data.Serial(
trax.data.Tokenize(vocab_type='sentencepiece',
vocab_dir='/content/drive/MyDrive/',
vocab_file='bpe.model'),
preprocessing,
trax.data.FilterByLength(1024)
)
train_stream = input_pipeline(train_data_stream())
eval_stream = input_pipeline(eval_data_stream())
preprocessing — это моя функция конкатенации, генератор. Сортировка по корзинам и формирование пакетов осуществляется благодаря следующей конструкции:
boundaries = [256, 512]
batch_sizes = [16, 8, 4]
train_batch_stream = trax.data.BucketByLength(
boundaries, batch_sizes)(train_stream)
eval_batch_stream = trax.data.BucketByLength(
boundaries, batch_sizes)(eval_stream)
МодельTransformer, работающий с двумя последовательностями, например при машинном переводе, включает два блока — энкодер и декодер, но для саммаризации достаточно только декодера. Такая архитектура в общем реализует языковую модель, где вероятность следующего слова определяется по предыдущим. Еще её называют Decoder-only Transformer и она похожа на GPT (Generative Pre-trained Transformer). Разобраться в деталях архитектур можно здесь. Для моего случая в библиотеке Trax есть отдельный класс моделей trax.models.transformer.TransformerLM(...), то есть создать модель можно одной строчкой кода. В упомянутой специализации модель строится from scratch. Я же выбрал нечто среднее — построил модель из готовых блоков, используя примеры кода.Схема модели показана на рисунке:
PositionlEncoder() – это блок, обеспечивающий построение векторного пространства и кодирование позиции токена во входной последовательности. Код:
from trax import layers as tl
def PositionalEncoder(vocab_size, d_model, dropout, max_len, mode):
return [
tl.Embedding(vocab_size, d_model),
tl.Dropout(rate=dropout, mode=mode),
tl.PositionalEncoding(max_len=max_len, mode=mode)]
Аргументы:
vocab_size (int): размер словаря
d_model (int): количество признаков векторного пространства
dropout (float): степень использования dropout
max_len (int): максимальная длина последовательности для позиционного кодирования
mode (str): 'train' или 'eval' — для dropout и поз. кодирования.FeedForward формирует блок прямого распространения с выбранной функций активации:
def FeedForward(d_model, d_ff, dropout, mode, ff_activation):
return [
tl.LayerNorm(),
tl.Dense(d_ff),
ff_activation(),
tl.Dropout(rate=dropout, mode=mode),
tl.Dense(d_model),
tl.Dropout(rate=dropout, mode=mode)
]
Аргументы:
d_model (int): количество признаков векторного пространства
d_ff (int): «ширина» блока или количество юнитов в выходном плотном слое
dropout (float): степень использования dropout
mode (str): 'train' или 'eval' — чтобы не использовать dropout при оценке качества модели
ff_activation (function): функция активации, в моей модели — ReLUDecoderBlock(...) - это два блока с Residual-соединием. Вряд ли перевод «остаточный» точно отражает смысл, но это обходное соединение для борьбы с исчезающим градиентом в глубоких архитектурах.Если считать от входа к выходу, то первый блок содержит механизм внимания, я использовал готовый уровень из библиотеки. Второй — описанный выше блок прямого распространения. Механизм внимания здесь необычный, он «смотрит» на ту же последовательность, для которой генерируется следующий токен, а чтобы он «не заглядывал в будущее» при расчете весов используется специальная маска.
def DecoderBlock(d_model, d_ff, n_heads, dropout, mode, ff_activation):
return [
tl.Residual(
tl.LayerNorm(),
tl.CausalAttention(d_model, n_heads=n_heads, dropout=dropout, mode=mode)
),
tl.Residual(
FeedForward(d_model, d_ff, dropout, mode, ff_activation)
),
]
Из неизвестных аргументов только n_heads (int) — количество головок внимания, надеюсь это удачный термин для attention heads. Каждая головка учится обращать внимание на что-то своё.Собираю все части вместе и задаю параметры модели. У меня шесть декодеров, в каждом из которых по восемь головок внимания. Общее количество обучаемых параметров 37 412 480. Из неизвестных мне уровней пожалуй только ShiftRight. Он сдвигает входную последовательность вправо, заполняя освободившееся место нулями, по умолчанию — на одну позицию. Это нужно для teacher forcing, специальной техники, упрощающей обучение языковой модели, особенно на ранних этапах. Идея здесь в следующем: когда модель учится прогнозировать следующее слово по предыдущим, вместо прогноза модели, возможно неверного, в качестве этих предыдущих слов используются правильные ответы (ground truth). Коротко это можно описать формулой:
y(t) = x(t+1). Здесьподробное объяснение для RNN.
def SumTransformer(vocab_size=vocab_size,
d_model=512,
d_ff=2048,
n_layers=6,
n_heads=8,
dropout=0.1,
max_len=4096,
mode='train',
ff_activation=tl.Relu):
decoder_blocks = [DecoderBlock(d_model, d_ff, n_heads, dropout, mode,
ff_activation) for _ in range(n_layers)]
return tl.Serial(
tl.ShiftRight(mode=mode),
PositionalEncoder(vocab_size, d_model, dropout, max_len, mode),
decoder_blocks,
tl.LayerNorm(),
tl.Dense(vocab_size),
tl.LogSoftmax()
)
ОбучениеПо моему опыту Google Colab не очень «любит» длительное использование своих GPU и не всегда их выделяет, особенно во второй половине дня. Поэтому я обучал модель отдельными эпохами по 20 000 шагов, где шаг соответствует одному пакету (batch). Получалось сделать 1-2 эпохи в день. 100 шагов это примерно минута, а эпоха — около трех часов.Первая эпоха показала, что модель учится только несколько тысяч шагов, дальше никаких улучшений не происходит. Оказалось, что я выбрал слишком большой шаг обучения (learning_rate). Для моей модели он должен быть 0.0002 первые несколько эпох, затем 0.0001 и 0.00005 в конце. Если бы я учил модель за один проход, то можно было бы использовать lr_schedules из trax.supervised. Там есть разные удобные варианты и с прогревом и с постепенным уменьшением шага.В качестве метрик я использовал CrossEntropyLoss и Accuracy. За 12 эпох на оценочном наборе loss упал с 10 до 2, а доля правильных ответов возросла почти до 60%. Этого оказалось достаточно, чтобы генерировать почти приемлемые заголовки.Цикл обучения выглядит следующим образом:
from trax.supervised import training
def training_loop(SumTransformer, train_gen, eval_gen, output_dir = "~/model"):
output_dir = os.path.expanduser(output_dir)
train_task = training.TrainTask(
labeled_data=train_gen,
loss_layer=tl.CrossEntropyLoss(),
optimizer=trax.optimizers.Adam(0.0001),
n_steps_per_checkpoint=100
)
eval_task = training.EvalTask(
labeled_data=eval_gen,
metrics=[tl.CrossEntropyLoss(), tl.Accuracy()]
)
loop = training.Loop(SumTransformer(),
train_task,
eval_tasks=[eval_task],
output_dir=output_dir)
return loop
Аргументы:
SumTransformer (trax.layers.combinators.Serial): модель
train_gen (generator): поток данных для обучения
eval_gen (generator): поток данных для оценки качества.
output_dir (str): папка для файла модели, откуда её можно скопировать на Google Drive перед выключением виртуальной машины. Дальше всё просто:
loop = training_loop(SumTransformer, train_batch_stream, eval_batch_stream)
loop.run(20000)
и три часа ожидания...Оценка результатов Для оценки результатов я использовал «жадный» декодер на базе argmax, который определяет индекс наиболее вероятного токена в словаре по положению максимального значения в выходном тензоре. Далее токен добавляется к входной последовательности и операция повторяется пока не появится символ EOS или не будет достигнута заданная максимальная длина предложения.Примеры из оценочного набора:
(Исходный текст сокращен)Тест #1: швейцарская часовая компания audemars piguet представила новую модель из коллекции royal oak. как сообщает luxurylaunches, речь идет о часах с вечным календарем. официальная презентация пройдет в рамках международного салона высокого часового искусства sihh, который проходит в женеве...
Образец: дом audemars piguet оснастил часы вечным календарем
Модель: audemars piguet представила новую модель из коллекции royal oak
Тест #2: на ежегодном фестивале в городе грэхэмстаун, юар, фокусник случайно выстрелил в голову своему напарнику во время представления. об этом сообщает местная газета the daily dispatch. инцидент произошел 30 июня. брендон пил (brendon peel) и его ассистент ли лау (li lau) выполняли магический трюк перед многочисленной аудиторией, когда пил по неосторожности пустил в затылок напарника стрелу...
Образец: фокусник случайно подстрелил ассистента на глазах у зрителей
Модель: на фестивале в грэлково напали с ножом
(И не в грэлково, и не напали, и не с ножом, но спасибо, что это было холодное оружие, а не пистолет)Еще примерыТест #3: международный валютный фонд (мвф) в среду, 15 мая, утвердил выделение кипру кредита в размере 1,33 миллиарда долларов (миллиард евро). как сообщает agence france-presse, в качестве первого транша кипрское правительство получит 110,7 миллиона долларов. утвержденный 15 мая кредит является частью плана помощи...
Образец: мвф выделил кипру миллиард евро
Модель: мвф утвердил кредит на кипрский кредитТест #4: автопортрет энди уорхола, выполненный в 1965 году и ранее не выставлявшийся, продадут с аукциона, пишет the new york times. автопортрет более 40 лет хранила бывшая секретарша уорхола кэти нейсо (cathy naso), которая получила картину от художника в оплату ее работы. нейсо работала в студии уорхола...
Образец: неизвестный автопортрет энди уорхола выставят на торги
Модель: энди уорхола продадут с аукционаТест #5: sony решила выпустить файтинг, который станет "ответом на игру super smash bros" от nintendo, пишет vg24/7 со ссылкой на paul gale network и neogaf. в новом проекте, в настоящее время известном под названием title fight, герои из нескольких игр издательства сразятся между собой...
Образец: sony приписали разработку нового файтинга
Модель: sony выпустит файтинг от nintendoИнтересно, что на ранних этапах обучения вместо «белиберды» модель генерирует почти осмысленные фейки. Чтобы посмотреть как это происходит, я сделал скринкаст нескольких интересных на мой взгляд вариантов:Извините, данный ресурс не поддреживается. :( Ссылки
- Мой репозитарий с кодом эксперимента)
- Репозитарий trax
- Математика механизма внимания в знаменитой статье «Attention Is All You Need». Кстати один из авторов статьи, Lukasz Kaiser, штатный исследователь Google Brain, является также автором и инструктором специализации.
ПримечанияЯ использовал trax 1.3.7, он инсталлируется через pip, но не работает под Windows. На форумах пишут что можно под WSL. А еще там нет beam_search, который есть в документации и который я очень хотел попробовать.Параметры для модели взяты из заведомо работающей модели для cnn_dailymail. С учетом более коротких последовательностей, предполагаю, что размер плотного слоя в блоке FeedForward и максимальную длину последовательности можно уменьшить. Вопрос эксперимента.В упомянутой модели TransformerLM выход не нормализован (нет уровня softmax).
===========
Источник:
habr.com
===========
Похожие новости:
- [Python, Программирование] Еще один фреймворк…
- [Информационная безопасность, Сетевые технологии, Исследования и прогнозы в IT, Искусственный интеллект, Интернет вещей] Top 7 Technology Trends to Look out for in 2021
- Языку Python исполнилось 30 лет
- [Искусственный интеллект] В МТИ придумали, как с помощью машинного обучения уменьшить отходы листового металла
- [Тестирование IT-систем, Python, Карьера в IT-индустрии, VueJS] Дайджест митапов и практикумов: Frontend, Web, QA и не только
- [Промышленное программирование, Бизнес-модели, Искусственный интеллект, IT-компании] Huawei начнет внедрять ИИ-технологии на свинофермах и в шахтах
- [Информационная безопасность, Криптография, Python, Графические оболочки, C] Поддержка токенов PKCS#11 с ГОСТ-криптографией в Python. Часть I
- [Искусственный интеллект] Вредоносный ИИ: реальность угрозы
- [Open source, Алгоритмы, Машинное обучение, Копирайт] Коммерческую систему компьютерных шахмат Fat Fritz 2 уличили в плагиате движка с открытым кодом
- [Машинное обучение, Научно-популярное, Биотехнологии] Как с помощью машинного обучения выращивают каннабис и помидорки
Теги для поиска: #_python, #_mashinnoe_obuchenie (Машинное обучение), #_iskusstvennyj_intellekt (Искусственный интеллект), #_natural_language_processing, #_nlp, #_transformer, #_trax, #_summarization, #_selfattention, #_transformer (трансформер), #_glubokoe_obuchenie (глубокое обучение), #_deep_learning, #_tensorflow, #_python, #_mashinnoe_obuchenie (
Машинное обучение
), #_iskusstvennyj_intellekt (
Искусственный интеллект
), #_natural_language_processing
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 23:06
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
В новой курсеровской специализации «NLP» от deeplearning.ai в качестве библиотеки глубокого обучения используется Trax. В последнем курсе подробно разбирается механизм внимания и его использование в архитектуре Transformer, в том числе в таких «новеллах» как BERT и T5. Имея некоторое количество свободного времени специализацию можно пройти за несколько недель, что я собственно и сделал, соблазнившись возможностью построить собственный трансформер. Очень хотелось сделать модель, которая может работать с текстами на русском языке.Для эксперимента я выбрал саммаризатор, эта конструкция получает на вход статью и генерирует короткий текст с описанием сути. Summary может быть и просто заголовком. Попробую рассказать обо всём в деталях.Trax — полнофункциональная библиотека для глубокого обучения с фокусом на понятный код и быстрые вычисления. По синтаксису она в общем похожа на Keras, а модель на Trax можно сконвертировать в модель на Keras. Библиотека активно развивается и поддерживается командой Google Brain. Trax использует Tensorflow и является одной из библиотек в его экосистеме. Она работает на CPU, GPU и TPU, при этом используется одна и та же версия. Не буду говорить неправду, TPU я пока не попробовал.Transformer - архитектура глубоких нейронных сетей, представленная в 2017 году исследователями из Google Brain. Transformer предназначен для работы с последовательностями, в том числе текстовыми, но в отличие от архитектур на рекуррентных сетях, не требует обрабатывать последовательность по порядку. Сильно упрощая можно сказать, что если из архитектуры Seq2Seq на LSTM с механизмом внимания оставить только механизм внимания и добавить нейронную сеть прямого распространения (Feed Forward), то он и получится. Подробнее про трансформеры с картинками здесьна английском, здесьна русском.ДанныеВ качестве набора данных для эксперимента я решил использовать корпус новостей Lenta.Ru, свежую версию которого нашел на Kaggle. Корпус содержит более 800 тыс. новостных статей в формате (url, title, text, topic, tags, date). Если статья — это text, то summary для моей модели — title. Это законченное предложение, содержащее основную мысль новостной статьи. Конечно это не полное summary как, например, в англоязычном корпусе cnn_dailymail, но я подумал, что так даже интереснее.Процесс подготовки данных представлен на схеме: Для начала я отфильтровал аномально короткие и аномально длинные статьи. Затем выделил из набора тексты и заголовки, преобразовал всё к нижнему регистру, сохранил в виде списка кортежей и в виде полного текста. Список кортежей разбил на две части — для обучения (train) и оценки (eval). Далее написал «бесконечный» генератор, который дойдя до конца списка, перемешивает его и начинает сначала. Неприятно же, когда генератор «заканчивается» где-то в середине эпохи. Это важно прежде всего для оценочного набора, я взял всего 5% от общего количества статей, примерно 36 тысяч пар.На основе полного текста я обучил токенайзер, а в качестве токенов использовал части слов. Проблема токенизации или сегментации на целые слова заключается в том, что некоторые слова в тексте встречаются редко, возможно единственный раз, и таких слов очень много, а размер словаря конечен и хочется его сделать не очень большим, чтобы поместиться в память виртуальной машины. Приходится заменять некоторые слова именованными шаблонами, часто использовать заполнитель для слов, которых в словаре нет и даже использовать специальные техники вроде pointer-generator. А разбиение на подслова позволяет сделать токенайзер с небольшим по объему словарем, который еще и работает практически без потерь информации.Для такой сегментации существует несколько сравнительно честных способов, познакомиться с ними можно например здесь. Я выбрал модель на основе Byte Pair Encoding (BPE), реализованную в библиотеке sentencepiece. BPE – способ кодирования текста со сжатием. Для кодирования часто повторяющейся последовательности символов используется символ, которого нет в исходной последовательности. Всё тоже самое и при сегментации, только последовательность часто встречающихся символов становится новым токеном, и так пока не будет достигнут заданный размер словаря. Мой словарь содержит 16000 токенов.Пример сегментированного текста['▁ученые', '▁придума', 'ли', '▁новый', '▁способ', '▁взаимо', 'действия', '▁с', '▁граф', 'ен', 'ом', ',', '▁который', '▁позволяет', '▁избавиться', '▁от', '▁"', 'сли', 'па', 'ющихся', '"', '▁ли', 'стов', '.', '▁статья', '▁ученых', '▁появилась', '▁в', '▁журнале', '▁ac', 's', '▁n', 'an', 'o', ',', '▁а', '▁ее', '▁крат', 'кое', '▁из', 'ложение', '▁приво', 'дится', '▁на', '▁сайте', '▁северо', '-', 'запа', 'дного', '▁университета', ',', '▁сотрудники', '▁которого', '▁принимали', '▁участие', '▁в', '▁работе', '.']Видно, что разбиваются даже слова на латинице, а знаки препинания кодируются как отдельные токены, просто мечта, а не токенайзер. Знак нижнего подчеркивания обозначает начало слова. Обучается модель благодаря вот такой нехитрой конструкции: import sentencepiece as spm
spm.SentencePieceTrainer.train('--input=full_text.txt \ --pad_id=0 --bos_id=-1 --eos_id=1 --unk_id=2 \ --model_prefix=bpe --vocab_size=16000 --model_type=bpe') input_pipeline = trax.data.Serial(
trax.data.Tokenize(vocab_type='sentencepiece', vocab_dir='/content/drive/MyDrive/', vocab_file='bpe.model'), preprocessing, trax.data.FilterByLength(1024) ) train_stream = input_pipeline(train_data_stream()) eval_stream = input_pipeline(eval_data_stream()) boundaries = [256, 512]
batch_sizes = [16, 8, 4] train_batch_stream = trax.data.BucketByLength( boundaries, batch_sizes)(train_stream) eval_batch_stream = trax.data.BucketByLength( boundaries, batch_sizes)(eval_stream) PositionlEncoder() – это блок, обеспечивающий построение векторного пространства и кодирование позиции токена во входной последовательности. Код: from trax import layers as tl
def PositionalEncoder(vocab_size, d_model, dropout, max_len, mode): return [ tl.Embedding(vocab_size, d_model), tl.Dropout(rate=dropout, mode=mode), tl.PositionalEncoding(max_len=max_len, mode=mode)] vocab_size (int): размер словаря d_model (int): количество признаков векторного пространства dropout (float): степень использования dropout max_len (int): максимальная длина последовательности для позиционного кодирования mode (str): 'train' или 'eval' — для dropout и поз. кодирования.FeedForward формирует блок прямого распространения с выбранной функций активации: def FeedForward(d_model, d_ff, dropout, mode, ff_activation):
return [ tl.LayerNorm(), tl.Dense(d_ff), ff_activation(), tl.Dropout(rate=dropout, mode=mode), tl.Dense(d_model), tl.Dropout(rate=dropout, mode=mode) ] d_model (int): количество признаков векторного пространства d_ff (int): «ширина» блока или количество юнитов в выходном плотном слое dropout (float): степень использования dropout mode (str): 'train' или 'eval' — чтобы не использовать dropout при оценке качества модели ff_activation (function): функция активации, в моей модели — ReLUDecoderBlock(...) - это два блока с Residual-соединием. Вряд ли перевод «остаточный» точно отражает смысл, но это обходное соединение для борьбы с исчезающим градиентом в глубоких архитектурах.Если считать от входа к выходу, то первый блок содержит механизм внимания, я использовал готовый уровень из библиотеки. Второй — описанный выше блок прямого распространения. Механизм внимания здесь необычный, он «смотрит» на ту же последовательность, для которой генерируется следующий токен, а чтобы он «не заглядывал в будущее» при расчете весов используется специальная маска. def DecoderBlock(d_model, d_ff, n_heads, dropout, mode, ff_activation):
return [ tl.Residual( tl.LayerNorm(), tl.CausalAttention(d_model, n_heads=n_heads, dropout=dropout, mode=mode) ), tl.Residual( FeedForward(d_model, d_ff, dropout, mode, ff_activation) ), ] y(t) = x(t+1). Здесьподробное объяснение для RNN. def SumTransformer(vocab_size=vocab_size,
d_model=512, d_ff=2048, n_layers=6, n_heads=8, dropout=0.1, max_len=4096, mode='train', ff_activation=tl.Relu): decoder_blocks = [DecoderBlock(d_model, d_ff, n_heads, dropout, mode, ff_activation) for _ in range(n_layers)] return tl.Serial( tl.ShiftRight(mode=mode), PositionalEncoder(vocab_size, d_model, dropout, max_len, mode), decoder_blocks, tl.LayerNorm(), tl.Dense(vocab_size), tl.LogSoftmax() ) from trax.supervised import training
def training_loop(SumTransformer, train_gen, eval_gen, output_dir = "~/model"): output_dir = os.path.expanduser(output_dir) train_task = training.TrainTask( labeled_data=train_gen, loss_layer=tl.CrossEntropyLoss(), optimizer=trax.optimizers.Adam(0.0001), n_steps_per_checkpoint=100 ) eval_task = training.EvalTask( labeled_data=eval_gen, metrics=[tl.CrossEntropyLoss(), tl.Accuracy()] ) loop = training.Loop(SumTransformer(), train_task, eval_tasks=[eval_task], output_dir=output_dir) return loop SumTransformer (trax.layers.combinators.Serial): модель train_gen (generator): поток данных для обучения eval_gen (generator): поток данных для оценки качества. output_dir (str): папка для файла модели, откуда её можно скопировать на Google Drive перед выключением виртуальной машины. Дальше всё просто: loop = training_loop(SumTransformer, train_batch_stream, eval_batch_stream)
loop.run(20000) (Исходный текст сокращен)Тест #1: швейцарская часовая компания audemars piguet представила новую модель из коллекции royal oak. как сообщает luxurylaunches, речь идет о часах с вечным календарем. официальная презентация пройдет в рамках международного салона высокого часового искусства sihh, который проходит в женеве... Образец: дом audemars piguet оснастил часы вечным календарем Модель: audemars piguet представила новую модель из коллекции royal oak Тест #2: на ежегодном фестивале в городе грэхэмстаун, юар, фокусник случайно выстрелил в голову своему напарнику во время представления. об этом сообщает местная газета the daily dispatch. инцидент произошел 30 июня. брендон пил (brendon peel) и его ассистент ли лау (li lau) выполняли магический трюк перед многочисленной аудиторией, когда пил по неосторожности пустил в затылок напарника стрелу... Образец: фокусник случайно подстрелил ассистента на глазах у зрителей Модель: на фестивале в грэлково напали с ножом (И не в грэлково, и не напали, и не с ножом, но спасибо, что это было холодное оружие, а не пистолет)Еще примерыТест #3: международный валютный фонд (мвф) в среду, 15 мая, утвердил выделение кипру кредита в размере 1,33 миллиарда долларов (миллиард евро). как сообщает agence france-presse, в качестве первого транша кипрское правительство получит 110,7 миллиона долларов. утвержденный 15 мая кредит является частью плана помощи... Образец: мвф выделил кипру миллиард евро Модель: мвф утвердил кредит на кипрский кредитТест #4: автопортрет энди уорхола, выполненный в 1965 году и ранее не выставлявшийся, продадут с аукциона, пишет the new york times. автопортрет более 40 лет хранила бывшая секретарша уорхола кэти нейсо (cathy naso), которая получила картину от художника в оплату ее работы. нейсо работала в студии уорхола... Образец: неизвестный автопортрет энди уорхола выставят на торги Модель: энди уорхола продадут с аукционаТест #5: sony решила выпустить файтинг, который станет "ответом на игру super smash bros" от nintendo, пишет vg24/7 со ссылкой на paul gale network и neogaf. в новом проекте, в настоящее время известном под названием title fight, герои из нескольких игр издательства сразятся между собой... Образец: sony приписали разработку нового файтинга Модель: sony выпустит файтинг от nintendoИнтересно, что на ранних этапах обучения вместо «белиберды» модель генерирует почти осмысленные фейки. Чтобы посмотреть как это происходит, я сделал скринкаст нескольких интересных на мой взгляд вариантов:Извините, данный ресурс не поддреживается. :( Ссылки
=========== Источник: habr.com =========== Похожие новости:
Машинное обучение ), #_iskusstvennyj_intellekt ( Искусственный интеллект ), #_natural_language_processing |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 23:06
Часовой пояс: UTC + 5