В этом примере показано, как классифицировать данные последовательности с помощью сети долгой краткосрочной памяти (LSTM).
Чтобы обучить глубокую нейронную сеть классифицировать данные последовательности, можно использовать сеть LSTM. Сеть LSTM позволяет вам вводить данные последовательности в сеть и делать предсказания на основе отдельных временных шагов данных последовательности.
Этот пример использует набор данных японских гласных, как описано в [1] и [2]. Этот пример обучает сеть LSTM распознавать говорящего по данным временных рядов, представляющих два японских гласных, на которых говорят последовательно. Обучающие данные содержат данные временных рядов для девяти дикторов. Каждая последовательность имеет 12 функции и изменяется в длине. Набор данных содержит 270 обучающих наблюдений и 370 тестовых наблюдений.
Загрузите обучающие данные японских гласных. XTrain
- массив ячеек, содержащий 270 последовательностей размерности 12 различной длины. Y
является категориальным вектором меток «1», «2»..., «9», которые соответствуют этим девяти дикторам. Записи в XTrain
матрицы с 12 строками (по одной строке для каждой функции) и меняющимся количеством столбцов (по одному столбцу для каждого временного шага).
[XTrain,YTrain] = japaneseVowelsTrainData; XTrain(1:5)
ans=5×1 cell array
{12×20 double}
{12×26 double}
{12×22 double}
{12×20 double}
{12×21 double}
Визуализируйте первые временные ряды на графике. Каждая линия соответствует функции.
figure plot(XTrain{1}') xlabel("Time Step") title("Training Observation 1") numFeatures = size(XTrain{1},1); legend("Feature " + string(1:numFeatures),'Location','northeastoutside')
Во время обучения по умолчанию программное обеспечение разделяет обучающие данные на мини-пакеты и заполняет последовательности так, чтобы они имели одинаковую длину. Слишком большое количество заполнения может негативно влияние на эффективность сети.
Чтобы предотвратить добавление слишком большого количества заполнений в процесс обучения, можно отсортировать обучающие данные по длине последовательности и выбрать размер мини-пакета, чтобы последовательности в мини-пакете имели одинаковую длину. Следующий рисунок показывает эффект заполнения последовательностей до и после сортировки данных.
Получите длины последовательности для каждого наблюдения.
numObservations = numel(XTrain); for i=1:numObservations sequence = XTrain{i}; sequenceLengths(i) = size(sequence,2); end
Отсортируйте данные по длине последовательности.
[sequenceLengths,idx] = sort(sequenceLengths); XTrain = XTrain(idx); YTrain = YTrain(idx);
Просмотрите отсортированные длины последовательности на столбчатой диаграмме.
figure bar(sequenceLengths) ylim([0 30]) xlabel("Sequence") ylabel("Length") title("Sorted Data")
Выберите мини-пакет размером 27, чтобы разделить обучающие данные равномерно и уменьшить количество заполнения в мини-пакетах. Следующий рисунок иллюстрирует заполнение, добавленное к последовательностям.
miniBatchSize = 27;
Определите сетевую архитектуру LSTM. Задайте размер входа, чтобы быть последовательностями размера 12 (размерность входных данных). Задайте двунаправленный слой LSTM со 100 скрытыми модулями измерения и выведите последний элемент последовательности. Наконец, задайте девять классов, включив полностью соединенный слой размера 9, затем слой softmax и слой классификации.
Если у вас есть доступ к полным последовательностям во время предсказания, то вы можете использовать двунаправленный слой LSTM в сети. Двунаправленный слой LSTM учится из полной последовательности на каждом временном шаге. Если у вас нет доступа к полной последовательности во время предсказания, для примера, если вы прогнозируете значения или прогнозируете один временной шаг за раз, используйте вместо этого слоя LSTM.
inputSize = 12; numHiddenUnits = 100; numClasses = 9; layers = [ ... sequenceInputLayer(inputSize) bilstmLayer(numHiddenUnits,'OutputMode','last') fullyConnectedLayer(numClasses) softmaxLayer classificationLayer]
layers = 5×1 Layer array with layers: 1 '' Sequence Input Sequence input with 12 dimensions 2 '' BiLSTM BiLSTM with 100 hidden units 3 '' Fully Connected 9 fully connected layer 4 '' Softmax softmax 5 '' Classification Output crossentropyex
Теперь задайте опции обучения. Задайте решатель, который будет 'adam'
, порог градиента, равный 1, и максимальное количество эпох, равное 100. Чтобы уменьшить количество заполнения в мини-пакетах, выберите мини-пакет размером 27. Чтобы дополнить данные такой же длиной, как и самые длинные последовательности, задайте длину последовательности, которая будет 'longest'
. Чтобы убедиться, что данные остаются отсортированными по длине последовательности, задайте, чтобы никогда не тасовать данные.
Поскольку мини-пакеты являются маленькими с короткими последовательностями, обучение лучше подходит для центрального процессора. Задайте 'ExecutionEnvironment'
чтобы быть 'cpu'
. Для обучения на графическом процессоре, при наличии, установите 'ExecutionEnvironment'
на 'auto'
(это значение по умолчанию).
maxEpochs = 100; miniBatchSize = 27; options = trainingOptions('adam', ... 'ExecutionEnvironment','cpu', ... 'GradientThreshold',1, ... 'MaxEpochs',maxEpochs, ... 'MiniBatchSize',miniBatchSize, ... 'SequenceLength','longest', ... 'Shuffle','never', ... 'Verbose',0, ... 'Plots','training-progress');
Обучите сеть LSTM с заданными опциями обучения при помощи trainNetwork
.
net = trainNetwork(XTrain,YTrain,layers,options);
Загрузите тестовый набор и классифицируйте последовательности в динамики.
Загрузите тестовые данные японских гласных. XTest
- массив ячеек, содержащий 370 последовательностей размерности 12 различной длины. YTest
является категориальным вектором меток «1», «2»... «9», которые соответствуют этим девяти дикторам.
[XTest,YTest] = japaneseVowelsTestData; XTest(1:3)
ans=3×1 cell array
{12×19 double}
{12×17 double}
{12×19 double}
Сетевые net
LSTM была обучена с использованием мини-партий последовательностей аналогичной длины. Убедитесь, что тестовые данные организованы таким же образом. Отсортируйте тестовые данные по длине последовательности.
numObservationsTest = numel(XTest); for i=1:numObservationsTest sequence = XTest{i}; sequenceLengthsTest(i) = size(sequence,2); end [sequenceLengthsTest,idx] = sort(sequenceLengthsTest); XTest = XTest(idx); YTest = YTest(idx);
Классификация тестовых данных. Чтобы уменьшить количество заполнения, введенного процессом классификации, установите размер мини-партии равным 27. Чтобы применить то же заполнение, что и обучающие данные, задайте длину последовательности, которая будет 'longest'
.
miniBatchSize = 27; YPred = classify(net,XTest, ... 'MiniBatchSize',miniBatchSize, ... 'SequenceLength','longest');
Вычислите классификационную точность предсказаний.
acc = sum(YPred == YTest)./numel(YTest)
acc = 0.9730
[1] М. Кудо, Дж. Тояма и М. Симбо. «Многомерная классификация кривых с использованием областей». Распознавание Букв. Том 20, № 11-13, стр. 1103-1111.
[2] UCI Machine Learning Repository: Японский набор данных гласных. https://archive.ics.uci.edu/ml/datasets/Japanese+Vowels
bilstmLayer
| lstmLayer
| sequenceInputLayer
| trainingOptions
| trainNetwork