Main Content

딥러닝을 사용한 시퀀스 분류

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

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

이 예제에서는 파형 데이터 세트를 사용합니다. 이 예제에서는 시계열 데이터를 주고 파형 유형을 인식하도록 LSTM 신경망을 훈련시킵니다. 훈련 데이터는 네 가지 유형의 파형에 대한 시계열 데이터를 포함합니다. 각 시퀀스는 3개의 채널을 가지며 길이가 서로 다릅니다.

시퀀스 데이터 불러오기

WaveformData에서 예제 데이터를 불러옵니다. 이 시퀀스 데이터는 시퀀스로 구성된 numObservations×1 셀형 배열이며, 여기서 numObservations는 시퀀스 개수입니다. 각 시퀀스는 numChannels×-numTimeSteps 숫자형 배열이며, 여기서 numChannels는 시퀀스의 채널 개수이고 numTimeSteps는 시퀀스의 시간 스텝 개수입니다. 레이블 데이터는 numObservations×1 categorical형 벡터입니다.

load WaveformData 

시퀀스 중 일부를 플롯으로 시각화합니다.

numChannels = size(data{1},1);

idx = [3 4 5 12];
figure
tiledlayout(2,2)
for i = 1:4
    nexttile
    stackedplot(data{idx(i)}',DisplayLabels="Channel "+string(1:numChannels))
    
    xlabel("Time Step")
    title("Class: " + string(labels(idx(i))))
end

테스트를 위해 데이터를 남겨 둡니다. 데이터의 90%가 포함된 훈련 세트와 데이터의 나머지 10%가 포함된 테스트 세트로 데이터를 분할합니다. 데이터를 분할하려면 이 예제에 지원 파일로 첨부된 trainingPartitions 함수를 사용합니다. 이 파일에 액세스하려면 이 예제를 라이브 스크립트로 여십시오.

numObservations = numel(data);
[idxTrain,idxTest] = trainingPartitions(numObservations, [0.9 0.1]);
XTrain = data(idxTrain);
TTrain = labels(idxTrain);

XTest = data(idxTest);
TTest = labels(idxTest);

채우기를 위해 데이터 준비하기

기본적으로 훈련 중에 훈련 데이터가 미니 배치로 분할되고 모든 시퀀스의 길이가 같아지도록 시퀀스가 채워집니다. 너무 많이 채우면 신경망 성능이 저하될 수 있습니다.

훈련 과정에서 너무 많이 채워지지 않도록 하려면 시퀀스 길이를 기준으로 시퀀스 데이터를 정렬한 다음 미니 배치 크기를 선택하여 하나의 미니 배치에 속한 시퀀스들이 비슷한 길이를 갖도록 합니다. 다음 그림에서는 데이터를 정렬하기 전과 후의 시퀀스 채우기의 효과를 보여줍니다.

각 관측값에 대한 시퀀스 길이를 가져옵니다.

numObservations = numel(XTrain);
for i=1:numObservations
    sequence = XTrain{i};
    sequenceLengths(i) = size(sequence,2);
end

시퀀스 길이를 기준으로 데이터를 정렬합니다.

[sequenceLengths,idx] = sort(sequenceLengths);
XTrain = XTrain(idx);
TTrain = TTrain(idx);

정렬된 시퀀스 길이를 막대 차트로 표시합니다.

figure
bar(sequenceLengths)
xlabel("Sequence")
ylabel("Length")
title("Sorted Data")

LSTM 신경망 아키텍처 정의하기

LSTM 신경망 아키텍처를 정의합니다. 입력 크기를 입력 데이터의 채널 개수로 지정합니다. 은닉 유닛 120개를 갖는 양방향 LSTM 계층을 지정하고 시퀀스의 마지막 요소를 출력합니다. 마지막으로, 출력 크기가 클래스 개수와 일치하는 완전 연결 계층을 포함하고 그 뒤에 소프트맥스 계층과 분류 계층을 포함합니다.

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

numHiddenUnits = 120;
numClasses = 4;

layers = [ ...
    sequenceInputLayer(numChannels)
    bilstmLayer(numHiddenUnits,OutputMode="last")
    fullyConnectedLayer(numClasses)
    softmaxLayer
    classificationLayer]
layers = 
  5×1 Layer array with layers:

     1   ''   Sequence Input          Sequence input with 3 dimensions
     2   ''   BiLSTM                  BiLSTM with 120 hidden units
     3   ''   Fully Connected         4 fully connected layer
     4   ''   Softmax                 softmax
     5   ''   Classification Output   crossentropyex

훈련 옵션을 지정합니다. Adam 솔버에 학습률을 0.002로, 기울기 임계값을 1로 설정하여 훈련시킵니다. 최대 Epoch 횟수를 150으로 설정하고 데이터 섞기를 비활성화합니다. 소프트웨어는 기본적으로 사용 가능한 GPU가 있으면 GPU에서 훈련시킵니다. GPU를 사용하려면 Parallel Computing Toolbox와 지원되는 GPU 장치가 필요합니다. 지원되는 장치에 대한 자세한 내용은 GPU 연산 요구 사항 (Parallel Computing Toolbox) 항목을 참조하십시오.

options = trainingOptions("adam", ...
    InitialLearnRate=0.002,...
    MaxEpochs=150, ...
    Shuffle="never", ...
    GradientThreshold=1, ...
    Verbose=false, ...
    Plots="training-progress");

LSTM 신경망 훈련시키기

trainNetwork를 사용하여 지정된 훈련 옵션으로 LSTM 신경망을 훈련시킵니다.

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

LSTM 신경망 테스트하기

테스트 데이터를 분류하고 예측의 분류 정확도를 계산합니다.

XTest(1:3)
ans=3×1 cell array
    {3×127 double}
    {3×180 double}
    {3×193 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);
TTest = TTest(idx);

테스트 데이터를 분류하고 예측의 분류 정확도를 계산합니다.

YTest = classify(net,XTest);
acc = mean(YTest == TTest)
acc = 0.8400

분류 결과를 혼동행렬 차트로 표시합니다.

figure
confusionchart(TTest,YTest)

참고 항목

| | | |

관련 항목