Main Content

深層学習を使用したシーケンスの分類

この例では、長短期記憶 (LSTM) ネットワークを使用してシーケンス データを分類する方法を説明します。

シーケンス データを分類するように深層ニューラル ネットワークに学習させるには、LSTM ニューラル ネットワークを使用します。LSTM ニューラル ネットワークでは、シーケンス データをネットワークに入力し、シーケンス データの個々のタイム ステップに基づいて予測を行うことができます。

次の図は、シーケンス分類ニューラル ネットワークを流れるシーケンス データを示しています。

この例では、波形データ セットを使用します。この例では、与えられた時系列データについて波形のタイプを認識するように LSTM ニューラル ネットワークに学習させます。学習データには 4 種類の波形の時系列データが含まれています。各シーケンスには 3 つのチャネルがあり、長さはさまざまです。

シーケンス データの読み込み

サンプル データを WaveformData から読み込みます。シーケンス データは、シーケンスの numObservations 行 1 列の cell 配列です。ここで、numObservations はシーケンスの数です。各シーケンスは numTimeStepsnumChannels 列の数値配列です。ここで、numTimeSteps はシーケンスのタイム ステップ数、numChannels はシーケンスのチャネル数です。ラベル データは、numObservations1 列の categorical ベクトルです。

load WaveformData 

シーケンスの一部をプロットで可視化します。

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

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

クラス名を表示します。

classNames = categories(labels)
classNames = 4×1 cell
    {'Sawtooth'}
    {'Sine'    }
    {'Square'  }
    {'Triangle'}

テスト用のデータを確保します。データの 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,1);
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 層は、各タイム ステップでシーケンス全体から学習します。予測時にシーケンス全体にアクセスしない場合、たとえば、値を予想していたり一度に 1 タイム ステップを予測していたりする場合は、代わりに LSTM 層を使用します。

numHiddenUnits = 120;
numClasses = 4;

layers = [
    sequenceInputLayer(numChannels)
    bilstmLayer(numHiddenUnits,OutputMode="last")
    fullyConnectedLayer(numClasses)
    softmaxLayer]
layers = 
  4×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

学習オプションの指定

学習オプションを指定します。オプションの中から選択するには、経験的解析が必要です。実験を実行してさまざまな学習オプションの構成を調べるには、Experiment Managerアプリを使用できます。

  • Adam ソルバーを使用して学習させます。

  • 学習を 200 エポック行います。

  • 学習率に 0.002 を指定します。

  • しきい値 1 で勾配をクリップします。

  • シーケンスを長さで並べ替えられた状態に保つために、シャッフルを無効にします。

  • 学習の進行状況をプロットで表示し、精度を監視します。

  • 詳細出力を無効にします。

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

LSTM ニューラル ネットワークの学習

関数trainnetを使用してニューラル ネットワークに学習させます。分類には、クロスエントロピー損失を使用します。既定では、関数 trainnet は利用可能な GPU がある場合にそれを使用します。GPU を使用するには、Parallel Computing Toolbox™ ライセンスとサポートされている GPU デバイスが必要です。サポートされているデバイスについては、GPU 計算の要件 (Parallel Computing Toolbox)を参照してください。そうでない場合、関数は CPU を使用します。実行環境を指定するには、ExecutionEnvironment 学習オプションを使用します。

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

LSTM ニューラル ネットワークのテスト

テスト データを分類し、予測の分類精度を計算します。

LSTM ニューラル ネットワーク net は、長さがほぼ等しいシーケンスのミニバッチを使用して学習されています。テスト データも同じ方法で構成されるようにします。シーケンス長でテスト データを並べ替えます。

numObservationsTest = numel(XTest);
for i=1:numObservationsTest
    sequence = XTest{i};
    sequenceLengthsTest(i) = size(sequence,1);
end

[sequenceLengthsTest,idx] = sort(sequenceLengthsTest);
XTest = XTest(idx);
TTest = TTest(idx);

テスト データを分類し、予測の分類精度を計算します。

関数minibatchpredictを使用して予測を行い、関数scores2labelを使用してスコアをラベルに変換します。既定では、関数 minibatchpredict は利用可能な GPU がある場合にそれを使用します。

scores = minibatchpredict(net,XTest);
YTest = scores2label(scores,classNames);

分類精度を計算します。精度は、正しく予測されたラベルの割合です。

acc = mean(YTest == TTest)
acc = 0.8700

分類結果を混同チャートで表示します。

figure
confusionchart(TTest,YTest)

参考

| | | | |

関連するトピック