1 次元畳み込みを使用した sequence-to-sequence 分類
この例では、一般的な時間的畳み込みネットワーク (TCN) を使用してシーケンス データの各タイム ステップを分類する方法を説明します。
sequence-to-sequence のタスクは一般的に再帰型ニューラル ネットワーク アーキテクチャを使って解きますが、典型的なシーケンス モデリングのタスクにおいては畳み込みニューラル ネットワークでも再帰型ネットワークと同等あるいはそれ以上の性能を発揮できることが Bai et al. [1] によって示されています。畳み込みネットワークを使用する潜在的な利点は、並列処理に優れること、受容野のサイズの制御に優れること、学習中のネットワークのメモリ フットプリントの制御に優れること、および勾配が安定していることです。再帰型ネットワークと同様に、畳み込みネットワークは可変長の入力シーケンスに対する操作が可能で、sequence-to-sequence や sequence-to-one のタスクのモデル化に使用できます。
この例では、スマートフォンを体に装着している人の活動を認識するように TCN に学習させます。3 方向の加速度計の測定値を表す時系列データを使用してネットワークに学習させます。
学習データの読み込み
行動認識データを読み込みます。このデータには、体に装着したスマートフォンから得られたセンサー データの 7 つの時系列が含まれています。各シーケンスには 3 つの特徴があり、長さはさまざまです。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
1 つの学習シーケンスをプロットで可視化します。最初の学習シーケンスの特徴と対応する行動をプロットします。
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 番目の畳み込み層の膨張係数が 、ストライドが 1 と仮定すると、そのようなネットワークの受容野のサイズは で計算できます。ここで、 はフィルター サイズ、 は畳み込み層の数です。フィルター サイズと層の数を変更することで、使用するデータやタスクの必要に合わせて、受容野のサイズや学習可能パラメーターの数を簡単に調整できます。
再帰型ネットワークと比較した場合の TCN の欠点の 1 つは、推論中のメモリ フットプリントが大きいことです。次のタイム ステップの計算には生のシーケンス全体が必要です。推論時間とメモリ消費量を削減するために、特にステップ先行の予測では、受容野の最小の妥当なサイズ で学習させ、入力シーケンスの最後の タイム ステップでのみ予測を実行します。
一般的な TCN アーキテクチャ ([1] を参照) は、複数の残差ブロックで構成されています。それぞれのブロックには、同じ膨張係数をもつ膨張因果畳み込み層の 2 つのセットが含まれ、その後に正規化層、ReLU 活性化層、および空間ドロップアウト層が続きます。ネットワークは、各ブロックの入力をブロックの出力に追加し (入力と出力のチャネル数が一致しない場合は入力の 1 x 1 の畳み込みも含む)、最終的な活性化関数を適用します。
これらの残差ブロックを 4 つ直列に含み、それぞれが前の層の 2 倍の膨張係数を持ち、膨張係数 1 で始まるネットワークを定義します。残差ブロックには、フィルター サイズを 5、空間ドロップアウト層のドロップアウト係数 0.005 として、1 次元畳み込み層向けに 64 個のフィルター数を指定します。空間ドロップアウトには、この例にサポート ファイルとして添付されているカスタム層 spatialDropoutLayer
を使用します。この層にアクセスするには、この例をライブ スクリプトとして開きます。
numFilters = 64; filterSize = 5; dropoutFactor = 0.005; numBlocks = 4; layer = sequenceInputLayer(numFeatures,Normalization="rescale-symmetric",Name="input"); lgraph = layerGraph(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(dropoutFactor) convolution1dLayer(filterSize,numFilters,DilationFactor=dilationFactor,Padding="causal") layerNormalizationLayer reluLayer spatialDropoutLayer(dropoutFactor) additionLayer(2,Name="add_"+i)]; % Add and connect layers. lgraph = addLayers(lgraph,layers); lgraph = connectLayers(lgraph,outputName,"conv1_"+i); % Skip connection. if i == 1 % Include convolution in first skip connection. layer = convolution1dLayer(1,numFilters,Name="convSkip"); lgraph = addLayers(lgraph,layer); lgraph = connectLayers(lgraph,outputName,"convSkip"); lgraph = connectLayers(lgraph,"convSkip","add_" + i + "/in2"); else lgraph = connectLayers(lgraph,outputName,"add_" + i + "/in2"); end % Update layer output name. outputName = "add_" + i; end layers = [ fullyConnectedLayer(numClasses,Name="fc") softmaxLayer classificationLayer]; lgraph = addLayers(lgraph,layers); lgraph = connectLayers(lgraph,outputName,"fc");
ネットワークをプロットで表示します。
figure
plot(lgraph)
title("Temporal Convolutional Network")
学習オプションの指定
学習に使用するオプションのセットを指定します。
ミニバッチ サイズを 1 として 60 エポック学習させます。
学習率を 0.001 にして学習を行います。
プロットに学習の進行状況を表示し、詳細出力を表示しないようにします。
options = trainingOptions("adam", ... MaxEpochs=60, ... miniBatchSize=1, ... Plots="training-progress", ... Verbose=0);
モデルの学習
net = trainNetwork(XTrain,TTrain,lgraph,options);
モデルのテスト
各タイム ステップの真のラベルをもつホールド アウトされたテスト セットの予測を比較して、モデルの分類精度をテストします。
テスト データを読み込みます。
s = load("HumanActivityTest.mat");
XTest = s.XTest;
TTest = s.YTest;
学習済みネットワークを使用し、関数 classify
を使用して予測を行います。
YPred = classify(net,XTest);
予測とプロット内の対応するテスト データを比較します。
figure plot(YPred{1},".-") 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{1})
予測とテスト ラベルを比較して、分類の精度を評価します。
accuracy = mean(YPred{1} == TTest{1})
accuracy = 0.9919
参考文献
[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.
参考
convolution1dLayer
| trainingOptions
| trainNetwork
| sequenceInputLayer
| maxPooling1dLayer
| averagePooling1dLayer
| globalMaxPooling1dLayer
| globalAveragePooling1dLayer