皆さん、こんにちは!KSKアナリティクスの岡地です。今回は、特異スペクトル変換法を使用した変化検知をRapidMinerとPythonを使用して実装してみたいと思います。以下の書籍に特異スペクトル変換法とその実装についての説明があったので参考にしました。井手剛・杉山将(2015)「異常検知と変化検知(機械学習プロフェッショナルシリーズ)」,講談社.使用するデータは心電図のデータを使用します。元データは以下よりダウンロードできます。http://www.cs.ucr.edu/~eamonn/discords/qtdbsel102.txt今回は上記よりダウンロードしたデータを加工したデータを使用します。使用するデータとRapidMinerのプロセスはこちらよりダウンロードして下さい。Extensionが必要です。メニューバー>Extensions>Marketplaceより無償でインストールできます。真ん中あたりで通常とは違った動きをしているのがわかります。今回は特異スペクトル変換法を使用して、この異常部分を発見したいと思います。特異スペクトル変換法は以下の図のように説明されます。(井手剛・杉山将(2015)「異常検知と変化検知(機械学習プロフェッショナルシリーズ)」,講談社.を参考に著者作成)特異スペクトル変換法は、ある時刻tの周りに部分時系列を現在側と過去側に作成します。現在側の部分時系列をテスト行列(Z^(t))、過去側の部分時系列を履歴行列(X^(t))と呼びます。このテスト行列、履歴行列にはそれぞれある一定区間に区切られたWindowが複数含まれています。時刻tの変化度(異常度)はテスト行列に含まれるWindow群の波形と履歴行列に含まれるWindow群の波形を比較して、どれだけ食い違っているかで定義されます。履歴行列とテスト行列を比較する前にそれぞれのWindow群の特徴を表す代表的な波形を数本作成しておきます。この代表的な波形を作成する作業が特異値分解(SVD)になります。したがって、履歴行列、テスト行列それぞれを代表する特徴的な波形数本同士を比較し、どれほど食い違いがあるかを調べます。Decomposition)特異値分解は固有値分解を正方行列だけでなく、長方形行列にも適用できるように拡張したものと考えられます。全体の情報をある程度保ちながら次元削減するために使用します。波形1本が1列に対応するように並べた後に、特異値分解を使用して次元削減します。イメージとしてはPCAと同じような働きをすると考えるとわかりやすいです。50本の波形全体の情報を保ちつつ、次元を減らすわけです。この操作を先ほど「Window群の特徴を表す代表的な波形を数本作成する」と表現しました。特異値分解は元データのXを上記のように3つの部分に分解します。式で書くと以下ようになります。U\Gamma^{1/2}V^T$$Uの各列を左特異ベクトル、Gamma^{1/2}の対角成分を特異値、Vの各列を右特異ベクトルと呼びます。左特異ベクトルの行列から、いくつか列を抜き出す事によって、次元削減を行います。Q_m^{(t)}$$とします。異常度は以下のように定義されます。特異スペクトル変換法をRapidMinerとpythonで実装した例が以下になります。ChangeDetection_SST.rmpというファイルをRapidMinerで開いてください。Processより上記rmpファイルを選択してください。)以下にプロセスを解説していきます。ECG_include_anomaly_3000データを読み込むオペレータです。プロセスを保存した場所と同じ場所にECG_include_anomaly_3000を取り込んでください。Macro)データセットをのサンプル数をカウントして格納しておくマクロです。ここではNumOfExampleに3000が格納されます。マクロについては以下のブログを参考にしてください。sizeを1として、Windowを作成します。1Windowにつき1行、Window内のデータをそのまま列に並べます。Windowingについては以下のブログも参考にしてください。Macroが配置されています。いずれもマクロを作成するためのものです。ここでは以下のマクロを作成しています。ここでは100が格納されます。履歴行列とテスト行列に含まれるWindowの数。ここでは50が格納されます。履歴行列とテスト行列をどれだけずらすか。ここでは25が格納されます。ベクトルの行列から何列使用するか。5Loopここで特異値分解を計算しています。中は以下のようになっています。Macroで履歴行列のスタート地点と終了地点、テスト行列のスタート地点と終了地点を設定しています。反復ごとに1時点ずれていきます。Transposeオペレータを置いているのは、1列1windowにするためです。Transpose後、履歴行列もテスト行列も100行50列のデータになります。SVDオペレータはデータを特異値分解し、左特異ベクトルの行列を指定した列数で返却します。reductionパラメータとdimensionパラメータで設定しています。Attribute)オペレータでそれぞれのSVDの結果にID番号(反復回数)を割り当てます。6AppendLoopの結果を行結合して、一つにまとめます。PythonID番号が一致する履歴行列とテスト行列の内積を計算し、その最大特異値を1から引いたものを異常度と定義します。コードは以下の通りです。8Store異常度をanomaly_scoreという名前で保存します。元の波形と異常度の関係はcompare_anomaly_and_seriese.rmpで確認できます。異常な動きをしている所の異常度が著しく大きくなっています。いかがでしたでしょうか。皆さんも一度、RapidMinerを使用して異常検知や変化検知を試してみてください。