exponenta event banner

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

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

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

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

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

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

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

Прочитать данные «Сонетов» Шекспира из файла "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;

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

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.lstmEncoder.InputWeights = initializeGlorot(sz,numOut,numIn);
parameters.lstmEncoder.RecurrentWeights = initializeOrthogonal([4*numHiddenUnits numHiddenUnits]);
parameters.lstmEncoder.Bias = initializeUnitForgetGate(numHiddenUnits);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    32    14

Преобразование данных в dlarray с форматом 'BTC' (партия, время, канал). Программное обеспечение автоматически изменяет формат выходных данных. 'CTB' таким образом, выходной сигнал имеет размер 1около-miniBatchSizeоколо-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около-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

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

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

Поскольку входные данные содержат дополненные последовательности различной длины, заполнение может оказывать неблагоприятное влияние на вычисления потерь. Для операции 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

См. также

| | |

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