ドキュメンテーション

最新のリリースでは、このページがまだ翻訳されていません。 このページの最新版は英語でご覧になれます。

深層学習を使用した波形セグメンテーション

この例は、再帰型深層学習ネットワークと時間-周波数解析を使用して、人間の心電図 (ECG) 信号をセグメント化する方法を説明します。

はじめに

心臓の電気的活動は、ベースライン信号から離れた一連の振幅として測定できます。単一の正常な心拍サイクルの場合、ECG 信号は次の心拍形態に分けられます [1]。

  • P 波 — QRS 群が心房性脱分極を表す前の小さいたわみ

  • QRS 群 — 心拍の最大振幅部分

  • T 波 — QRS 群が心室再分極を表した後の小さいたわみ

ECG 波形のこれらの領域のセグメンテーションでは、人間の心臓全体の健康状態と異常の存在を評価するのに役立つ測定値の基準を提供できます [2]。手動で ECG 信号の各領域に注釈を付けると、手間と時間がかかるタスクになり、信号処理方法と機械学習方法によって自動化される可能性があります。

この例は、一般に使用できる QT データベースからの ECG 信号を使用します [3] [4]。データは、合計 105 人の患者からの約 15 分間の ECG の記録で構成されています。各記録を取得するために、検査員は患者の胸部の異なる場所に 2 つの電極を配置して、2 チャネル信号にします。データベースは、自動化されたエキスパート システムによって生成される信号領域ラベルを提供します [2]。この例は、深層学習の解を使用して、サンプルがある領域に応じて各サンプルにラベルを付けることを目的としています。信号に対して関心領域をラベル付けするこのプロセスは、多くの場合波形セグメンテーションと呼ばれます。

信号領域を分類するよう深層ニューラル ネットワークに学習させるために、長短期記憶 (LSTM) ネットワークを使用できます。この例は、 LSTM セグメンテーション性能を向上させるために信号前処理技術と時間-周波数解析をどのように使用できるかを示します。特に、例は、フーリエ シンクロスクイーズド変換を使用して、ECG 信号の非定常動作を表しています。

データのダウンロードと準備

最初のステップは、GitHub リポジトリからデータをダウンロードすることです。すべてのブラウザーには設定を介して特定できるダウンロード ディレクトリがあります。そのディレクトリにあるファイル QT_Database-master.zip を見つけて、書き込み権限のあるフォルダーに移動します。この例では、一時ディレクトリにファイルを配置していて、その場所は MATLAB® の tempdir コマンドによって指定されると仮定しています。tempdir と異なるフォルダーにデータがある場合、それ以降の手順でディレクトリ名を変更してください。まず、データ ファイルを解凍します。

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

解凍すると、一時ディレクトリにフォルダー QT_Database-master が作成されます。このフォルダーには、テキスト ファイル README.md と次のファイルが含まれます。

  • QTData.mat

  • Modified_physionet_data.txt

  • License.txt

QTData.mat にはこの例で使用されるデータが含まれます。ファイル Modified_physionet_data.txt は、データ用のソース属性と、生の ECG 記録ごとに適用される操作の説明を提供します。

load(fullfile(tempdir,'QT_Database-master','QTData.mat'))
QTData
QTData = 
  labeledSignalSet with properties:

             Source: {105×1 cell}
         NumMembers: 105
    TimeInformation: "sampleRate"
         SampleRate: 250
             Labels: [105×2 table]
        Description: ""

 Use labelDefinitionsHierarchy to see a list of labels and sublabels.
 Use setLabelValue to add data to the set.

QTData は、単一のオブジェクトに、ソースの ECG 信号と対応する波形ラベルを一緒に保持するlabeledSignalSetです。105 個の 2 チャネルの ECG 信号は Source プロパティに含まれます。Labels プロパティには、波形ラベルのテーブルが含まれます。各チャネルは、自動化されたエキスパート システムによってそれぞれラベル化され、合計 210 個の ECG 信号に対して個別に扱われます。波形ラベルは、次のクラス P、QRS、T、および N/A のいずれかに属するものとして、信号の各サンプルを指定します。N/A の値は、P 波、QRS 群、または T 波以外のサンプルに対応します。

head コマンドを使用して、QTDataLabels プロパティに含まれるテーブルの最初の数行を検査します。

head(QTData.Labels)
ans=8×2 table
                 WaveformLabels_Chan1    WaveformLabels_Chan2
                 ____________________    ____________________

    Member{1}      [225000×2 table]        [225000×2 table]  
    Member{2}      [225000×2 table]        [225000×2 table]  
    Member{3}      [225000×2 table]        [225000×2 table]  
    Member{4}      [225000×2 table]        [225000×2 table]  
    Member{5}      [225000×2 table]        [225000×2 table]  
    Member{6}      [225000×2 table]        [225000×2 table]  
    Member{7}      [225000×2 table]        [225000×2 table]  
    Member{8}      [225000×2 table]        [225000×2 table]  

各テーブル行は患者に対応し、各テーブル列はチャネルに対応します。getSignal 関数を使用して、最初の患者の単一のデータを抽出します。getLabelValues 関数を使用して、最初のチャネルのラベルを抽出します。displayWaveformLabels 補助関数を使用して、最初の 1000 個のサンプルのラベルを可視化します。

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

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

150 番目あたりのサンプルのラベル値を検査します。ここで信号は急速に変化します。領域は、QRS 群の最後と N/A サンプルへの遷移をマークします。

val = labelVals.Value(145:155)
val = 11×1 categorical array
     QRS 
     QRS 
     QRS 
     QRS 
     QRS 
     QRS 
     QRS 
     QRS 
     n/a 
     n/a 
     n/a 

通常の機械学習の分類手順は次のとおりです。

  1. データベースを学習データセットとテスト データセットに分割します。

  2. 学習データセットを使用してネットワークに学習させます。

  3. 学習済みのネットワークを使用して、テスト データセットについて予測を行います。

ネットワークをデータの 70% で学習し、残りの 30% でテストします。バイアスを防ぐために、同じ患者に属するデータは学習セットとテスト セット間で共有されません。

再現可能な結果が必要な場合は、乱数発生器をリセットします。labeledSignalSetNumMembers プロパティを使用して、患者の数を抽出します。dividerand 関数を使用して患者をシャッフルし、subset 関数を使用してデータを学習とテストの labeledSignalSet に分割します。

rng default
[trainInd,~,testInd] = dividerand(QTData.NumMembers,0.7,0,0.3);

trainQT = subset(QTData,trainInd);
testQT = subset(QTData,testInd);

ネットワークに時系列データを入力するには、補助関数 resizeSignals を使用して行列の cell 配列としてデータを整理します。さらに、この補助関数は、メモリ使用量が過度になるのを防ぐためにデータを 5000 サンプルのチャンクに分割します。

[signalsTrain,labelsTrain] = resizeSignals(trainQT);
[signalsTest,labelsTest] = resizeSignals(testQT);

生の ECG 信号の LSTM ネットワークへの直接入力

最初に、学習データセットからの生の ECG 信号を使用してネットワークを学習させます。

学習前のネットワーク アーキテクチャを定義します。サイズ 1 の sequenceInputLayer を指定して、1 次元の時系列を受け入れます。'sequence' 出力モードで LSTM 層を指定して、信号の各サンプルに対して分類できるようにします。最適なパフォーマンスを得るために 200 個の非表示ノードを使用します。出力サイズが 4 の fullyConnectedLayer を波形クラスごとに 1 つ指定します。softmaxLayerclassificationLayer を追加して、推定ラベルを出力します。

layers = [ ...
    sequenceInputLayer(1)
    lstmLayer(200,'OutputMode','sequence')
    fullyConnectedLayer(4)
    softmaxLayer
    classificationLayer];

適切なネットワーク性能を確認する学習プロセスに対するオプションを選択します。各パラメーターの説明については、trainingOptionsのドキュメンテーションを参照してください。

options = trainingOptions('adam', ...
    'MaxEpochs',10, ...
    'MiniBatchSize',50, ...
    'InitialLearnRate',0.01, ...
    'LearnRateDropPeriod',3, ...
    'LearnRateSchedule','piecewise', ...
    'GradientThreshold',1, ...
    'Plots','training-progress',...
    'Verbose',0);

ネットワークの学習

trainNetwork コマンドを使用して LSTM ネットワークを学習させます。データセットのサイズが大きいため、このプロセスには数分かかる場合があります。マシンに GPU と Parallel Computing Toolbox™ がある場合は、MATLAB は学習に GPU を自動で使用します。そうでない場合は CPU が使用されます。

図の学習の精度と損失のサブプロットは、すべての反復回数間の学習の進行状況を追跡します。生の信号データを使用して、ネットワークは、P 波、QRS 群、T 波、または N/A に属するものとして、サンプルの約 70% を正しく分類します。

net = trainNetwork(signalsTrain,labelsTrain,layers,options);

テスト データの分類

学習済み LSTM ネットワークと classify コマンドを使用してテスト データを分類します。学習オプションを一致させるためにミニバッチのサイズ 50 を指定します。

predTest = classify(net,signalsTest,'MiniBatchSize',50);

混同行列では、分類性能を可視化するための直感的で有益な方法を提供しています。confusionchart コマンドを使用して、テスト データ予測に対する全体の分類精度を計算します。各入力に対して、categorical ラベルの cell 配列を行ベクトルに変換します。列を正視化した表示を指定して、各クラスのサンプルの割合として結果を表示します。

confusionchart([predTest{:}],[labelsTest{:}],'Normalization','column-normalized');

ネットワークへの入力として生の ECG 信号を使用すると、P 波のサンプルの約 35%、QRS 群のサンプルの 60%、T 波のサンプルの 60% のみが正しくなります。パフォーマンスを向上させるには、深層学習のネットワークに入力する前に ECG 信号の特性の情報を適用します。たとえば、患者の呼吸の動きによって引き起こされる基線変動です。

フィルター処理方法の適用による基線変動と高周波ノイズの除去

3 つの心拍形態は、異なる周波数バンドを占めます。QRS 群のスペクトルには一般的に、10 ~ 25 Hz あたりの中心周波数があり、そのコンポーネントは 40 Hz 未満にあります。P 波と T 波は低周波でも起こります。P 波のコンポーネントは 20 Hz 未満で、T 波のコンポーネントは 10 Hz 未満です [5]。

基線変動は、患者の呼吸の動きによって引き起こされる低周波数 (< 0.5 Hz) の振動です。この振動は、心拍形態から独立していて、有効な情報を提供しません [6]。

[0.5, 40] Hz の通過帯域周波数幅を持つバンドパス フィルターを設計して、変動と高周波ノイズを削除します。これらのコンポーネントを削除すると、ネットワークが関係のない特徴を学習しないため LSTM 学習が向上します。

Fs = QTData.SampleRate;
[~,dBP] = bandpass(signalsTrain{1},[0.5 40],Fs);

無名関数 BPfun を指定して、各信号にバンドパス フィルターを適用します。

BPfun = @(X) filter(dBP,X);

signalsFilteredTrain = cellfun(BPfun,signalsTrain,'UniformOutput',false);
signalsFilteredTest  = cellfun(BPfun,signalsTest,'UniformOutput',false);

一般的なケースの生の信号とフィルター処理した信号をプロットします。

subplot(2,1,1)
plot(signalsTrain{210}(2001:3000))
title('Raw')
grid

subplot(2,1,2)
plot(signalsFilteredTrain{210}(2001:3000))
title('Filtered')
grid

フィルター済み ECG 信号を使用したネットワークの学習

同じネットワークのアーキテクチャを使用してフィルター済み ECG 信号で LSTM ネットワークを学習します。

filteredNet = trainNetwork(signalsFilteredTrain,labelsTrain,layers,options);

信号の前処理は 80% 以上まで学習精度を向上させます。

フィルター処理された ECG 信号の分類

前処理済みテスト データを更新した LSTM ネットワークで分類します。

predFilteredTest = classify(filteredNet,signalsFilteredTest,'MiniBatchSize',50);

混同行列として分類性能を可視化します。

figure
confusionchart([predFilteredTest{:}],[labelsTest{:}],'Normalization','column-normalized');

シンプルな前処理で、P 波の分類が約 10%、QRS 群の分類が 10%、および T 波の分類が 20% 向上します。

ECG 信号の時間-周波数の表現

時系列データの正常な分類に対する共通アプローチは、時間-周波数の特徴を抽出し、それらを元のデータの代わりにネットワークに供給することです。その後、ネットワークは、時間と周波数間で同時にパターンを学習します [7]。

フーリエ シンクロスクイーズド変換 (FSST) で、信号サンプルごとに周波数スペクトルを計算します。fsst 関数を使用して、学習信号の 1 つの変換を検査します。適切な周波数分解能を与えるために、長さが 128 のカイザー ウィンドウを指定します。

fsst(signalsTrain{1},Fs,kaiser(128),'yaxis')

学習データセットの各信号の FSST を計算します。変換出力からの関連コンテンツをインデックス化して、対象の周波数範囲 [0.5, 40] Hz 間のデータを抽出します。個別の機能として FSST の実数部と虚数部を取り扱い、ネットワークに両方のコンポーネントを供給します。

ネットワークを学習する前に、平均を減算し、標準偏差で除算することで、学習用の特徴を標準化します。

signalsFsstTrain = cell(size(signalsTrain));
meanTrain = cell(1,length(signalsTrain));
stdTrain = cell(1,length(signalsTrain));
for idx = 1:length(signalsTrain)
   [s,f,t] = fsst(signalsTrain{idx},Fs,kaiser(128));
   
   f_indices = (f > 0.5) & (f < 40);
   signalsFsstTrain{idx}= [real(s(f_indices,:)); imag(s(f_indices,:))];
   
   meanTrain{idx} = mean(signalsFsstTrain{idx},2);
   stdTrain{idx} = std(signalsFsstTrain{idx},[],2);
end

standardizeFun = @(x) (x - mean(cell2mat(meanTrain),2))./mean(cell2mat(stdTrain),2);
signalsFsstTrain = cellfun(standardizeFun,signalsFsstTrain,'UniformOutput',false);

テスト データに対してこの手順を繰り返します。学習データからの平均と標準偏差を使用してテスト用の特徴を標準化します。

signalsFsstTest = cell(size(signalsTest));
for idx = 1:length(signalsTest)
   [s,f,t] = fsst(signalsTest{idx},Fs,kaiser(128));
   
   f_indices =  (f > 0.5) & (f < 40);
   signalsFsstTest{idx}= [real(s(f_indices,:)); imag(s(f_indices,:))]; 
end

signalsFsstTest = cellfun(standardizeFun,signalsFsstTest,'UniformOutput',false);

ネットワーク アーキテクチャの調整

ネットワークが単一の値の代わりに各サンプルに周波数スペクトルを受け入れるように LSTM アーキテクチャを変更します。FSST のサイズを検査し、周波数の数値を確認します。

size(signalsFsstTrain{1})
ans = 1×2

          40        5000

入力の特徴を 40 として sequenceInputLayer に指定します。残りのネットワーク パラメーターは変更しないで保持します。

layers = [ ...
    sequenceInputLayer(40)
    lstmLayer(200,'OutputMode','sequence')
    fullyConnectedLayer(4)
    softmaxLayer
    classificationLayer];

ECG 信号の FSST を使用したネットワークの学習

変換されたデータセットを使用して更新された LSTM ネットワークに学習をさせます。

fsstNet = trainNetwork(signalsFsstTrain,labelsTrain,layers,options);

時間-周波数の特徴を使用すると学習精度が改善します。現在、90% を超えています。

FSST を使用したテスト データの分類

更新された LSTM ネットワークと抽出された FSST の特徴を使用して、テスト データを分類します。

predFsstTest = classify(fsstNet,signalsFsstTest,'MiniBatchSize',50);

混同行列として分類性能を可視化します。

confusionchart([predFsstTest{:}],[labelsTest{:}],'Normalization','column-normalized');

時間-周波数表現を使用すると、P 波の分類が 50% (約 35% から 85% まで)、QRS 群の分類が 35%、および T 波の分類が 25% 向上します。

displayWaveformLabels を使用して、ネットワーク予測を単一の ECG 信号のグラウンド トゥルース ラベルと比較します。

subplot(2,1,1)
displayWaveformLabels(signalsTest{50}(1400:1900),labelsTest{50}(1400:1900))
title('Ground Truth')

subplot(2,1,2)
displayWaveformLabels(signalsTest{50}(1400:1900),predFsstTest{50}(1400:1900))
title('Predicted')

まとめ

この例は、信号の前処理と時間-周波数解析が LSTM 波形セグメンテーション性能を向上させることができる方法を説明しています。バンドパス フィルターとフーリエ ベースのシンクロスクイージングによって、すべての出力クラス間の平均が 60% から 85% 以上まで改善されます。

参照

[1] McSharry, Patrick E., et al. "A dynamical model for generating synthetic electrocardiogram signals."IEEE® Transactions on Biomedical Engineering.Vol. 50, No. 3, 2003, pp. 289–294.

[2] 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, No. 1, 1994, pp. 45–60.

[3] 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, No. 23, 2000, pp. e215–e220.[Circulation Electronic Pages; http://circ.ahajournals.org/content/101/23/e215.full].

[4] 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.

[5] Sörnmo, Leif, and Pablo Laguna."Electrocardiogram (ECG) signal processing."Wiley Encyclopedia of Biomedical Engineering, 2006.

[6] Kohler, B-U., Carsten Hennig, and Reinhold Orglmeister."The principles of software QRS detection."IEEE Engineering in Medicine and Biology Magazine.Vol. 21, No. 1, 2002, pp. 42–57.

[7] Salamon, Justin, and Juan Pablo Bello."Deep convolutional neural networks and data augmentation for environmental sound classification."IEEE Signal Processing Letters.Vol. 24, No. 3, 2017, pp. 279–283.

参考

関数

関連するトピック