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

信号ラベラー

解析または機械学習や深層学習の各アプリケーションの信号のラベル付け

説明

信号ラベラーは、解析のため、または機械学習と深層学習のアプリケーションで使用するために信号のラベル付けが可能な対話型のツールです。信号ラベラーを使用して、次のことができます。

  • 属性、領域、および関心点をもつ信号のラベル付け

  • logical、categorical、numerical、または string の値が付いたラベルの使用

  • 信号ピークの自動ラベル付けまたはカスタム ラベル付け関数の適用

  • ラベルまたはサブラベルの追加、編集、および削除

  • 信号とラベルの選択されたサブセットの表示

信号ラベラーは、データを信号アナライザーlabeledSignalSet オブジェクトとして保存します。labeledSignalSet オブジェクトを使用して、ネットワーク、分類器を学習させるか、データを解析して統計をレポートできます。

信号ラベラー を開く

信号アナライザー アプリの [アナライザー] タブで、[ラベル] をクリックします。

すべて展開する

クジラの歌の録音にはふるえ声とうめき声が含まれます。"ふるえ声" の音声は一連のクリックに似ています。"うめき声" は、船の警笛による音声に似た低周波数の鳴き声です。各信号を確認してラベルを付けて、クジラの種類、ふるえ声の領域、およびうめき声の領域を識別します。また、ふるえ声の各領域では、いくつかの選択された信号ピークにラベルを付けます。

ラベル付けされていないデータの読み込み

クジラの歌の 2 つの記録を含むデータセットを読み込むことから開始します。信号は whale1whale2 と呼ばれ、4 kHz でサンプリングされます。whale1 は 1 つのふるえ声と、その後 3 つのうめき声で構成されます。whale2 は 2 つのうめき声、1 つのふるえ声、および別のうめき声で構成されます。

load labelwhalesignals

% To hear, type soundsc(whale1,Fs), pause(22), soundsc(whale2,Fs)

信号ラベラーに信号を移動します。

  1. 信号アナライザーを開始して、信号を信号テーブルにドラッグします。

  2. 信号を選択して時間情報を追加します。[アナライザー] タブで [時間値] をクリックし、Sample Rate and Start Time を選択して、サンプルレート Fs を入力します。

  3. 信号を選択して、[アナライザー] タブの [ラベル] をクリックします。

信号ラベル定義の追加

ラベルを定義して、信号に付加します。ラベルは次の 3 つのタイプです。

  • "属性" ラベルは信号の特性を定義します。

  • "関心領域" (ROI) ラベルは関心領域上の信号特性を定義します。

  • "点" ラベルは関心点での信号特性を定義します。

各ラベルは 4 つのデータ型のうち 1 つをもつことができます。

  • logical ラベルは、true または false のいずれかです。

  • categorical ラベルは、指定するカテゴリ セットの 1 つに属します。

  • 数値 ラベルは任意の数値をもちます。

  • string ラベルは文字列で表される任意の値をもちます。

ラベルは任意の数の "サブラベル" をもちます。サブラベル自体がサブラベルをもつことはできません。

クジラの歌の信号の場合:

  1. クジラの種類を格納する categorical 属性ラベルを定義します。これを WhaleType とします。使用するカテゴリは、シロナガスクジラ、ザトウクジラ、およびシロイルカです。

  2. うめき声の領域に対して true である logical の関心領域 (ROI) ラベルを定義します。これを MoanRegions とします。

  3. ふるえ声の領域に対して true である logical の (ROI) ラベルを定義します。これを TrillRegions とします。

  4. ふるえ声のピークを取得するための数値の点ラベルを定義します。これを TrillPeaks とします。このラベルは、TrillRegions ラベルのサブラベルとして設定します。

各ラベルを定義するには、[ラベル] タブの [ラベルの追加] をクリックします。サブラベルを定義するには、[ラベル定義] ブラウザーの TrillRegions ラベルを選択し、[定義の追加] ▼ をクリックして Add sublabel definition を選択します。

各信号ラベルまたはサブラベル定義に表示するダイアログ ボックスのフィールドに次の値を入力します。それぞれの場合で [既定の設定] フィールドを空のままにします。

LabelNameLabelTypeLabelDescriptionDataTypeCategoriesWhaleTypeAttributeWhaletypecategorical{bluehumpbackwhiteMoanRegionsROIRegionswheremoansoccurlogical---TrillRegionsROIRegionswheretrillsoccurlogical---TrillPeaksPointTrillpeaksnumeric---

[エクスポート] をクリックして、MAT ファイルに作成した信号定義をエクスポートできます。ファイル名に入力するためのダイアログ ボックスが表示されます。どの時点でも、[インポート] をクリックして、MAT ファイルに保存された信号定義をインポートできます。

信号属性のラベル付け

データの歌は、2 頭のシロナガスクジラのものです。両方の信号に WhaleType 値を設定します。

  1. [ラベルの定義] ブラウザーで WhaleType を選択します。

  2. [ラベル] ▼ をクリックし、Label Signals を選択します。

  3. 表示されるダイアログ ボックスで、whale1whale2 の両方が選択されて、[値] フィールドが blue に設定されていることを確認します (categorical 信号ラベル定義で既定値を指定しない場合、信号ラベラーは定義で指定された最初のカテゴリにラベルを設定します)。

  4. [OK] をクリックします。

名前の隣にあるチェック ボックスを選択して whale1 信号をプロットします。[ラベル付き信号セット] ブラウザー内とタイム プロットの両方で信号属性が表示されます。

信号領域のラベル付け

クジラの歌を可視化して、ふるえ声とうめき声の領域をラベル付けします。

  • ふるえ声の領域にはサイレンスで区切られた異なるバーストの音声があります。whale1 には約 2 秒で中央揃えされたふるえ声があります。

  • うめき声の領域は持続した低周波数のうめき声です。whale1 には約 7 秒、12 秒、17 秒で中央揃えされたうめき声があります。

一度に 1 つずつ信号をラベル付け

  1. [ラベル付き信号セット] ブラウザーの [プロット] 列で、信号名の隣のボックスをオンにして、信号をプロットします。

  2. うめき声をラベル付けするには、[ラベルの定義] ブラウザーで、MoanRegions のラベル定義を選択します。

  3. [ラベル] ▼ をクリックし、Label Plotted を選択します。アニメーションの破線によってフレーム化された、影付き領域が表示されます (アニメーション フレームは、領域が "アクティブ" であることを示します)。うめき声の領域を囲むまでアクティブな領域を移動してサイズ変更します。ラベルを適切に配置するには、[表示] タブに移動して、ズーム操作を選択するかパナーを有効にします。

  4. [ラベル] ボタンの横にあるチェック マークをクリックして、Enter キーを押すか、ダブルクリックして ROI をラベル付けします。領域は信号の色のグラデーションに変わります。論理ラベル定義で既定値を指定しない場合、信号ラベラーはラベルを true に設定します。

  5. 他の 2 つのうめき声に対して手順を繰り返します。

  6. ふるえ声をラベル付けするには、[ラベルの定義] ブラウザーで、TrillRegions ラベル定義を選択します。ステップ 3 と 4 を使用して、ふるえ声の領域をラベル付けします。

  7. 2 番目のクジラの歌の信号をラベル付けする前に、[ラベル付き信号セット] ブラウザーで名前の横にあるチェック ボックスをオフにしてプロットから最初のクジラの歌の信号を削除します。領域または点をラベル付けするときにプロットされた信号が 2 つある場合、信号ラベラーは両方の信号でラベルを関連付けます。

ラベル ビューアーの座標軸は関心領域の位置と幅を示します。各領域に割り当てられた値も表示します。

信号点のラベル付け

ふるえ声の領域には音声のバーストに対応する明確なピークがあります。ふるえ声の各領域の 3 つのピークにラベルを付けます。ふるえ声のピークはサブラベルのため、それぞれが特定の TrillRegions ラベルに関連付けられていなければなりません。

一度に 1 つずつ信号をラベル付け

  1. [ラベル付き信号セット] ブラウザーの [プロット] 列で、信号名の隣のボックスをオンにして、信号をプロットします。また、ピークをラベル付けするふるえ声の領域に対応するボックスをオンにします。

  2. [ラベルの定義] ブラウザーで、TrillPeaks を選択します。

  3. ツールストリップで、[値] に、最初のピークに対応する「1」と入力します。

  4. [ラベル付き信号セット] ブラウザーで、ふるえ声の領域を選択します。ふるえ声の領域がアクティブになり、アニメーションの破線でフレーム化されます。

  5. [ラベル] ▼ をクリックし、Label Plotted を選択します。ふるえ声の領域は実線によってフレーム化され、アニメーションの破線 (アクティブな線) がラベル付けされている点に対して表示されます。

  6. 選択したピークで信号が交差するまでアクティブな線を移動します。ラベルを適切に配置するには、[表示] タブに移動して、ズーム操作を選択するかパナーを有効にします。

  7. [ラベル] ボタンの横にあるチェック マークをクリックして、Enter キーを押すか、ダブルクリックしてピークをラベル付けします。破線が信号と同じ色の実線に変わります。

  8. 2」と「3」を入力してさらに 2 つのピークを繰り返し、識別します。

  9. 2 番目のクジラの歌の信号のふるえ声のピークをラベル付けする前に、[ラベル付き信号セット] ブラウザーの名前の横にあるチェック ボックスをオフにしてプロットから最初のクジラの歌の信号を削除します。

ラベル ビューアーの座標軸は、関心点の位置と各位置に割り当てられた値を示します。

2 つの信号をプロットして、ラベル ビューアーでラベルの概要を参照します。[ラベル付き信号セット] ブラウザーのラベル付き信号セット階層を展開して、すべてのラベルの詳細を参照します (階層を展開するには、ブラウザーの任意の信号を右クリックし、Expand All を選択します)。それぞれの信号に対して、最初のうめき声の領域と、ラベル付けした 3 つ目のふるえ声のピークをプロットします。

信号のラベル値の編集

任意の時点で、[ラベル付き信号セット] ブラウザーを使用して、任意の信号ラベルを編集できます。属性ラベルを編集するには、選択して右クリックし、[編集] を選択します。たとえば、2 番目のクジラが実際にシロイルカであることを検出した場合、whale2WhaleType 属性を選択して、右クリックし、[編集] を選択して、表示されるダイアログ ボックスのドロップダウン メニューから white を選択します。

ROI ラベルまたは点ラベルの値を編集する場合は、ダイアログ ボックスで値を変更できます。ROI ラベルまたは点ラベルの位置を変更するには、ダイアログ ボックスで位置フィールドを変更できます。または、以下が可能です。

  1. 名前の隣にあるボックスをオンにしてラベルをプロットします。

  2. ラベルを選択します。

  3. アクティブになるときに時間プロットの領域または点を移動します。

ラベル付き信号セットのエクスポート

ラベル付けの保存と新しい labeledSignalSet オブジェクトのエクスポートによってラベル付けした信号をエクスポートします。ツールストリップで [ラベルを保存] ボタンをクリックします。表示されるダイアログ ボックスで、ラベル付き信号セットに名前 whalesongs を指定します。[OK] ボタンをクリックすると、信号アナライザーに戻ります。信号ラベラーでラベル付き信号セットをエクスポートする方法の詳細については、信号ラベラーによる動作のインポートとエクスポートを参照してください。

信号テーブルで、whalesongs を選択して右クリックし、Whale_Songs.mat と呼ばれるファイルにエクスポートします。

信号属性、関心領域、および点のラベル付けの例で作成した MAT ファイルを MATLAB® ワークスペースに読み込みます。ラベル付き信号セットに信号ラベラーを使用して追加した定義が含まれていることを確認します。

load Whale_Songs

labelDefinitionsSummary(whalesongs)
ans=3×9 table
      LabelName        LabelType     LabelDataType     Categories     ValidationFunction    DefaultValue             Sublabels             Tag            Description         
    ______________    ___________    _____________    ____________    __________________    ____________    ___________________________    ___    ____________________________

    "WhaleType"       "attribute"    "categorical"    {3x1 string}       {["N/A"   ]}       {0x0 double}    {0x0 double               }    ""     "Whale type"                
    "MoanRegions"     "roi"          "logical"        {["N/A"   ]}       {0x0 double}       {0x0 double}    {0x0 double               }    ""     "Regions where moans occur" 
    "TrillRegions"    "roi"          "logical"        {["N/A"   ]}       {0x0 double}       {0x0 double}    {1x1 signalLabelDefinition}    ""     "Regions where trills occur"

TrillPeaksTrillRegions のサブラベルであることを確認します。

labelDefinitionsHierarchy(whalesongs)
ans = 
    'WhaleType
       Sublabels: []
     MoanRegions
       Sublabels: []
     TrillRegions
       Sublabels: TrillPeaks
     '

セットの 2 番目のメンバーを取得します。timetable 変数の名前を取得します。

song = getSignal(whalesongs,2);

summary(song)
RowTimes:

    Time: 76579x1 duration
        Values:
            Min           0 sec       
            Median        9.5722 sec  
            Max           19.144 sec  
            TimeStep      0.00025 sec 

Variables:

    whale2: 76579x1 double

        Values:

            Min       -0.37326
            Median           0
            Max        0.37914

信号をプロットします。

t = song.Time;
sng = song.whale2;

plot(t,sng)

ラベル付けされた領域の可視化

ラベル付けした関心領域を表示および特定します。詳細については、例の最後の関数 labelIntervals のコードを参照してください。

mvals = getLabelValues(whalesongs,2,'MoanRegions');
tvals = getLabelValues(whalesongs,2,'TrillRegions');

cmap = lines;

hold on

tmoan = mvals.ROILimits;
for kj = 1:size(tmoan,1)
    tv = find(seconds(t)>tmoan(kj,1) & seconds(t)<tmoan(kj,2));
    plot(t(tv),sng(tv),'Color',cmap(2,:))
end

ttrill = tvals.ROILimits;
for kj = 1:size(ttrill,1)
    tv = find(seconds(t)>ttrill(kj,1) & seconds(t)<ttrill(kj,2));
    plot(t(tv),sng(tv),'Color',cmap(3,:))
end

labelIntervals(mvals,tvals,cmap(4,:))

hold off

ラベル付けされた点の可視化

ラベル付けしたふるえ声のピークを表示および特定します。

pk = getLabelValues(whalesongs,2,{'TrillRegions','TrillPeaks'});

locs  = zeros(size(pk,1),1);
for kj = 1:length(locs)
    locs(kj) = find(seconds(t) == pk.Location(kj));
end

hold on
plot(t(locs),sng(locs)+0.01,'v','MarkerSize',8,'Color',[0.929,0.694,0.125])
text(t(locs)+seconds(0.2),sng(locs)+0.05,int2str(cell2mat(pk.Value)), ...
    'HorizontalAlignment','center')
hold off

補助関数によって、関心領域が表示および特定されます。

function labelIntervals(mvals,tvals,clr)
    [X,Y] = meshgrid(seconds([mvals.ROILimits;tvals.ROILimits]),ylim);
    plot(X,Y,':k')
    topts = {'HorizontalAlignment','center','FontWeight','bold', ...
        'FontSize',12,'Color',clr};
    text((X(1,1:4)+X(1,5:end))/2,Y(2,5:end)-0.1, ...
        ["moan" "moan" "moan" "trill"],topts{:})
end

この例では、信号ラベラーのカスタム自動ラベル付け関数を使用して、心電図 (ECG) 信号の QRS 群と R ピークにラベル付けする方法を示します。1 つのカスタム関数は、以前に学習済みの再帰型深層学習ネットワークを使用し、QRS 群を特定して検索します。もう 1 つのカスタム関数は、単純なピークの検索を使用して R ピークを検索します。この例では、ネットワークは、ネットワークの学習とテストのプロセスから完全に独立した 2 つの信号の QRS 群にラベル付けします。

ECG 波形の 3 つの偏位で構成される QRS 群は、心臓の左右の心室の脱分極を反映しています。また、QRS は人間の心拍の最大振幅セグメントでもあります。QRS 群の調査は、人の心臓の全体的な健康状態と異常の有無を評価するために役立ちます [1]。特に、QRS 群内の R ピークを検出し、連続するピークの時間間隔を調べることで、診断医は患者の心拍変動を計算して、心不整脈を見つけることができます。

この例の深層学習ネットワークは深層学習を使用した波形セグメンテーションで導入されており、公開されている QT データベースの ECG 信号を使用して学習させています [2] [3]。データは、合計 105 人の患者からの約 15 分間の ECG の記録で構成され、250 Hz でサンプリングされています。各記録を取得するために、検査員は患者の胸部の異なる場所に 2 つの電極を配置して、2 チャネル信号にしています。データベースは、自動化されたエキスパート システムによって生成される信号領域ラベルを提供します [1]。追加されたラベルにより、深いネットワークの学習にデータを使用できるようになっています。詳細は、深層学習を使用した波形セグメンテーションを参照してください。

信号ラベラーへのデータの読み込み、リサンプリング、およびインポート

この例では、MIT-BIH Arrhythmia Database の信号をラベル付けします [4]。データベース内の各信号は 360 Hz でサンプリングされ、2 人の心臓専門医によって注釈が付けられ、結果の検証が可能になっています。

記録 200 および 203 に対応する 2 つの MIT データベース信号を読み込みます。信号を QT データベース データのサンプルレートである 250 Hz にリサンプリングします。

load mit200
y200 = resample(ecgsig,25,36);

load mit203
y203 = resample(ecgsig,25,36);

信号アナライザーを起動して、信号テーブルに信号をドラッグします。信号を選択します。時間情報を追加します。[アナライザー] タブで [時間値] をクリックし、Sample Rate and Start Time を選択して、サンプルレートとして 250 Hz を指定します。[アナライザー] タブの [ラベル] をクリックします。[ラベル付き信号セット] ブラウザーに信号が表示されます。

ラベルの定義

ラベルを定義して、信号に付加します。

  1. QRS 群のカテゴリカル関心領域 (ROI) ラベルを定義します。[ラベル] タブの [定義の追加] をクリックします。[ラベル名] として QRSregions を指定し、[ラベル タイプ]ROI を選択して、[データ型] として categorical と入力し、2 つの [カテゴリ]QRS および n/a を 1 行に 1 つずつ追加します。

  2. R ピークの数値の点ラベルを定義し、QRSregions のサブラベルとして設定します。[ラベルの定義] ブラウザーで QRSregions をクリックして選択します。[定義の追加] ▼ をクリックし、Add sublabel definition を選択します。[ラベル名]Rpeaks を指定して、[ラベル タイプ]Point を選択し、[データ型] として numeric と入力します。

カスタム自動ラベル付け関数の作成

2 つのカスタム関数を作成します。1 つは QRS 群を検索してラベル付けし、もう 1 つは各 QRS 群内の R ピークを検索してラベル付けします。(関数 findQRScomputeFSSTp2qrs、および findRpeaks のコードは、後ほどこの例で示します)。各関数を作成するために、[アナライザー] タブの [値の自動処理] ▼ をクリックして、[カスタム関数の追加] を選択します。信号ラベラーにより、追加する関数の名前、説明、およびラベル タイプを求めるダイアログ ボックスが表示されます。

  1. QRS 群を検索する関数については、名前フィールドに findQRS と入力し、[ラベル タイプ] として ROI を選択します。説明フィールドは空のままにすることも、独自の説明を入力することもできます。

  2. R ピークを検索する関数については、名前フィールドに findRpeaks と入力し、[ラベル タイプ] として Point を選択します。説明フィールドは空のままにすることも、独自の説明を入力することもできます。

関数を書き込み済みでその関数が現在のフォルダーまたは MATLAB® パスにある場合、信号ラベラーはその関数をギャラリーに追加します。関数をまだ書き込んでいない場合、コードの入力または貼り付けができるように、信号ラベラーはエディターで空白のテンプレートを開きます。ファイルを保存します。関数がギャラリーに表示されます。

QRS 群と R ピークのラベル付け

入力信号の QRS 群を見つけてラベル付けします。

  1. [ラベル付き信号セット] ブラウザーで、y200 の横にあるチェック ボックスをオンにします。

  2. [ラベルの定義] ブラウザーで QRSregions を選択します。

  3. [値の自動処理] ギャラリーで、findQRS を選択します。

  4. [自動ラベル付け] をクリックし、表示されたダイアログ ボックスで [OK] をクリックします。

信号ラベラーは、すべての信号の QRS 群を検索してラベル付けしますが、チェック ボックスをオンにした信号の QRS 群のみを表示します。QRS 群が、プロットとラベル ビューアーの座標軸に影付きの領域として表示されます。[表示] タブの [パナー] をクリックしてパナーをアクティブにし、ラベル付き信号の領域を拡大します。

QRS 群に対応する R ピークを見つけてラベル付けします。

  1. [ラベルの定義] ブラウザーで Rpeaks を選択します。

  2. [ラベル] タブに戻ります。[値の自動処理] ギャラリーで、findRpeaks を選択します。

  3. [自動ラベル付け] をクリックし、表示されたダイアログ ボックスで [OK] をクリックします。

ラベルとその数値が、プロットとラベル ビューアーの座標軸に表示されます。

ラベル付き信号のエクスポートと心拍変動の計算

ラベル付き信号をエクスポートして、各患者の心拍変動を比較します。[ラベル] タブの [ラベルの保存] をクリックします。表示されるダイアログ ボックスで、ラベル付き信号セットに名前 heartrates を指定します。[OK] をクリックして、信号アナライザーに戻ります。信号テーブルで、heartrates を選択して右クリックし、HeartRates.mat という名前のファイルにエクスポートします。

ラベル付き信号セットを読み込みます。セット内の各信号について、連続する心拍間の時間差の標準偏差として心拍変動を計算します。差のヒストグラムをプロットし、心拍変動を表示します。

load HeartRates

nms = getMemberNames(heartrates);

for k = 1:heartrates.NumMembers
    
    v = getLabelValues(heartrates,k,{'QRSregions','Rpeaks'});
    
    hr = diff(cellfun(@(x)x.Location,v));
    
    subplot(2,1,k)
    histogram(hr,0.5:.025:1.5)
    legend(['hrv = ' num2str(std(hr))])
    ylabel(nms(k))
    ylim([0 6])

end

関数 findQRS: QRS 群の検出

関数 findQRS は、入力信号の QRS 群を見つけてラベル付けします。

この関数は、computeFSSTp2qrs の 2 つの補助関数を使用します。(両方の補助機能のコードは、後ほどこの例で示します)。同じディレクトリ内の別のファイルに関数を保存するか、最後の end ステートメントの前に関数を挿入して、findQRS 内で関数を入れ子にすることができます。

computeFSSTp2qrs の呼び出しの間で、findQRS は関数 classify と学習済みの深いネットワーク net を使用して、QRS 領域を特定します。classify を呼び出す前に、深層学習を使用した波形セグメンテーションで説明されているように、findQRS はデータを net で期待される形式に変換します。

  • 各信号は 250 Hz でサンプリングされ、2 行 N 列の cell 配列のスタックに分割されなければなりません。ここで、各行はチャネルに対応し、N は 5000 の倍数です。実際の分割とスタックは関数 computeFSST で行われます。

  • リサンプリングされた各 MIT 信号には 6945 個のサンプルがあり、5000 の倍数ではありません。各信号のすべてのデータを保持するには、信号を乱数でパディングします。プロセスの後半で、関数 p2qrs がこの乱数を QRS 群に属さないものとしてラベル付けし、破棄します。

function [labelVals,labelLocs] = findQRS(x,t,parentLabelVal,parentLabelLoc,varargin)
% This is a template for creating a custom function for automated labeling
%
%  x is a matrix where each column contains data corresponding to a
%  channel. If the channels have different lengths, then x is a cell array
%  of column vectors.
%
%  t is a matrix where each column contains time corresponding to a
%  channel. If the channels have different lengths, then t is a cell array
%  of column vectors.
%
%  parentLabelVal is the parent label value associated with the output
%  sublabel or empty when output is not a sublabel.
%  parentLabelLoc contains an empty vector when the parent label is an
%  attribute, a vector of ROI limits when parent label is an ROI or a point
%  location when parent label is a point.
%
%  labelVals must be a column vector with numeric, logical or string output
%  values.
%  labelLocs must be an empty vector when output labels are attributes, a
%  two column matrix of ROI limits when output labels are ROIs, or a column
%  vector of point locations when output labels are points.

labelVals = [];
labelLocs = [];

Fs = 250;

load('trainedQTSegmentationNetwork','net')

for kj = 1:size(x,2)

    sig = x(:,kj);
    
    % Create 10000-sample signal expected by the deep network
    
    sig = [sig;randn(10000-length(sig),1)/100]';
    
    % Resize input and compute synchrosqueezed Fourier transforms

    mitFSST = computeFSST(sig,Fs);
    
    % Use trained network to predict which points belong to QRS regions
    
    netPreds = classify(net,mitFSST,'MiniBatchSize',50);
    
    % Convert stack of cell arrays into a single vector
    
    Location = [1:length(netPreds{1}) length(netPreds{1})+(1:length(netPreds{2}))]';
    Value = [netPreds{1} netPreds{2}]';
    
    % Label QRS complexes as regions of interest and discard non-QRS data
    
    [Locs,Vals] = p2qrs(table(Location,Value));
    
    labelVals = [labelVals;Vals];
    labelLocs = [labelLocs;Locs/Fs];

end

% Insert computeFSST and p2qrs here if you want to nest them inside
% queryQRS instead of including them as separate functions in the folder.

end

関数 computeFSST: 入力のサイズ変更とフーリエ シンクロスクイーズド変換の計算

この関数は、入力データを net で期待される形式に整形し、関数fsstを使用して入力のフーリエ シンクロスクイーズド変換 (FSST) を計算します。深層学習を使用した波形セグメンテーションで、ネットワークのパフォーマンスは、各学習信号またはテスト信号の時間-周波数マップを入力として与えられた場合に最も高くなります。FSST は変換が元の入力と同じ時間分解能を持つため、再帰型ネットワークに特に役立つ一連の機能を発揮します。関数は以下を実行します。

  • 適切な周波数分解能を与えるために、長さが 128 のカイザー ウィンドウを指定します。

  • 0.5 Hz ~ 40 Hz の周波数範囲でデータを抽出します。

  • 各信号の平均で減算し、標準偏差で除算します。

  • FSST の実数部と虚数部を個別の特徴として扱います。

function signalsFsst = computeFSST(xd,Fs)

targetLength = 5000;
signalsOut = {};

for sig_idx = 1:size(xd,1)

    current_sig = xd(sig_idx,:)';

    % Compute the number of targetLength-sample chunks in the signal
    numSigs = floor(length(current_sig)/targetLength);

    % Truncate to a multiple of targetLength
    current_sig = current_sig(1:numSigs*targetLength);

    % Create a matrix with as many columns as targetLength signals
    xM = reshape(current_sig,targetLength,numSigs);

    % Vertically concatenate into cell arrays
    signalsOut = [signalsOut; mat2cell(xM.',ones(numSigs,1))];

end

signalsFsst = cell(size(signalsOut));

for idx = 1:length(signalsOut)

   [s,f] = fsst(signalsOut{idx},Fs,kaiser(128));

   % Extract data over the frequency range from 0.5 Hz to 40 Hz
   f_indices = (f > 0.5) & (f < 40);
   signalsFsst{idx}= [real(s(f_indices,:)); imag(s(f_indices,:))];

   signalsFsst{idx} = (signalsFsst{idx}-mean(signalsFsst{idx},2)) ...
       ./std(signalsFsst{idx},[],2);

end

end

関数 p2qrs: 関心領域としての QRS 群のラベル付け

深いネットワークは、入力信号のすべての点を、P 領域、QRS 群、T 領域に属するとして、またはいずれにも属さないとしてラベル付けする categorical 配列を出力します。この関数は、これらの点ラベルを QRS 関心領域ラベルに変換します。

  • 変換を実行するために、この関数は整数の数値をカテゴリに割り当て、関数findchangeptsを使用して数値配列の値が変化する点を見つけます。

  • これらの各変化点はカテゴリカル領域の左の端点であり、配列内でその前にある点は、前の領域の右の端点です。

  • このアルゴリズムは、1e-6 を右の端点に追加して、1 サンプル領域の持続時間がゼロになることを防ぎます。

  • df パラメーターは、持続時間が df サンプルよりも長い QRS 群のみを関心領域として選択します。

function [locs,vals] = p2qrs(k)

fc = 1e-6;
df = 20;

ctgs = categories(k.Value);
levs = 1:length(ctgs);
for jk = levs
   cat2num(k.Value == ctgs{jk}) = levs(jk);
end
chpt = findchangepts(cat2num,'MaxNumChanges',length(cat2num));
locs = [[1;chpt'] [chpt'-1;length(cat2num)]+fc];

vals = categorical(cat2num(locs(:,1))',levs,ctgs);
locs = locs+round(k.Location(1))-1;

qrs = find(vals=='QRS' & diff(locs,[],2)>df);

vals = categorical(string(vals(qrs)),["QRS" "n/a"]);

locs = locs(qrs,:);

end

関数 findRpeaks: R ピークの検出

この関数は、findQRS により見つかった QRS 関心領域の最も突出したピークを検索します。この関数は、MATLAB® 関数 islocalmax を、findQRS により見つかった区間の信号の絶対値に適用します。

function [labelVals,labelLocs] = findRpeaks(x,t,parentLabelVal,parentLabelLoc,varargin)

Fs = 250;

if isempty(t)
    t = (0:length(x)-1)'/Fs;
end

labelVals = zeros(size(parentLabelLoc,1),1);
labelLocs = zeros(size(parentLabelLoc,1),1);

for kj = 1:size(parentLabelLoc,1)
    tvals = t>=parentLabelLoc(kj,1) & t<=parentLabelLoc(kj,2);
    ti = t(tvals);
    xi = x(tvals);
    lc = islocalmax(abs(xi),'MaxNumExtrema',1);
    labelVals(kj) = xi(lc);
    labelLocs(kj) = ti(lc);
end

end

参照

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

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

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

[4] Moody, George B., and Roger G. Mark."The impact of the MIT-BIH Arrhythmia Database."IEEE Engineering in Medicine and Biology Magazine.Vol. 20, No. 3, May–June 2001, pp. 45–50.

この例では、信号ラベラーで発声された単語にラベル付けする方法を示します。この例では、IBM® Watson Speech to Text API と Audio Toolbox™ ソフトウェアを使用します。以下の手順については、Speech-to-Text Transcription (Audio Toolbox)を参照してください。

  1. MATLAB® Central から入手可能な Audio Toolbox の speech2text 拡張機能をダウンロードします。

  2. IBM Cloud サービスから提供されている IBM Watson Speech API を設定します。IBM Cloud アカウントと Speech to Text サービス インスタンスを作成し、サービス ダッシュボードに移動して、資格情報 (API キーと URL の値) をコピーしなければなりません。詳細については、IBM ドキュメンテーションの入門チュートリアルを参照してください。

音声データの読み込み

男性の声で話された "Oak is strong, and also gives shade" という文を含むオーディオ データ ファイルを読み込みます。信号は 44,100 Hz でサンプリングされています。

[y,fs] = audioread('oak.m4a');

% To hear, type soundsc(y,fs)
  1. 信号アナライザーを起動して、信号テーブルに信号をドラッグします。信号を選択します。

  2. 時間情報を追加します。[アナライザー] タブで [時間値] をクリックし、Sample Rate and Start Time を選択して、サンプルレートとして fs を指定します。

  3. [アナライザー] タブの [ラベル] をクリックします。[ラベル付き信号セット] ブラウザーに信号が表示されます。

ラベルの定義

信号に付加するラベルを定義します。[ラベル] タブの [定義の追加] をクリックします。[ラベル名]Words を指定して、[ラベル タイプ]ROI を選択し、[データ型] として string と入力します。

カスタム自動ラベル付け関数の作成

オーディオ ファイルの発声された単語にラベル付けするカスタム関数を作成します。(関数 stt のコードは、後ほどこの例で示します)。

  1. speech2text P コード ファイルと IBM Cloud の資格情報が格納されている JSON ファイルを保存したディレクトリに移動します。

  2. 関数を作成するために、[アナライザー] タブの [値の自動処理] ▼ をクリックして、[カスタム関数の追加] を選択します。信号ラベラーにより、追加する関数の名前、説明、およびラベル タイプの入力を求めるダイアログ ボックスが表示されます。名前フィールドに stt と入力し、[ラベル タイプ] として ROI を選択します。説明フィールドは空のままにすることも、独自の説明を入力することもできます。

  3. 関数コードをコピーして、表示される空のテンプレートに貼り付けます。ファイルを保存します。関数がギャラリーに表示されます。

発声された単語の検索と特定

入力信号の発声された単語を検索して特定します。

  1. [ラベル付き信号セット] ブラウザーで、y の横にあるチェック ボックスをオンにします。

  2. [ラベルの定義] ブラウザーで Words を選択します。

  3. [値の自動処理] ギャラリーで、stt を選択します。

  4. [自動ラベル付け] をクリックし、表示されたダイアログ ボックスで [OK] をクリックします。

信号ラベラーが発声された単語を検索してラベル付けします。

ラベル付き信号のエクスポート

ラベル付き信号をエクスポートします。[ラベル] タブの [ラベルの保存] をクリックします。表示されるダイアログ ボックスで、ラベル付き信号セットに名前 transcribedAudio を指定します。[OK] をクリックすると、信号アナライザーに戻ります。信号テーブルで、transcribedAudio を選択して右クリックし、Transcription.mat と呼ばれるファイルにエクスポートします。

ラベル付き信号セットを読み込みます。このセットのメンバーは 1 つのみです。ラベルの名前を取得し、その名前を使用して、文字に起こされた単語を取得して表示します。

load Transcription

ln = getLabelNames(transcribedAudio);

v = getLabelValues(transcribedAudio,1,ln)
v=7×2 table
     ROILimits       Value  
    ____________    ________

    0.09    0.56    "oak"   
    0.59    0.97    "is"    
       1    1.78    "strong"
    1.94    2.19    "and"   
    2.22    2.67    "also"  
    2.67    3.22    "gives" 
    3.25    3.91    "shade" 

"Oak gives shade, and also is strong" という文になるように単語を並べ替えます。単語ごとに異なる色を使用して信号をプロットします。

k = v([1 6:7 4:5 2:3],:);

s = getSignal(transcribedAudio,1);

sent = [];
sgs = NaN(height(s),height(k));
lgd = [];

for kj = 1:height(k)
    lm = length(sent);
    word = s.y(timerange(seconds(k.ROILimits(kj,1)),seconds(k.ROILimits(kj,2))));
    sent = [sent;word];
    sgs(lm+(1:length(word)),kj) = word;
    lgd = [lgd;(length(sent)-length(word)/2)/fs];
end

sgs(length(sent)+1:end,:) = [];

% To hear, type soundsc(sent,fs)

plot((0:length(sgs)-1)/fs,sgs)
text(lgd,-0.7*ones(size(lgd)),k.Value,'HorizontalAlignment',"center")
axis tight

関数 stt: 発声された単語の検索と特定

この関数は、IBM Watson Speech API と Audio Toolbox の speech2text 拡張機能を使用して、オーディオ ファイルから発声された単語を抽出します。

function [labelVals,labelLocs] = stt(x,t,parentLabelVal,parentLabelLoc,varargin)

aspeechObjectIBM = speechClient('IBM','timestamps',true,'model','en-US_NarrowbandModel');

fs = 1/(t(2)-t(1));

tixt = speech2text(aspeechObjectIBM,x,fs);

numLabels = numel(tixt.TimeStamps{:});
labelVals = strings(numLabels,1);
labelLocs = zeros(numLabels,2);

for idx =1:numLabels
    labelVals(idx) = tixt.TimeStamps{:}{idx}{1};
    labelLocs(idx,1) = tixt.TimeStamps{:}{idx}{2};
    labelLocs(idx,2) = tixt.TimeStamps{:}{idx}{3};
end

end

ヒント

  • ラベルを保存するときに、信号ラベラーは時間情報を持つすべての信号を timetable に変換します。この変換により、保存された labeledSignalSet のネストされたチャネルの階層がより深くなります。詳細は、信号ラベラーによる動作のインポートとエクスポートを参照してください。

  • 信号ラベラーは、マルチチャネル信号に対応するラベルをレンダリングするときにチャネルの色を平均化します。最適な結果を得るには、指定した信号のチャネルすべてに対して同じになるようにラインの色をカスタマイズします。信号ラベラーを入力する前に信号アナライザーでカスタマイズを実行します。

    diffr のラベルの色 (チャネルが異なる色をもつ信号) を equal のラベルの色 (チャネルすべてが同じ色をもつ信号) と比較します。equal のいずれのラベルも、チャネルすべてが共有する青色の陰影でレンダリングされます。diffr のラベルは、チャネルの色のいずれにも一致しない茶色の陰影でレンダリングされます。

  • 信号ラベラーのウィンドウの幅を狭くすると、時間プロットの下の属性テーブルに水平スクロールバーが表示されます。Apple macOS システムでは、このスクロールバーは既定で非表示になっています。トラックパッドがある場合、水平方向にスクロールすると、スクロールバーが表示されます。マウスを使用していて、スクロールバーを常に表示する場合は、システム設定でシステムの動作を変更できます。

R2019a で導入