이 페이지의 최신 내용은 아직 번역되지 않았습니다. 최신 내용은 영문으로 볼 수 있습니다.

심층 학습을 사용한 시퀀스 분류

이 예제에서는 장단기 기억(LSTM) 네트워크를 사용하여 시퀀스 데이터를 분류하는 방법을 보여줍니다.

시퀀스 데이터를 분류하도록 심층 신경망을 훈련시키기 위해 LSTM 신경망을 사용할 수 있습니다. LSTM 네트워크를 사용하면 네트워크에 시퀀스 데이터를 입력하고 시퀀스 데이터의 개별 시간 스텝을 기준으로 예측을 수행할 수 있습니다.

이 예제에서는 [1]과 [2]에서 설명한 Japanese Vowels 데이터 세트를 사용합니다. 이 예제에서는 연속해서 발화된 2개의 일본어 모음을 나타내는 시계열 데이터를 주고 화자를 인식하도록 LSTM 네트워크를 훈련시킵니다. 훈련 데이터는 화자 9명의 시계열 데이터를 포함합니다. 각 시퀀스는 12개의 특징을 가지며 길이가 서로 다릅니다. 데이터 세트는 270개의 훈련 관측값과 370개의 테스트 관측값을 포함합니다.

시퀀스 데이터 불러오기

Japanese Vowels 훈련 데이터를 불러옵니다. XTrain은 12개 차원으로 된 서로 다른 길이의 시퀀스 270개를 포함하는 셀형 배열입니다. Y는 9명의 화자 각각에 대응하는 레이블 "1","2",...,"9"로 구성된 categorical형 벡터입니다. XTrain의 요소는 각 특징에 대해 하나의 행을 갖는 12개의 행과 각 시간 스텝에 대해 하나의 열을 갖는 가변 개수의 열로 이루어진 행렬입니다.

[XTrain,YTrain] = japaneseVowelsTrainData;
XTrain(1:5)
ans = 5x1 cell array
    {12x20 double}
    {12x26 double}
    {12x22 double}
    {12x20 double}
    {12x21 double}

첫 번째 시계열을 플롯으로 시각화합니다. 선은 각각 하나의 특징에 대응됩니다.

figure
plot(XTrain{1}')
xlabel("Time Step")
title("Training Observation 1")
legend("Feature " + string(1:12),'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 네트워크 아키텍처 정의하기

LSTM 네트워크 아키텍처를 정의합니다. 시퀀스의 입력 크기를 12(입력 데이터의 차원)로 지정합니다. 은닉 유닛 100개를 갖는 양방향 LSTM 계층을 지정하고 시퀀스의 마지막 요소를 출력합니다. 마지막으로, 크기가 9인 완전 연결 계층을 포함하여 9개의 클래스를 지정하고, 이어서 소프트맥스 계층과 분류 계층을 지정합니다.

예측 시점에 전체 시퀀스에 액세스할 수 있다면 네트워크에서 양방향 LSTM 계층을 사용할 수 있습니다. 양방향 LSTM 계층은 각 시간 스텝마다 전체 시퀀스로부터 학습합니다. 예측 시점에 전체 시퀀스에 액세스할 수 없다면, 예를 들어 한 번에 하나의 시간 스텝의 값을 예측하려 한다면, LSTM 계층을 대신 사용합니다.

inputSize = 12;
numHiddenUnits = 100;
numClasses = 9;

layers = [ ...
    sequenceInputLayer(inputSize)
    bilstmLayer(numHiddenUnits,'OutputMode','last')
    fullyConnectedLayer(numClasses)
    softmaxLayer
    classificationLayer]
layers = 
  5x1 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로 지정하고, 최대 Epoch 횟수를 100으로 지정합니다. 미니 배치의 채우기 양을 줄이려면 미니 배치 크기를 27로 선택하십시오. 데이터가 가장 긴 시퀀스의 길이와 같도록 데이터를 채우려면 시퀀스 길이를 'longest'로 지정하십시오. 데이터가 시퀀스 길이를 기준으로 정렬된 상태를 유지하도록 하려면 데이터가 섞이지 않도록 지정하십시오.

미니 배치가 짧은 시퀀스를 갖는 작은 배치이기 때문에 훈련에는 CPU를 사용하는 것이 더 적합합니다. 'ExecutionEnvironment''cpu'로 지정합니다. GPU를 사용할 수 있는 경우 GPU를 훈련시키려면 '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를 사용하여 지정된 훈련 옵션으로 LSTM 네트워크를 훈련시킵니다.

net = trainNetwork(XTrain,YTrain,layers,options);

LSTM 네트워크 테스트하기

테스트 세트를 불러오고 시퀀스를 화자별로 분류합니다.

Japanese Vowels 테스트 데이터를 불러옵니다. XTest는 12개 차원으로 된 서로 다른 길이의 시퀀스 370개를 포함하는 셀형 배열입니다. YTest는 9명의 화자에 대응하는 레이블 "1","2",..."9"로 구성된 categorical형 벡터입니다.

[XTest,YTest] = japaneseVowelsTestData;
XTest(1:3)
ans = 3x1 cell array
    {12x19 double}
    {12x17 double}
    {12x19 double}

LSTM 네트워크 net은 비슷한 길이를 갖는 시퀀스를 포함하는 미니 배치를 사용하여 훈련되었습니다. 테스트 데이터도 같은 방식으로 구성되도록 합니다. 시퀀스 길이를 기준으로 테스트 데이터를 정렬합니다.

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.9324

참고 문헌

[1] M. Kudo, J. Toyama, and M. Shimbo. "Multidimensional Curve Classification Using Passing-Through Regions." Pattern Recognition Letters. Vol. 20, No. 11–13, pages 1103–1111.

[2] UCI Machine Learning Repository: Japanese Vowels Dataset. https://archive.ics.uci.edu/ml/datasets/Japanese+Vowels

참고 항목

| | | |

관련 항목