exponenta event banner

Определение функции модели декодера текста

В этом примере показано, как определить функцию модели текстового декодера.

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

  • Создание текста путем инициализации повторяющейся сети с закодированным вектором.

  • Трансляция последовательности в последовательность с использованием кодированного вектора в качестве вектора контекста.

  • Субтитры изображения с использованием кодированного вектора в качестве вектора контекста.

Загрузить данные

Загрузить закодированные данные из sonnetsEncoded.mat. Этот MAT-файл содержит кодировку слов, мини-пакет последовательностей dlXи соответствующие закодированные данные dlZ выходные данные кодировщика, используемого в примере Определение функции модели кодировщика текста (панель инструментов глубокого обучения).

s = load("sonnetsEncoded.mat");
enc = s.enc;
dlX = s.dlX;
dlZ = s.dlZ;

[latentDimension,miniBatchSize] = size(dlZ,1:2);

Инициализация параметров модели

Целью декодера является генерирование последовательностей, заданных некоторыми исходными входными данными и состоянием сети.

Инициализируйте параметры для следующей модели.

Декодер восстанавливает вход, используя LSTM, инициализированный выходом кодера. Для каждого временного шага декодер прогнозирует следующий временной шаг и использует выходные данные для следующих предсказаний временного шага. Кодер и декодер используют одно и то же встраивание.

В этой модели используются три операции:

  • Вложение отображает индексы слов в диапазоне 1, хотя vocabularySize к векторам размерности embeddingDimension, где vocabularySize - количество слов в кодирующей лексике и embeddingDimension - количество компонентов, полученных при встраивании.

  • Операция LSTM принимает в качестве входных данных вектор одного слова и выводит 1-by-numHiddenUnits вектор, где numHiddenUnits - количество скрытых блоков в операции LSTM. Начальное состояние сети LSTM (состояние на первом шаге времени) является кодированным вектором, поэтому количество скрытых единиц должно соответствовать скрытой размерности кодера.

  • Полностью подключенная операция умножает вход на весовую матрицу, добавляя смещение, и выводит векторы размера vocabularySize.

Укажите размеры параметров. Размеры встраивания должны соответствовать кодировщику.

embeddingDimension = 100;
vocabularySize = enc.NumWords;
numHiddenUnits = latentDimension;

Создайте структуру для параметров.

parameters = struct;

Инициализируйте веса встраивания с помощью гауссова initializeGaussian функция, которая присоединена к этому примеру в качестве вспомогательного файла. Укажите среднее значение 0 и стандартное отклонение 0,01. Дополнительные сведения см. в разделе Гауссовская инициализация (Deep Learning Toolbox).

mu = 0;
sigma = 0.01;
parameters.emb.Weights = initializeGaussian([embeddingDimension vocabularySize],mu,sigma);

Инициализируйте обучаемые параметры для операции декодера LSTM:

  • Инициализируйте входные веса с помощью инициализатора Glorot с помощью initializeGlorot функция, которая присоединена к этому примеру в качестве вспомогательного файла. Дополнительные сведения см. в разделе Инициализация Glorot (Deep Learning Toolbox).

  • Инициализируйте повторяющиеся веса ортогональным инициализатором с помощью initializeOrthogonal функция, которая присоединена к этому примеру в качестве вспомогательного файла. Дополнительные сведения см. в разделе Ортогональная инициализация (инструментарий глубокого обучения).

  • Инициализируйте смещение с помощью инициализатора литника unit forget с помощью initializeUnitForgetGate функция, которая присоединена к этому примеру в качестве вспомогательного файла. Дополнительные сведения см. в разделе Инициализация Gate Unit Forget (инструментарий глубокого обучения).

Размеры обучаемых параметров зависят от размера входных данных. Поскольку входы в операцию LSTM являются последовательностями векторов слов из операции внедрения, количество входных каналов равно embeddingDimension.

  • Матрица входного веса имеет размер 4*numHiddenUnitsоколо-inputSize, где inputSize - размерность входных данных.

  • Матрица повторяющегося веса имеет размер 4*numHiddenUnitsоколо-numHiddenUnits.

  • Вектор смещения имеет размер 4*numHiddenUnits-по-1.

sz = [4*numHiddenUnits embeddingDimension];
numOut = 4*numHiddenUnits;
numIn = embeddingDimension;

parameters.lstmDecoder.InputWeights = initializeGlorot(sz,numOut,numIn);
parameters.lstmDecoder.RecurrentWeights = initializeOrthogonal([4*numHiddenUnits numHiddenUnits]);
parameters.lstmDecoder.Bias = initializeUnitForgetGate(numHiddenUnits);

Инициализируйте обучаемые параметры для полностью подключенной операции кодера:

  • Инициализируйте веса с помощью инициализатора Glorot.

  • Инициализируйте смещение нулями с помощью initializeZeros функция, которая присоединена к этому примеру в качестве вспомогательного файла. Дополнительные сведения см. в разделе Инициализация нулей (Deep Learning Toolbox).

Размеры обучаемых параметров зависят от размера входных данных. Поскольку входы в полностью подключенную операцию являются выходами операции LSTM, количество входных каналов равно numHiddenUnits. Для создания полностью соединенных выходных векторов операций с размером latentDimension, укажите размер вывода latentDimension.

  • Матрица весов имеет размер outputSizeоколо-inputSize, где outputSize и inputSize соответствуют выходному и входному размерам соответственно.

  • Вектор смещения имеет размер outputSize-по-1.

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

inputSize = numHiddenUnits;
outputSize = vocabularySize;
parameters.fcDecoder.Weights = dlarray(randn(outputSize,inputSize,'single'));
parameters.fcDecoder.Bias = dlarray(zeros(outputSize,1,'single'));

Определение функции декодера модели

Создание функции modelDecoder, перечисленных в разделе «Функция модели декодера» примера, который вычисляет выходные данные модели декодера. modelDecoder функция принимает в качестве входных последовательностей индексов слов, параметров модели и длин последовательностей и возвращает соответствующий скрытый вектор признаков.

Использование функции модели в функции градиентов модели

При обучении модели глубокого обучения с помощью пользовательского цикла обучения необходимо вычислить градиенты потерь относительно обучаемых параметров. Этот расчет зависит от выхода прямого прохода функции модели.

Существует два общих подхода к генерации текстовых данных с помощью декодера:

  1. Замкнутый цикл (Closed loop) - для каждого временного шага делать прогнозы с использованием предыдущего прогноза в качестве входных данных.

  2. Разомкнутый цикл (Open loop) - для каждого временного шага делать прогнозы, используя входные данные из внешнего источника (например, цели обучения).

Генерация замкнутого контура

Формирование замкнутого цикла - это когда модель генерирует данные на один шаг за раз и использует предыдущее предсказание в качестве входных данных для следующего предсказания. В отличие от генерации с разомкнутым контуром, этот процесс не требует каких-либо входных данных между прогнозами и лучше всего подходит для сценариев без контроля. Например, модель перевода языка, которая генерирует выходной текст в одном переходе.

Использование замкнутого контура

Инициализация скрытого состояния сети LSTM с выходом кодера dlZ.

state = struct;
state.HiddenState = dlZ;
state.CellState = zeros(size(dlZ),'like',dlZ);

Для первого шага времени используйте массив стартовых маркеров в качестве входных данных для декодера. Для простоты извлеките массив стартовых маркеров из первого временного шага обучающих данных.

decoderInput = dlX(:,:,1);

Предварительно распределить выходной сигнал декодера по размеру numClassesоколо-miniBatchSizeоколо-sequenceLength с тем же типом данных, что и dlX, где sequenceLength - желаемая длина генерации, например, длина учебных целей. В этом примере укажите длину последовательности 16.

sequenceLength = 16;
dlY = zeros(vocabularySize,miniBatchSize,sequenceLength,'like',dlX);
dlY = dlarray(dlY,'CBT');

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

for t = 1:sequenceLength
    [dlY(:,:,t), state] = modelDecoder(parameters,decoderInput,state);
    
    [~,idx] = max(dlY(:,:,t));
    decoderInput = idx;
end

Выходные данные представляют собой vocabularySizeоколо-miniBatchSizeоколо-sequenceLength массив.

size(dlY)
ans = 1×3

        3595          32          16

Этот фрагмент кода показывает пример создания замкнутого цикла в функции градиентов модели.

function gradients = modelGradients(parameters,dlX,sequenceLengths)

    % Encode input.
    dlZ = modelEncoder(parameters,dlX,sequenceLengths);

    % Initialize LSTM state.
    state = struct;
    state.HiddenState = dlZ;
    state.CellState = zeros(size(dlZ),'like',dlZ);

    % Initialize decoder input.
    decoderInput = dlX(:,:,1);

    % Closed loop prediction.
    sequenceLength = size(dlX,3);
    dlY = zeros(numClasses,miniBatchSize,sequenceLength,'like',dlX);
    for t = 1:sequenceLength
        [dlY(:,:,t), state] = modelDecoder(parameters,decoderInput,state);
    
        [~,idx] = max(dlY(:,:,t));
        decoderInput = idx;
    end

    % Calculate loss.
    % ...

    % Calculate gradients.
    % ...

end

Генерация с разомкнутым контуром: форсирование учителя

При обучении с генерацией замкнутого цикла прогнозирование наиболее вероятного слова для каждого шага в последовательности может привести к неоптимальным результатам. Например, в рабочем процессе субтитрирования изображения, если декодер предсказывает, что первое слово подписи является «a», когда дано изображение слона, то вероятность предсказания «elephant» для следующего слова становится гораздо более маловероятной из-за крайне низкой вероятности появления фразы «a elephant» в английском тексте.

Чтобы помочь сети быстрее сойтись, можно использовать принудительное использование учителя: использовать целевые значения в качестве входных данных декодера вместо предыдущих прогнозов. Использование принудительного использования учителя помогает сети узнать характеристики из более поздних временных шагов последовательностей без необходимости ждать, пока сеть правильно сформирует более ранние временные шаги последовательностей.

Для выполнения форсирования учителя используйте modelEncoder непосредственно с целевой последовательностью в качестве входных данных.

Инициализация скрытого состояния сети LSTM с выходом кодера dlZ.

state = struct;
state.HiddenState = dlZ;
state.CellState = zeros(size(dlZ),'like',dlZ);

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

dlY = modelDecoder(parameters,dlX,state);

Выходные данные представляют собой vocabularySizeоколо-miniBatchSizeоколо-sequenceLength массив, где sequenceLength - длина входных последовательностей.

size(dlY)
ans = 1×3

        3595          32          14

Этот фрагмент кода показывает пример выполнения принудительного использования учителем функции градиентов модели.

function gradients = modelGradients(parameters,dlX,sequenceLengths)

    % Encode input.
    dlZ = modelEncoder(parameters,dlX,dlZ);

    % Initialize LSTM state.
    state = struct;
    state.HiddenState = dlZ;
    state.CellState = zeros(size(dlZ),'like',dlZ);

    % Teacher forcing.
    dlY = modelDecoder(parameters,dlX,state);

    % Calculate loss.
    % ...

    % Calculate gradients.
    % ...

end

Функция модели декодера

modelDecoder функция принимает в качестве входных параметров модели, последовательности индексов слов и состояние сети и возвращает декодированные последовательности.

Потому что lstm функция имеет статус (если в качестве входных данных задан временной ряд, функция распространяет и обновляет состояние между каждым временным шагом) и что embed и fullyconnect функции распределяются по времени по умолчанию (при вводе временного ряда функции работают на каждом временном шаге независимо), modelDecoder функция поддерживает как последовательные, так и одномоментные входы.

function [dlY,state] = modelDecoder(parameters,dlX,state)

% Embedding.
weights = parameters.emb.Weights;
dlX = embed(dlX,weights);

% LSTM.
inputWeights = parameters.lstmDecoder.InputWeights;
recurrentWeights = parameters.lstmDecoder.RecurrentWeights;
bias = parameters.lstmDecoder.Bias;

hiddenState = state.HiddenState;
cellState = state.CellState;

[dlY,hiddenState,cellState] = lstm(dlX,hiddenState,cellState, ...
    inputWeights,recurrentWeights,bias);

state.HiddenState = hiddenState;
state.CellState = cellState;

% Fully connect. 
weights = parameters.fcDecoder.Weights;
bias = parameters.fcDecoder.Bias;
dlY = fullyconnect(dlY,weights,bias);

end

См. также

| | |

Связанные темы