Глава 9. Глубокое обучение для последовательностей и текста
377
let encoder = tf.layers.embedding({
inputDim: inputVocabSize,
outputDim: embeddingDims,
inputLength,
maskZero: true
}).apply(encoderInput);
Рис. 9.11.
Заглядываем глубже в основанную на механизме внимания модель «кодировщик —
декодировщик». Этот рисунок можно считать расширенной, с дополнительными подробностями,
версией архитектуры «кодировщик — декодировщик» с рис. 9.10
Все так же, как и в слоях вложений для задачи анализа тональностей IMDb,
только речь идет о вложениях символов, а не слов. А значит, сфера применения ме
тода вложений не ограничивается словами. На самом деле он достаточно гибок для
применения к любому конечному дискретному множеству, например к музыкаль
ным жанрам, статьям на новостном вебсайте, аэропортам страны и т. д. Настройка
maskZero:
true
слоя вложений предписывает расположенному далее по конвейеру
LSTMслою пропускать шаги, где все значения — нулевые, и таким образом эконо
мит вычислительные ресурсы на уже завершившихся последовательностях.
LSTM — тип RNN, который мы пока что подробно не рассматривали. Не станем
углубляться в нюансы его внутренней структуры. Достаточно сказать, что он подо
бен GRU (см. рис. 9.4) в том, что решает проблему исчезающего градиента за счет
упрощения переноса состояния через несколько временн
ы
х шагов. В посте в блоге
Криса Олаха (Chris Olah)
Understanding LSTM Networks
(«Разбираемся с LSTM
сетями»), ссылку на которое вы можете найти в конце главы, приведены прекрасный
378
Часть III • Продвинутые возможности глубокого обучения с TensorFlow.js
обзор и визуализация структуры и механизмов LSTM. LSTMслой нашего кодиров
щика применяется к векторам вложений символов:
encoder = tf.layers.lstm({
units: lstmUnits,
returnSequences: true
}).apply(encoder);
Благодаря настройке
returnSequences:
true
выходной сигнал LSTM может
представлять собой последовательность выходных векторов, а не только одного
выходного вектора (по умолчанию) — итогового выходного сигнала, как это было
в моделях предсказания температуры и анализа тональностей. Этот шаг необходим
для расположенного далее по конвейеру механизма внимания.
Слой
GetLastTimestepLayer
, следующий за слоем LSTM кодировщика, — не
стандартный:
const encoderLast = new GetLastTimestepLayer({
name: 'encoderLast'
}).apply(encoder);
Он просто производит срез тензора «время — последовательность» по измерению
времени (второму измерению) и выдает на выходе последний временной шаг. Благо
даря этому мы можем отправить итоговое состояние LSTMслоя кодировщика на
вход LSTMслоя декодировщика в качестве начального состояния. Эта связь — один
из способов получения декодировщиком информации о входной последователь
ности. Она показана на рис. 9.11 с помощью стрелки, соединяющей
h12
в зеленом
прямоугольнике кодировщика со слоем LSTM декодировщика в голубом прямо
угольнике кодировщика.
Относящаяся к декодировщику часть кода начинается со слоя вложений и LSTM
слоя, напоминающих топологию кодировщика:
let decoder = tf.layers.embedding({
inputDim: outputVocabSize,
outputDim: embeddingDims,
inputLength: outputLength,
maskZero: true
}).apply(decoderInput);
decoder = tf.layers.lstm({
units: lstmUnits,
returnSequences: true
}).apply(decoder, {initialState: [encoderLast, encoderLast]});
Обратите внимание, как в последней строке этого фрагмента кода итоговое
состоя ние кодировщика используется в качестве начального состояния декодиров
щика. Не удивляйтесь повторению символического тензора
encoderLast
в послед
ней строке кода: дело в том, что LSTMслой содержит два состояния, в отличие от
структуры с одним состоянием, как в simpleRNN и GRU.
Дополнительный, еще более многообещающий способ взглянуть на входные
последовательности для декодировщика — конечно, механизм внимания. Внима
Do'stlaringiz bilan baham: |