Main Content

このページの翻訳は最新ではありません。ここをクリックして、英語の最新版を参照してください。

ラベル付き信号セットを作成して労力を軽減するための反復アプローチ

この例では、信号のラベル付けに伴う労力を軽減する、深層学習ベースの反復的なワークフローを紹介します。

信号データへのラベル付けは、多大な労力を必要とする手間と費用のかかるタスクです。この労力を軽減できれば、信号処理の問題に対する深層学習ソリューションの開発は、大幅に高速化される可能性があります。

信号データ セット内の関心領域に対するラベル付けというタスクを検討します。最初のアプローチでは、データへのラベル付けを手作業で行います。このアプローチでは、多大な時間と労力が必要になります。この例で検証する代替手法では、ラベル付け処理を反復的に行います。各反復において、信号のサブセットがラベルの付いていないデータ セットから選択され、自動ラベル付け用に事前学習済みの深層ネットワークに送信されます。ラベル付け担当者は、結果として得られたラベルを調査し、正しくないラベルを修正します。検証済みのラベル付き信号が学習データ セットに追加され、拡張された学習データを使用して深層ネットワークに再学習させます。

それでもなお、ラベル付け担当者は、各反復において、ネットワークによってラベル付けされたすべての信号を確認および調査する必要があります。とはいえ、タスクは、ゼロからの信号へのラベル付けから、信頼性の高いネットワークが生成した不正確なラベルの修正に変化しています。後者のタスクで要求されるラベル付けの労力は、はるかに小さいものとなります。新しい反復ごとに、ネットワークに学習させるために使用するデータは多くなります。それにより、ネットワークの予測およびラベル付けのパフォーマンスが向上します。そのため、ラベル修正のために人が介入する必要性は、反復ごとに小さくなります。

データ

この例では、一般に公開されている QT データベースのデータを使用した、ECG 信号領域のラベル付けを検討します [1] [2]。データは、合計 105 人の患者からの約 15 分間の ECG の記録で構成されています。各記録を取得するために、検査員は患者の胸部の異なる場所に 2 つの電極を配置して、2 チャネル信号にします。データベースは、自動化されたエキスパート システムによって生成される信号領域ラベルを提供します [3]。ラベルは、ECG 測定における P 波、R 波、および QRS 群領域の位置に対応します。この例では、深層学習を使用した波形セグメンテーションで示されている手続きに従って双方向長短期記憶 (BiLSTM) ネットワークの学習を行います。BiLSTM ネットワークでは、ECG 信号サンプルを 3 つの関心領域のいずれかに属するものとして分類できます。

GitHub リポジトリからデータをダウンロードします。この例では、一時ディレクトリにファイルを配置していて、その場所は MATLAB® の tempdir コマンドによって指定されると仮定しています。データファイルを解凍し、データを読み込みます。

unzip(fullfile(tempdir,'QT_Database-master.zip'),tempdir)
load(fullfile(tempdir,'QT_Database-master','QTData.mat'))

補助関数 displayWaveformLabels を使用して、最初の患者から ECG 信号の最初の 1000 サンプルをプロットします。このとき、エキスパート システムがラベル付けした領域は、異なる色で塗り重ねられます。データセットには、余分なラベル 'N/A' が含まれます。このラベルは、3 つの関心領域のいずれにも属さない信号サンプルを特定するために使用されます。

patientID = 1;
signalVals = getSignal(QTData,patientID);
labelVals = getLabelValues(QTData,patientID,'WaveformLabels_Chan1');

displayWaveformLabels(signalVals(1,1:1000),labelVals.Value(1:1000)) 

補助関数 resizeSignals を使用して、ECG 信号とラベルのベクトルを各々が 5000 サンプル長のフレームに分割します。次いで、この関数はそれらのフレームをシャッフルして、データの 70% を含む学習データ セットとデータの 30% を含むテスト データ セットに分割します。

rng default
[testFrames,testLabels,ecgFrames,ecgLabels,testInfo,ecgInfo] = resizeSignals(QTData,0.3);

ecgFrames には 6543 個、testFrames には 2768 個のフレームが含まれます。変数 ecgInfo は、学習データ セットの各フレームの患者 ID、チャネル ID、およびサンプル インデックスを格納します。testInfo は、テスト データ セットに関する同様の情報を格納します。

ECG フレームを時間-周波数領域に変換します。補助関数 featureExtraction を使用して、対象となる周波数範囲 [0.5, 40] Hz 間の ECG 信号フレームのフーリエ シンクロスクイーズド変換を計算し、その平均を減算して標準偏差で除算することで、得られた変換を標準化します。

Fs = QTData.SampleRate;
testFrames = featureExtraction(testFrames,Fs);
ecgFrames = featureExtraction(ecgFrames,Fs);

この例では、深層ネットワークに反復的に学習させることにより、信号のラベル付けに伴う労力を軽減できることを示します。各反復では次が行われます。

  1. ネットワークが、以前にラベル付けされたフレームを使用して、ラベルが付いていないデータ フレームのサブセットにラベル付けします。

  2. ラベル付け担当者が、ラベル付けの誤りを手作業で修正します。

  3. 修正されたラベル付けが、以前にラベル付けされたフレームに追加されます。

  4. 拡張されたラベル付き信号のセットが、次回の反復に向けたネットワークの学習に使用されます。

定量的な比較を行うために、次の 2 つのシナリオをシミュレーションします。

  • 基本となるシナリオでは、人がゼロからデータセット全体にラベル付けを行い、完全にラベル付けされた ecgFrames セットを使用してネットワークに学習させます。

  • 2 番目のシナリオでは、ecgFrames データにラベルが付いておらず、そのラベル付けを反復的な方法で行うものとします。

完全にラベル付けされた ECG データ セットを使用した予測パフォーマンス

BiLSTM ネットワークを作成し、完全にラベル付けされた ecgFrames セットを使用してそのネットワークに学習させることにより、予測パフォーマンスの上限を得ます。上述のように、このアプローチではデータ セット全体に対して総当たり的なラベル付けが必要になり、必要な労力が最大となります。ラベル付けされた ecgFrames セットでネットワークに学習させ、テスト データ セットに対する予測精度を計算します。

ネットワーク アーキテクチャ

深層学習層を使用して BiLSTM ネットワークを作成します。

  • 信号の FSST に含まれる特徴の数 (周波数領域サンプルの総数。この例では 40) をサイズとして使用して、sequenceInputLayer を指定します。

  • 各信号サンプルにラベルが付けられているため、200 個の非表示ノードを使用して bilstmLayer を指定し、OutputModesequence に設定します。

  • P 波、QRS 群、T 波、および N/A という 4 つのカテゴリに対応する出力サイズ 4 を使用して fullyConnectedLayer を指定します。

  • softmaxLayerclassificationLayer を追加して、推定ラベルを出力します。

% Training with the full emulated unlabeled data set
layers = [ ...
    sequenceInputLayer(size(ecgFrames{1},1))
    bilstmLayer(200,'OutputMode','sequence')
    fullyConnectedLayer(4)
    softmaxLayer
    classificationLayer];

traningOptions で最適化ソルバーとハイパーパラメーターを指定して、ネットワークに学習させます。この例では、ADAM オプティマイザーと 50 のミニバッチ サイズを使用します。CPU または GPU を使用してネットワークに学習させます。GPU を使用するには、Parallel Computing Toolbox™、および Compute Capability 3.0 以上の CUDA® 対応 NVIDIA® GPU が必要です。その他のパラメーターの詳細については、trainingOptions (Deep Learning Toolbox)を参照してください。この例では、'ExecutionEnvironment' の名前と値のペアを使用する学習に GPU を使用します。

options = trainingOptions('adam', ...
    'MaxEpochs',10, ...
    'MiniBatchSize',50, ...
    'ExecutionEnvironment','gpu', ...
    'InitialLearnRate',0.01, ...
    'LearnRateDropPeriod',6, ...
    'LearnRateSchedule','piecewise', ...
    'GradientThreshold',1, ...
    'Shuffle','every-epoch',...
    'Plots','training-progress',...
    'Verbose',0);

完全にラベル付けされた ecgFrames データ セットを使用して、ネットワークの学習を行います。

baselineNet = trainNetwork(ecgFrames,ecgLabels,layers,options);

学習済みネットワークを使用してテスト フレームを分類し、平均予測精度を計算します。基準となる予測精度は約 95% です。

predictLabelsAll = classify(baselineNet,testFrames,'MiniBatchSize',50);
accuracyAll = mean(cellfun(@(x,y)mean(x==y),predictLabelsAll,testLabels));
fprintf('The baseline prediction accuracy is %2.1f%%.\n',accuracyAll*100);
The baseline prediction accuracy is 94.2%.

人によるループでの反復的なラベル付け

ラベル付けの労力を軽減するために、次の反復的なアプローチを試します。最初の時点では ecgFrames データ セットにラベルが付いておらず、データに手作業でラベル付けするものとします。実際には、この例では、データ セットが提供するグラウンド トゥルース ラベルを使用します。

初期ネットワークの学習

まず、ecgFrames セットから 25 個のフレームを選択し、それらに手作業でラベル付けします。反復処理の最初のステップとして、最初にラベル付けされたこのセットを使用して BiLSTM ネットワークの学習を行います。

numInitFrames = 25;

currentTrainingSet = ecgFrames(1:numInitFrames,1);
currentTrainingLabels = ecgLabels(1:numInitFrames);

最初の学習データ セットには 25 個のフレームしか存在しないため、学習エポックの回数を増やし、ミニバッチ サイズが小さくなるように学習オプションを設定します。

options = trainingOptions('adam', ...
    'MaxEpochs',20, ...
    'MiniBatchSize',5, ...
    'ExecutionEnvironment','gpu', ...
    'InitialLearnRate',0.01, ...
    'LearnRateDropPeriod',6, ...
    'LearnRateSchedule','piecewise', ...
    'GradientThreshold',1, ...
    'Shuffle','every-epoch', ...
    'Plots','none',...
    'Verbose',0);

最初の学習データ セットで BiLSTM ネットワークに学習させ、パフォーマンスのベースラインの確立に使用されるのと同じテスト データ セットを使用してラベルを予測します。ネットワークの予測精度は約 80% を下回ります。

initNet = trainNetwork(currentTrainingSet,currentTrainingLabels,layers,options);
initPrediction = classify(initNet,testFrames,'MiniBatchSize',50); 
initAccuracy = mean(cellfun(@(x,y)mean(x==y),initPrediction,testLabels));
fprintf('The prediction accuracy is %2.1f%%.\n',initAccuracy*100);
The prediction accuracy is 78.3%.

ラベル付け

次のステップでは、ecgFrames セットから 200 個の新しいデータ フレームを選択し、それらを事前学習済みのネットワーク initNet に供給することで、信号に自動でラベル付けします。

iteration = 1;
% Number of frames to label at each iteration
numFrames = 200; 
% Select the next set of frames to label
indexNext = numInitFrames+1:numInitFrames+numFrames;
currentPrediction = classify(initNet,ecgFrames(indexNext),'MiniBatchSize',50);

ネットワークが生成したラベル付けの結果を評価し、その結果をグラウンド トゥルースと比較します。次の例のように、選択した 200 サンプルのデータ フレームの 3 番目を使用します。グラウンド トゥルース ラベルおよびネットワークが予測したラベルを重ね合わせた最初の 750 サンプルをプロットします。

idx = 3;
info = ecgInfo{indexNext(idx)};
signal = QTData.Source{info.patientID}(info.channelID,info.indexID);
groundTruthLabels = ecgLabels{indexNext(idx)};
predictedLabels = currentPrediction{idx};

subplot(2,1,1)
displayWaveformLabels(signal,groundTruthLabels)
xlim([1 750])
title('Ground Truth')

subplot(2,1,2)
displayWaveformLabels(signal,predictedLabels)
xlim([1 750])
title('Labeling by Network')

このフレームでは、ネットワークは良好なラベル付けを行いました。その結果、ネットワークの結果を検査する人は、予測されたラベルを少ない労力で修正できます。

ただし、ネットワークのラベル付けのパフォーマンスがそれほど高くない場合もあります。選択した 200 サンプルのデータ フレームの 6 番目を使用して取得した結果を検討します。

idx = 6;
info = ecgInfo{indexNext(idx)};
signal = QTData.Source{info.patientID}(info.channelID,info.indexID);
groundTruthLabels = ecgLabels{indexNext(idx)};
predictedLabels = currentPrediction{idx};

figure
subplot(2,1,1)
displayWaveformLabels(signal,groundTruthLabels)
xlim([1 750])
title('Ground Truth')

subplot(2,1,2)
displayWaveformLabels(signal,predictedLabels)
xlim([1 750])
title('Labeling by Network')

この信号に対するネットワークのパフォーマンスはそれほど良好ではありません。結果を検査するには、ラベル付け担当者が予測されたラベルにいくつかの修正を加えなければなりません。

200 個のデータ フレームに対する修正の労力を定量化するために、ネットワークのラベル付け誤り率、およびラベル付け担当者が修正しなければならないフレームあたりの平均サンプル数を計算します。

numSamplesPerFrame = 5000;
networkLabelingErrorRate(iteration) = 1-mean(cellfun(@(x,y)mean(x==y),currentPrediction,ecgLabels(indexNext)));
averageNumOfCorrectionsPerFrame(iteration) = networkLabelingErrorRate(iteration) * numSamplesPerFrame;
fprintf('The average number of corrections per frame is %2.1f.\n',averageNumOfCorrectionsPerFrame(iteration));
The average number of corrections per frame is 1077.4.

最初の反復では、フレームあたり平均で約 1000 個のサンプルを人が修正しなければなりません。

最初の反復の終わりでは、人が 200 個のフレームを検査し、値に誤りがあるラベルを修正することになります。ネットワークとラベル付け担当者の作業によって、反復の終了時、データ フレームには正しいラベルが付けられます。

次の反復では、新しくラベル付けされた 200 個のフレームを currentTrainingSet セットに追加して、ネットワークに再学習させ、ラベル付け反復を繰り返すことができます。次のチャートは、最初の反復後の各反復におけるワークフローを示しています。

ラベル付け反復の繰り返し

新たに修正されたラベル付きフレームを追加して学習セットを拡張し、ラベル付け対象となる別の 200 個のデータ フレームを選択し、パフォーマンスが満足できる結果になるまでラベル付け反復を繰り返します。

% Include the initial training set and the 200 newly labeled data frames
maxIter = 15;
indexTraining = 1:numInitFrames+numFrames;

networkAccuracy = zeros(1,15);
networkAccuracy(iteration) = initAccuracy;

options = trainingOptions('adam', ...
    'MaxEpochs',20, ...
    'MiniBatchSize',50, ...
    'ExecutionEnvironment','gpu', ...
    'InitialLearnRate',0.01, ...
    'LearnRateDropPeriod',6, ...
    'LearnRateSchedule','piecewise', ...
    'GradientThreshold',1, ...
    'Shuffle','every-epoch', ...
    'Plots','none', ...
    'Verbose',0);

for iteration = 2:maxIter
    % Extended training data set
    currentTrainingSet = ecgFrames(indexTraining,1);    
    % Emulate human correction by assigning ground-truth labels to the
    % extended training set
    currentTrainingLabels = ecgLabels(indexTraining);

    % Train network with extended training set
    currentNet = trainNetwork(currentTrainingSet,currentTrainingLabels,layers,options);
    
    % Predict labels for the test data set and calculate the accuracy to
    % compare to baseline performance
    currentTestSetPrediction = classify(currentNet,testFrames,'MiniBatchSize',50);
    networkAccuracy(iteration) = mean(cellfun(@(x,y)mean(x==y),currentTestSetPrediction,testLabels));
    
    % Get another numFrames data frames for human labeler
    indexNext = indexTraining(end)+1:indexTraining(end)+numFrames;
    
    % Measure average number of human corrections per frame in this iteration
    currentPrediction = classify(currentNet,ecgFrames(indexNext),'MiniBatchSize',50);
    networkLabelingErrorRate(iteration) = 1-mean(cellfun(@(x,y)mean(x==y),currentPrediction,ecgLabels(indexNext)));
    averageNumOfCorrectionsPerFrame(iteration) = networkLabelingErrorRate(iteration) * numSamplesPerFrame;
    
    indexTraining = 1:indexNext(end);
end

ラベル付けのパフォーマンス

ラベル付け反復を 15 回繰り返すと、currentTrainingSet には 2825 個のデータ フレームが存在するようになり、この個数は ecgDataset セット全体に含まれる 6543 個のデータ フレームの約半数に相当します。2825 個のフレームで学習を行ったネットワークの予測精度は、基準となる精度の約 1% にも及びません。

accuDiff = accuracyAll-networkAccuracy(end);
fprintf('The accuracy difference is %2.1f%%.\n',accuDiff*100);
The accuracy difference is 0.8%.

各反復における学習データ セットのサイズに関して、テスト データ セットに対するネットワークの予測精度をプロットします。完全にラベル付けされたデータ セットで取得した精度の上限を表示します。検証されるデータ フレーム数が増えれば、ネットワークの予測精度が向上します。

figure
examinedDataSize = 25:200:2825;
plot(examinedDataSize,networkAccuracy,'*-')
hold on
% Prediction accuracy upper bound
plot(examinedDataSize,ones(1,15)*accuracyAll,'r--')
grid on
xlabel('Training set size')
title('Accuracy for the test data set')
xlim([25 2825])
legend('Labeling Network','Upper Bound','Location','southeast')

各反復の最後では、学習データセットのサイズが大きくなるほど、フレームあたりの人による平均修正数が減少します。検証されてネットワークの学習に使用されるデータ フレームが増えれば、選択したフレームのラベル修正に必要な労力が軽減されます。最後の反復では、人による修正が必要なサンプルは、フレームあたり平均して 300 個になります。

figure
plot(examinedDataSize,averageNumOfCorrectionsPerFrame,'*-')
grid on
xlabel('Training set size')
title('Average number of human corrections per frame')
xlim([25 2825])

15 回すべてのラベル付け反復を通じて、人による修正が必要な信号サンプルは、フレームあたり平均して約 500 個になります。

fprintf('The average number of corrections per frame is %2.1f.\n',mean(averageNumOfCorrectionsPerFrame));
The average number of corrections per frame is 465.7.

まとめ

この例では、ECG データ セットの半分にラベル付けするだけで、完全にラベル付けされたデータ セットで深層ネットワークに学習させた場合と同様の予測精度が達成できることを示しました。推奨した反復ラベル付けワークフローを採用することにより、ラベル付け担当者による確認が必要なデータ セットは半分に抑えられ、修正が必要な信号サンプルはフレームあたり平均して 500 個のみになります。一方で、総当たり的なラベル付けでは、データ セット内のすべてのフレームを確認し、すべてのサンプルに対してゼロからラベル付けしなければなりません。

参考文献

[1] Goldberger, Ary L., Luis A. N. Amaral, Leon Glass, Jeffery M. Hausdorff, Plamen Ch. Ivanov, Roger G. Mark, Joseph E. Mietus, George B. Moody, Chung-Kang Peng, and H. Eugene Stanley. "PhysioBank, PhysioToolkit, and PhysioNet: Components of a New Research Resource for Complex Physiologic Signals." Circulation. Vol. 101, Number 23, 2000, pp. e215–e220. [Circulation Electronic Pages; http://circ.ahajournals.org/content/101/23/e215.full].

[2] Laguna, Pablo, Roger G. Mark, Ary L. Goldberger, and George B. Moody. "A Database for Evaluation of Algorithms for Measurement of QT and Other Waveform Intervals in the ECG."Computers in Cardiology.Vol.24, 1997, pp. 673–676.

[3] Laguna, Pablo, Raimon Jané, and Pere Caminal. "Automatic detection of wave boundaries in multilead ECG signals: Validation with the CSE database." Computers and Biomedical Research.Vol. 27, Number 1, 1994, pp. 45–60.

参考

|