Main Content

1차원 컨벌루션을 사용한 sequence-to-sequence 분류

이 예제에서는 일반적인 시계열 컨벌루션 신경망(TCN: Temporal Convolutional Network)을 사용하여 시퀀스 데이터의 각 시간 스텝을 분류하는 방법을 보여줍니다.

sequence-to-sequence 작업은 주로 순환 신경망 아키텍처를 사용하여 풀지만, Bai et al. [1]에 따르면 전형적인 시퀀스 모델링 작업의 경우 컨벌루션 신경망이 순환 신경망에 준하는 성능이나 심지어 더 뛰어난 성능을 낼 수 있음을 보여줍니다. 컨벌루션 신경망을 사용하면 병렬 처리를 더 잘 활용하고, 수용 영역 크기를 더 잘 제어하고, 훈련하는 동안 신경망의 메모리 사용량을 더 잘 제어하고, 더 안정적인 기울기를 구하는 등의 이점을 기대할 수 있습니다. 순환 신경망과 마찬가지로 컨벌루션 신경망은 가변 길이 입력 시퀀스에 대해 연산을 수행할 수 있으며 sequence-to-sequence 작업 또는 sequence-to-one 작업을 모델링하는 데 사용될 수 있습니다.

이 예제에서는 신체에 스마트폰을 착용한 사람의 활동을 인식하도록 TCN을 훈련시킵니다. 세 방향의 가속도계 측정값을 나타내는 시계열 데이터를 사용하여 신경망을 훈련시킵니다.

훈련 데이터 불러오기

사람의 동작에 대한 인식 데이터를 불러옵니다. 이 데이터는 신체에 착용한 스마트폰으로부터 얻은 센서 데이터로 구성된 7개의 시계열을 포함합니다. 각 시퀀스는 3개의 특징을 가지며 길이가 서로 다릅니다. 3개의 특징은 세 방향의 가속도계 측정값에 대응됩니다.

s = load("HumanActivityTrain.mat");
XTrain = s.XTrain;
TTrain = s.YTrain;

훈련 데이터에 있는 관측값의 개수를 확인합니다.

numObservations = numel(XTrain)
numObservations = 
6

훈련 데이터의 클래스 개수를 확인합니다.

classes = categories(TTrain{1});
numClasses = numel(classes)
numClasses = 
5

훈련 데이터의 특징 개수를 확인합니다.

numFeatures = size(s.XTrain{1},1)
numFeatures = 
3

훈련 시퀀스 하나를 플롯으로 시각화합니다. 첫 번째 훈련 시퀀스의 특징과 대응하는 동작을 플로팅합니다.

figure
for i = 1:3
    X = s.XTrain{1}(i,:);

    subplot(4,1,i)
    plot(X)
    ylabel("Feature " + i + newline + "Acceleration")
end

subplot(4,1,4)

hold on
plot(s.YTrain{1})
hold off

xlabel("Time Step")
ylabel("Activity")

subplot(4,1,1)
title("Training Sequence 1")

딥러닝 모델 정의하기

TCN의 기본 컴포넌트는 팽창된 인과적 컨벌루션 계층으로, 각 시퀀스의 시간 스텝에 대해 연산을 수행합니다. 이 문맥 정보에서 "인과적"이라 함은 특정 시간 스텝에 대해 계산된 활성화가 미래 시간 스텝의 활성화에 종속되지 않는다는 의미입니다.

이전 시간 스텝으로부터 문맥 정보를 구축하기 위해 일반적으로 복수의 컨벌루션 계층을 쌓아서 올립니다. 다음 영상에 나와 있는 것처럼 수용 영역 크기를 크게 하기 위해 후속 컨벌루션 계층의 팽창 인자가 지수적으로 커집니다. k번째 컨벌루션 계층의 팽창 인자가 2(k-1)이고 스트라이드가 1이라고 가정할 경우 이러한 신경망의 수용 영역 크기는 R=(f-1)(2K-1)+1로 계산할 수 있습니다. 여기서 f는 필터 크기이고 K는 컨벌루션 계층의 개수입니다. 필터 크기와 계층의 개수를 변경하여 현재 데이터와 작업에 필요한 수용 영역 크기와 학습 가능 파라미터 개수를 쉽게 조정할 수 있습니다.

순환 신경망과 비교했을 때 TCN의 한 단점은 추론하는 동안 메모리 사용량이 더 크다는 것입니다. 다음 시간 스텝을 계산하려면 전체 원시 시퀀스가 필요합니다. 특히 향후 스텝 사전 예측에 사용되는 추론 시간과 메모리 사용량을 줄이려면, 합당한 수준 내에서 최소의 수용 영역 크기 R로 훈련시키고 입력 시퀀스의 마지막 R개 시간 스텝으로만 예측을 수행합니다.

일반적인 TCN 아키텍처([1]에 설명되어 있음)는 복수의 잔차 블록으로 구성되며, 각 블록에는 동일한 팽창 인자를 가진 팽창된 인과적 컨벌루션 계층이 두 세트씩 들어 있습니다. 그리고 각 컨벌루션 계층마다 정규화 계층, ReLU 활성화 계층, 공간 드롭아웃 계층이 따라옵니다. 신경망은 각 블록의 입력을 블록의 출력에 더해서 (이때 입력과 출력의 채널 개수가 일치하지 않을 경우 입력에 1×1 컨벌루션도 포함시킴) 최종 활성화 함수를 적용합니다.

이러한 잔차 블록을 연속해서 4개 포함하는 신경망을 정의합니다. 팽창 인자는 1부터 시작하고 각 블록마다 이전 계층에서의 팽창 인자의 두 배가 됩니다. 잔차 블록의 경우 필터 크기가 5인 1차원 컨벌루션 계층에 64개 필터를 지정하고 공간 드롭아웃 계층에 드롭아웃 인자 0.005를 지정합니다.

심층 신경망 디자이너 앱을 사용하여 이 신경망을 구축할 수도 있습니다. 심층 신경망 디자이너 시작 페이지의 Sequence-to-Sequence 분류 신경망(훈련되지 않음) 섹션에서 TCN을 클릭합니다.

numFilters = 64;
filterSize = 5;
dropoutFactor = 0.005;
numBlocks = 4;

net = dlnetwork;

layer = sequenceInputLayer(numFeatures,Normalization="rescale-symmetric",Name="input");

net = addLayers(net,layer);

outputName = layer.Name;

for i = 1:numBlocks
    dilationFactor = 2^(i-1);
    
    layers = [
        convolution1dLayer(filterSize,numFilters,DilationFactor=dilationFactor,Padding="causal",Name="conv1_"+i)
        layerNormalizationLayer
        spatialDropoutLayer(Probability=dropoutFactor)
        convolution1dLayer(filterSize,numFilters,DilationFactor=dilationFactor,Padding="causal")
        layerNormalizationLayer
        reluLayer
        spatialDropoutLayer(Probability=dropoutFactor)
        additionLayer(2,Name="add_"+i)];

    % Add and connect layers.
    net = addLayers(net,layers);
    net = connectLayers(net,outputName,"conv1_"+i);

    % Skip connection.
    if i == 1
        % Include convolution in first skip connection.
        layer = convolution1dLayer(1,numFilters,Name="convSkip");

        net = addLayers(net,layer);
        net = connectLayers(net,outputName,"convSkip");
        net = connectLayers(net,"convSkip","add_" + i + "/in2");
    else
        net = connectLayers(net,outputName,"add_" + i + "/in2");
    end
    
    % Update layer output name.
    outputName = "add_" + i;
end

layers = [
    fullyConnectedLayer(numClasses,Name="fc")
    softmaxLayer];

net = addLayers(net,layers);
net = connectLayers(net,outputName,"fc");

신경망을 플롯에 표시합니다.

figure
plot(net)
title("Temporal Convolutional Network")

훈련 옵션 지정하기

훈련에 사용되는 옵션 세트를 지정합니다. 옵션 중에서 선택하려면 경험적 분석이 필요합니다. 실험을 실행하여 다양한 훈련 옵션 구성을 살펴보려면 실험 관리자 앱을 사용합니다.

  • Adam 최적화 함수를 사용하여 훈련시킵니다.

  • 크기가 1인 미니 배치로 Epoch 60회만큼 훈련시킵니다.

  • 훈련 데이터는 행과 열이 각각 채널과 시간 스텝에 대응하는 시퀀스를 가지므로 입력 데이터 형식 "CTB"(채널, 시간, 배치)를 지정합니다.

  • 훈련 진행 상황을 플롯으로 표시하고 정확도를 모니터링합니다.

  • 상세 출력값을 비활성화합니다.

options = trainingOptions("adam", ...
    MaxEpochs=60, ...
    miniBatchSize=1, ...
    InputDataFormats="CTB", ...
    Plots="training-progress", ...
    Metrics="accuracy", ...
    Verbose=0);

모델 훈련시키기

trainnet 함수를 사용하여 신경망을 훈련시킵니다. 기본적으로 trainnet 함수는 GPU를 사용할 수 있으면 GPU를 사용합니다. GPU에서 훈련시키려면 Parallel Computing Toolbox™ 라이선스와 지원되는 GPU 장치가 필요합니다. 지원되는 장치에 대한 자세한 내용은 GPU 연산 요구 사항 (Parallel Computing Toolbox) 항목을 참조하십시오. GPU를 사용할 수 없는 경우, trainnet 함수는 CPU를 사용합니다. 실행 환경을 지정하려면 ExecutionEnvironment 훈련 옵션을 사용하십시오.

net = trainnet(XTrain,TTrain,net,"crossentropy",options);

모델 테스트하기

홀드아웃 테스트 세트에 대한 예측값을 각 시간 스텝의 실제 레이블과 비교하여 모델의 분류 정확도를 테스트합니다.

테스트 데이터를 불러옵니다.

s = load("HumanActivityTest.mat");
XTest = s.XTest;
TTest = s.YTest;

테스트 영상을 분류합니다. 여러 개의 관측값을 사용하여 예측을 수행하려면 minibatchpredict 함수를 사용합니다. 예측 점수를 레이블로 변환하려면 scores2label 함수를 사용합니다. minibatchpredict 함수는 GPU를 사용할 수 있으면 자동으로 GPU를 사용합니다. GPU를 사용할 수 없는 경우, 함수는 CPU를 사용합니다.

scores = minibatchpredict(net,XTest,InputDataFormats="CTB");
YPred = scores2label(scores,classes);

플롯에서 예측값을 대응하는 테스트 데이터와 비교합니다.

figure
plot(YPred,".-")
hold on
plot(TTest{1})
hold off

xlabel("Time Step")
ylabel("Activity")
legend(["Predicted" "Test Data"],Location="northeast")
title("Test Sequence Predictions")

예측값을 혼동행렬로 시각화합니다.

figure
confusionchart(TTest{1},YPred)

예측값을 테스트 레이블과 비교하여 분류 정확도를 평가합니다.

accuracy = mean(YPred == TTest{1})
accuracy = 
0.9905

참고 문헌

[1] Bai, Shaojie, J. Zico Kolter, and Vladlen Koltun. “An Empirical Evaluation of Generic Convolutional and Recurrent Networks for Sequence Modeling.” Preprint, submitted April 19, 2018. https://arxiv.org/abs/1803.01271.

[2] Oord, Aaron van den, Sander Dieleman, Heiga Zen, Karen Simonyan, Oriol Vinyals, Alex Graves, Nal Kalchbrenner, Andrew Senior, and Koray Kavukcuoglu. “WaveNet: A Generative Model for Raw Audio.” Preprint, submitted September 12, 2016. https://arxiv.org/abs/1609.03499.

[3] Tompson, Jonathan, Ross Goroshin, Arjun Jain, Yann LeCun, and Christoph Bregler. “Efficient Object Localization Using Convolutional Networks.” 2015 IEEE Conference on Computer Vision and Pattern Recognition (CVPR), 648–56. https://doi.org/10.1109/CVPR.2015.7298664.

참고 항목

| | | | | | | |

관련 항목