Задайте функцию модели текстового энкодера

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

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

  • Классификация путем применения операции softmax к кодированным данным и использования потери перекрестной энтропии.

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

Загрузка данных

Файл sonnets.txt содержит все сонеты Шекспира в одном текстовом файле.

Считайте данные Sonnets Шекспира из файла "sonnets.txt".

filename = "sonnets.txt";
textData = fileread(filename);

Сонеты изрезаны двумя пробелами символов. Удалите углубления с помощью replace и разделите текст на отдельные линии, используя split функция. Удалите заголовок из первых девяти элементов и кратких заголовков сонетов.

textData = replace(textData,"  ","");
textData = split(textData,newline);
textData(1:9) = [];
textData(strlength(textData)<5) = [];

Подготовка данных

Создайте функцию, которая токенизирует и предварительно обрабатывает текстовые данные. Функция preprocessText, перечисленный в конце примера, выполняет следующие шаги:

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

  2. Токенизация текста с помощью tokenizedDocument.

Предварительно обработайте текстовые данные и задайте начальные и стоповые лексемы "<start>" и "<stop>", соответственно.

startToken = "<start>";
stopToken = "<stop>";
documents = preprocessText(textData,startToken,stopToken);

Создайте объект кодирования слов из токенизированных документов.

enc = wordEncoding(documents);

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

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

paddingToken = "<pad>";
newVocabulary = [enc.Vocabulary paddingToken];
enc = wordEncoding(newVocabulary);
paddingIdx = word2ind(enc,paddingToken)
paddingIdx = 3595

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

Цель энкодера состоит в том, чтобы сопоставить последовательности индексов слов с векторами в некотором скрытом пространстве.

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

Эта модель использует три операции:

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

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

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

Задайте размерности параметров.

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

Создайте struct для параметров.

parameters = struct;

Инициализируйте веса встраивания, используя Гауссов метод initializeGaussian функция, которая присоединена к этому примеру как вспомогательный файл. Задайте среднее значение 0 и стандартное отклонение 0,01. Для получения дополнительной информации смотрите Гауссову инициализацию.

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

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

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

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

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

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

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

  • Повторяющаяся матрица веса имеет размер 4*numHiddenUnits-by- numHiddenUnits.

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

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

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

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

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

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

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

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

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

sz = [latentDimension numHiddenUnits];
numOut = latentDimension;
numIn = numHiddenUnits;

parameters.fcEncoder.Weights = initializeGlorot(sz,numOut,numIn);
parameters.fcEncoder.Bias = initializeZeros([latentDimension 1]);

Задайте функцию энкодера модели

Создайте функцию modelEncoder, перечисленный в разделе Encoder Model Function примера, который вычисляет выход модели энкодера. The modelEncoder function, принимает в качестве входных последовательностей индексы слов, параметры модели и длины последовательности и возвращает соответствующий латентный вектор функции.

Подготовка мини-пакета данных

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

Подготовим пример мини-пакета данных. Выберите мини-пакет из 32 документов из documents. Это представляет мини-пакет данных, используемых в итерации пользовательского цикла обучения.

miniBatchSize = 32;
idx = 1:miniBatchSize;
documentsBatch = documents(idx);

Преобразуйте документы в последовательности с помощью doc2sequence и задайте для правого дополнения последовательностей индексом слова, соответствующим лексеме заполнения.

X = doc2sequence(enc,documentsBatch, ...
    'PaddingDirection','right', ...
    'PaddingValue',paddingIdx);

Выходные выходы doc2sequence функция является массивом ячеек, где каждый элемент является вектором-строкой словесных индексов. Поскольку функция модели энкодера требует числового входа, соедините строки данных с помощью cat функцию и задать для конкатенации по первой размерности. Размер выхода miniBatchSize-by- sequenceLength, где sequenceLength - длина самой длинной последовательности в мини-пакете.

X = cat(1,X{:});
size(X)
ans = 1×2

    32    14

Преобразуйте данные в dlarray с форматом 'BTC' (пакет, время, канал). Программа автоматически переставляет выход в формат 'CTB' поэтому выход имеет размер 1-by- miniBatchSize-by- sequenceLength.

dlX = dlarray(X,'BTC');
size(dlX)
ans = 1×3

     1    32    14

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

sequenceLengths = doclength(documentsBatch);

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

iteration = 0;

% Loop over epochs.
for epoch = 1:numEpochs

    % Loop over mini-batches.
    for i = 1:numIterationsPerEpoch

        iteration = iteration + 1;

        % Read mini-batch.
        idx = (i-1)*miniBatchSize+1:i*miniBatchSize;
        documentsBatch = documents(idx);

        % Convert to sequences.
        X = doc2sequence(enc,documentsBatch, ...
            'PaddingDirection','right', ...
            'PaddingValue',paddingIdx);
        X = cat(1,X{:});

        % Convert to dlarray.
        dlX = dlarray(X,'BTC');

        % Calculate sequence lengths.
        sequenceLengths = doclength(documentsBatch);

        % Evaluate model gradients.
        % ...

        % Update learnable parameters.
        % ...
    end
end

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

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

Для выполнения прямого прохода энкодера используйте modelEncoder прямая функция с параметрами, данными и длинами последовательности в качестве входных параметров. Выходные выходы latentDimension-by- miniBatchSize матрица.

dlZ = modelEncoder(parameters,dlX,sequenceLengths);
size(dlZ)
ans = 1×2

    50    32

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

function gradients = modelGradients(parameters,dlX,sequenceLengths)
    
    dlZ = modelEncoder(parameters,dlX,sequenceLengths);

    % Calculate loss.
    % ...

    % Calculate gradients.
    % ...

end

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

iteration = 0;

% Loop over epochs.
for epoch = 1:numEpochs

    % Loop over mini-batches.
    for i = 1:numIterationsPerEpoch
        iteration = iteration + 1;

        % Prepare mini-batch.
        % ...

        % Evaluate model gradients.
        gradients = dlfeval(@modelGradients, parameters, dlX, sequenceLengths);

        % Update learnable parameters.
        [parameters,trailingAvg,trailingAvgSq] = adamupdate(parameters,gradients, ...
            trailingAvg,trailingAvgSq,iteration);
    end
end

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

The modelEncoder function, принимает за вход параметры модели, последовательности словесных индексов и длины последовательности и возвращает соответствующий латентный вектор функции.

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

function dlZ = modelEncoder(parameters,dlX,sequenceLengths)

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

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

numHiddenUnits = size(recurrentWeights,2);
hiddenState = zeros(numHiddenUnits,1,'like',dlX);
cellState = zeros(numHiddenUnits,1,'like',dlX);

dlZ1 = lstm(dlZ,hiddenState,cellState,inputWeights,recurrentWeights,bias);

% Output mode 'last' with masking.
miniBatchSize = size(dlZ1,2);
dlZ = zeros(numHiddenUnits,miniBatchSize,'like',dlZ1);
dlZ = dlarray(dlZ,'CB');

for n = 1:miniBatchSize
    t = sequenceLengths(n);
    dlZ(:,n) = dlZ1(:,n,t);
end

% Fully connect.
weights = parameters.fcEncoder.Weights;
bias = parameters.fcEncoder.Bias;
dlZ = fullyconnect(dlZ,weights,bias);

end

Функция предварительной обработки

Функция preprocessText выполняет следующие шаги:

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

  2. Токенизация текста с помощью tokenizedDocument.

function documents = preprocessText(textData,startToken,stopToken)

% Add start and stop tokens.
textData = startToken + textData + stopToken;

% Tokenize the text.
documents = tokenizedDocument(textData,'CustomTokens',[startToken stopToken]);

end

См. также

| |

Похожие темы