以下の赤い本の9章を読みます。キャラクターは適当です。誤りがありましたらご指摘いただけますと幸いです。 「変化を検知したい」ってときありますよね。この本の9章を読みたいです。 導入が雑…。 最初の累積和法は、「正常状態の分布」「異常状態の分布」を所与として、逐次的に観測される変数が異常状態の方に近い場合にだけ異常さのポイントを積み上げる手法のようですね。…「正常状態の分布」「異常状態の分布」がわかってたら苦労しなくないですか? いやまあそこがわかってたらかなりありがたいけど、じゃあどちらの分布に近いのかというのを対数尤度比という形で定量化して、さらにそれを時系列データにおける継続的な異常状態の検知に適用するために累積和という指標にまとめる、というのも大事な仕事なんじゃないかな。 そう、その「継続的な異常状態の検知」という点についてもなんですが、この累積和って異常の継続性を考慮してますか? 「たまに異常になる分には目をつぶって、継続的に異常になったら検知したい」ということで累積和をとったということですが、これって異常が連続していようと数回おきであろうと足し上げていくだけですよね。異常が継続していなくても累積和はどんどん降り積もっていきません? そういう場合は定期的にリセットするんでしょ。結局ある一定の期間内の異常さの和に閾値を置いているのと等しいとは思うよ。ある一定の期間内に多くの異常が発生することがここでの継続的な異常なんだと思う。 なるほど。…次に紹介されているのは近傍法ですね。この手法で少なくとも所与とするのは「正常な部分時系列のセット」ですね。それで、検査対象の部分時系列を入力すると、最も近い正常な部分時系列までの距離(の対数の定数倍)を返すといった具合ですね。 k=1 の k 近傍法で、明示的に異常標本を与えずにとにかく異常度のみ算出する場合はその手続きになるね。 いや、カルバック・ライブラー情報量ですね。 はい。 KL情報量は非対称だけど、これは「参照データの分布が厚いところで検査データの分布が薄いことを問題視する」って向きだね。参照データにはよく見られるようなデータが検査データに全然見られなかったらおかしいだろうと。狭い参照データ分布をカバーするように広い検査データ分布よりは、広い参照データ分布をカバーし切らない狭い検査データ分布の方が相違度が大きくなるね。例えば、 参照データ分布としてそんなにだらだら広がった分布を仮定しない方がよさそうですね。検査データ分布側の密度の欠落に厳しくなりそうです。 116ページからは、(9.8) 式の具体的な計算手法が1つ紹介されていて、つまり、特異スペクトル変換法だね。 フォンミーゼス・フィッシャー分布…扱ったことがないですね…7章を参照するとこれは、M次元超球面上に定義される分布ということですが…なぜこんな分布を導入するのでしょう…。 参照データ分布と検査データ分布にフォンミーゼス・フィッシャー分布(長いので以下vMF分布)を仮定するということだけど、(少なくともこの本の)特異スペクトル法の手順の中で「集中度」は推定せず参照データ分布も検査データ分布も適当な同一の集中度を取ると仮定しているから、結局推定対象パラメータは「平均方向」のみで、だから「参照データセットと検査データセットをそれぞれ表現するvMF分布って何だろう」というよりは、実質的には「参照データセットと検査データセットをそれぞれ代表する単位ベクトルって何だろう」ってことだね。そういう単位ベクトルを求めたらそれらを平均方向とするvMF分布どうしのKL情報量を相違度とするわけだけど。ともあれ単位ベクトルの求め方が肝心そうだね。いや…単位ベクトル自体を求めるわけじゃなくて、そのような単位ベクトルどうしの内積に相当する値を直接求めにいってるね。 参照データの第i成分を全て束ねたM本のベクトルをどのようなM個の係数の組み合わせで線形結合するとそのL2ノルムが極値になるかを考える(ただし、M個の係数の2乗和は1という制約の下で)。極値を与える係数のセット(=左特異ベクトル)がMセット求まる。最も大きい極値を与える左特異ベクトルは参照データを特徴付けるベクトルだろう、って感じだね。だから参照データのそれと検査データのそれの内積を取れば相違度がわかるだろうと。ただ最も大きい極値以外無視するというのもあれだっていうなら特異値上位の何本かずつ左特異ベクトルを選ぶわけだけど、例えば2本ずつ選んだら内積が4パターン計算できちゃう。どうやってトータルの相違度とすべきかわからない。そのときは、ここでまたしても各行ベクトル(列ベクトルでもいいけど)の各成分をどのように線形結合するとL2ノルムが極値になるかという問題を解いて、最大の極値(最大特異値)をトータルの相違度とするんだね。この操作は の行列2ノルムを取ることと等しい。 それが118ページでいう「一番人気のある方向」だね。 ちょっと図示してみたいですね。ランダムな2次元データセットを生成して、左特異ベクトルをプロットしてみましょう。こんな感じでいいんでしょうか。灰色のベクトルたちを代表するのが赤いベクトルになると期待しているんですが…。 だから、特異スペクトル変換の定義を modify するみたいだね。もう検査データ側の特異値分解はしないことにして、代表的なデータを選んで(全て選んで後で相違度を何らかの方法で集約してもいいけど)左特異ベクトルの変わりにするみたいだね。 いや部長は高校1年生だよね!? 幼稚園の年長に数値計算の授業はないよね!?異常検知と変化検知 (機械学習プロフェッショナルシリーズ)
井手 剛 杉山 将
講談社 2015-08-08
売り上げランキング : 56236
Amazonで詳しく見る by G-Tools
(参照データ分布の方が狭い場合)
(参照データ分布の方が広い場合)n <- 7
x <- c()
for (i in 1:n) {
t <- runif(1, min=0, max=2)
x <- c(x, 2*cos(pi*t), 2*sin(pi*t))
}
x <- matrix(x, nrow=2)
plot(c(-2,2), c(-2,2), xlab="", ylab="", type="n")
for (i in 1:n) {
lines(c(0, x[[1,i]]), c(0, x[[2,i]]), lwd=2, col="dimgray")
}
res <- svd(x)
lines(c(0, res$u[[1,1]]), c(0, res$u[[2,1]]), lwd=4, col="red")
lines(c(0, res$u[[1,2]]), c(0, res$u[[2,2]]), lwd=4, col="darkorange")
print(res)
雑記
Keras をよくわかっていないのでおかしな点があればご指摘いただきたいのですが、1つ前までの記事で紹介していた DAGMM(メモ1/メモ2/メモ3/メモ4)を Keras で実装しようとすると以下のような手順でできるんでしょうか。よくわかりません。
- 不整脈データ(274次元)を真ん中の特徴量が2次元の深層自己符号化器にかける。
- 深層自己符号化器が終わったところで、最初の入力と特徴量を回収してきて、損失に再構築誤差を流し込むと同時に、特徴量に再構築エラー(2次元)を concat してこれを出力する(カスタムレイヤー0)。
- さっきの出力を何層かの全結合層にかけて各分布への割り当て確率にする(不整脈データは混合数2)。
- ここで4次元の特徴量を回収してきて、尤度と正則化項を損失に流し込む(カスタムレイヤー1)。
ガワだけ実装すると以下のようなイメージですが、中身を実装してコンパイルできるのか知りませんし、訓練して勾配計算が意図通りに動くのかも知りません。
# DAGMM x_org = Input(shape=[274]) h_0 = Dense(10, activation='tanh')(x_org) z_c = Dense(2)(h_0) h_1 = Dense(10, activation='tanh')(z_c) x_dash = Dense(274)(h_1) z = MyLayer0()([x_org, z_c, x_dash]) # 損失に再構築誤差を付加 & 再構築エラーをconcat h_2 = Dense(10, activation='tanh')(z) h_3 = Dropout(0.5)(h_2) gamma = Dense(2, activation='softmax')(h_3) gamma_ = MyLayer1()([z, gamma]) # 損失にエネルギーと正則化を付加 DAGMM = Model(x_org, gamma_) DAGMM.compile(optimizer=optimizers.Adam(lr=0.0001), loss=None) DAGMM.summary()
_______________________________________________________________________________________ Layer (type) Output Shape Param # Connected to ======================================================================================= input_1 (InputLayer) (None, 274) 0 _______________________________________________________________________________________ dense_1 (Dense) (None, 10) 2750 input_1[0][0] _______________________________________________________________________________________ dense_2 (Dense) (None, 2) 22 dense_1[0][0] _______________________________________________________________________________________ dense_3 (Dense) (None, 10) 30 dense_2[0][0] _______________________________________________________________________________________ dense_4 (Dense) (None, 274) 3014 dense_3[0][0] _______________________________________________________________________________________ my_layer0_1 (MyLayer0) (None, 4) 0 input_1[0][0] dense_2[0][0] dense_4[0][0] _______________________________________________________________________________________ dense_5 (Dense) (None, 10) 50 my_layer0_1[0][0] _______________________________________________________________________________________ dropout_1 (Dropout) (None, 10) 0 dense_5[0][0] _______________________________________________________________________________________ dense_6 (Dense) (None, 2) 22 dropout_1[0][0] _______________________________________________________________________________________ my_layer1_1 (MyLayer1) (None, 2) 0 my_layer0_1[0][0] dense_6[0][0] =======================================================================================
カスタムレイヤー0は以下です。再構築エラーをつくって低次元の特徴に concat すればいいと思うんですが、まだつくっていないのでなので低次元の特徴を2つ concat しています(不整脈データの例では低次元の特徴と再構築エラーが同じ2次元なので)。雰囲気です。
from keras import backend as K # 損失に再構築誤差を付加 & 再構築エラーをconcat class MyLayer0(Layer): def __init__(self, **kwargs): self.output_dim = 4 super(MyLayer0, self).__init__(**kwargs) def reconstruction_loss(self, x_org, x_dash): return metrics.mean_squared_error(x_org, x_dash) def reconstruction_error(self, x_org, x_dash): z_e = None # IMPLIMENT ME return z_e def call(self, inputs): x_org = inputs[0] z_c = inputs[1] x_dash = inputs[2] loss = self.reconstruction_loss(x_org, x_dash) self.add_loss(loss, inputs=[x_org, x_dash]) # 再構築誤差を付加 z_e = z_c # self.reconstruction_error(x_org, x_dash) # 再構築エラーを計算 z = K.concatenate([z_c, z_e], axis=1) return z def compute_output_shape(self, input_shape): return(input_shape[1][0], self.output_dim)
カスタムレイヤー1は以下です。ここは損失にエネルギー項と正則化項を足すだけですがまだ書いていません。一応各分布への割り当て gamma をそのまま output していますが output する必要はないです。
# 損失にエネルギーと正則化を付加 class MyLayer1(Layer): def __init__(self, **kwargs): self.output_dim = 2 super(MyLayer1, self).__init__(**kwargs) def custom_loss(self, z, gamma): return 0 # IMPLIMENT ME def call(self, inputs): z = inputs[0] gamma = inputs[1] loss = self.custom_loss(z, gamma) self.add_loss(loss, inputs=[z, gamma]) return gamma def compute_output_shape(self, input_shape): return(input_shape[1][0], self.output_dim)
まだ実装してないのでわかりませんというか実装すればいいんですが気が向いたらやります。いつ気が向くのかはわかりません。
深層自己符号化器までは何も問題ないはずなので取り出して動かしてみます。
# 不整脈データ df = pd.read_csv('arrhythmia.data', header=None) df = df.drop(df.columns[[10,11,12,13,14]], axis=1) # 欠損カラムを除去 # 異常ラベルを貼り変える df.iloc[:,274][(df.iloc[:,274]>=1 ) & (df.iloc[:,274]<=2 )] = 20 df.iloc[:,274][(df.iloc[:,274]>=3 ) & (df.iloc[:,274]<=5 )] = 21 df.iloc[:,274][(df.iloc[:,274]>=6 ) & (df.iloc[:,274]<=6 )] = 20 df.iloc[:,274][(df.iloc[:,274]>=7 ) & (df.iloc[:,274]<=9 )] = 21 df.iloc[:,274][(df.iloc[:,274]>=10) & (df.iloc[:,274]<=13)] = 20 df.iloc[:,274][(df.iloc[:,274]>=14) & (df.iloc[:,274]<=15)] = 21 df.iloc[:,274][(df.iloc[:,274]>=16) & (df.iloc[:,274]<=16)] = 20 df.iloc[:,274] = df.iloc[:,274] - 20 x = df.drop(df.columns[[274]], axis=1).values y = df.iloc[:,274].values # 深層自己符号化器のみ取り出して学習 DAE = Model(x_org, x_dash) DAE.compile(loss='mean_squared_error', optimizer=optimizers.Adam(lr=0.0001)) DAE.fit(x, x, shuffle=True, epochs=10000, batch_size=128) # エンコーダを取り出してプロット encoder = Model(x_org, z_c) z_trained = encoder.predict(x) plt.figure(figsize=(12, 8)) plt.scatter(z_trained[:,0], z_trained[:,1], c=y, cmap=plt.get_cmap("bwr")) cb = plt.colorbar() for t in cb.ax.get_yticklabels(): t.set_fontsize(18) plt.tick_params(labelsize=18) plt.show()
上で学習すると特徴空間(2次元)は以下のようになりました。青が正常で赤が異常です。452点あったはずなんですが、相当重なっていると思います。
あと再構築誤差方向への分布はどうなっているのかも気になると思います。さらに何らかの再構築誤差も含めてプロットしようとするともう3次元プロットになってしまうのでその準備をします。
from mpl_toolkits.mplot3d import Axes3D def my_relative_distance(x, y): ret = [] for i in range(x.shape[0]): e2 = 0 x2 = 0 for j in range(x.shape[1]): e2 = e2 + (x[i][j] - y[i][j]) * (x[i][j] - y[i][j]) x2 = x2 + x[i][j] * x[i][j] ret.append(e2 / x2) return ret
その上でこうすると再構築誤差も含めてプロットできると思います。
# エンコーダを取り出してプロット encoder = Model(x_org, z_c) x0 = df.loc[df.iloc[:,274]==0,:].drop(df.columns[[274]], axis=1).values x1 = df.loc[df.iloc[:,274]==1,:].drop(df.columns[[274]], axis=1).values z_trained0 = encoder.predict(x0) z_trained1 = encoder.predict(x1) r_error0 = my_relative_distance(x0, DAE.predict(x0)) r_error1 = my_relative_distance(x1, DAE.predict(x1)) fig = plt.figure(figsize=(12, 8)) ax = Axes3D(fig) ax.plot(z_trained0[:,0], z_trained0[:,1], r_error0, "o", color="#0000ff") ax.plot(z_trained1[:,0], z_trained1[:,1], r_error1, "o", color="#ff0000") plt.tick_params(labelsize=18) plt.show()
なんか再構築誤差方向にも異常データと正常データがあまり分離されているようにみえないので、深層自己符号化器のみで分離する場合は適するハイパーパラメータが違うんだと思います。
論文読みメモ: 深層自己符号化器+混合ガウスモデルによる教師なし異常検知(その4)
以下の論文を読みます。
それも含めて、検証実験のコンフィギュレーションを説明しましょう。今回は2つの実験を行うのですが、1つ目の実験では、各データセットをまず訓練用とテスト用に2分割します。そして、訓練用データから正常データのみを取り出してモデルを訓練します。そのモデルをテストデータに適用するのですが、今回は教師なし学習なので、モデルの出力は各サンプルが「正常か異常か」ではなく「どれくらい異常か」ですね。そこで、今回は次のようにします。「各データセットの異常データ混入割合をa%としたとき、テストデータ異常度の上位a%が『異常』、その他が『正常』と判定されたとする。」 例えば、3つ目の不整脈のデータセットには異常データが15%含まれているので、異常度の上位15%が『異常』判定ということです。こうすれば、通常の分類問題の評価指標がそのまま利用できますね。つまり、精度、感度、F値で各モデルを比較します。
なるほど、それならある程度フェアな比較になるのかな。
それでその1つ目の実験の結果ですが、論文10ページに数表がありますが、見やすいようにF値のみグラフにしてみました。
4.5 節に低次元表現の可視化がありますね。Figure 3. (a) の DAGMM の低次元表現は、他のモデル (b) (c) (d) よりも正常データ(青)と異常データ(赤)をよく分離できていると思いませんか?
まあ、(a) が比較的赤と青が混ざっていないようには見えるけど…3次元プロットじゃ他の角度からも見てみないとよくわかんないような。
どっち!? ちゃんと読んで!
論文の内容は以上になります。あ、今後の課題とかは特にないです。
ないんだ!?
実際にベンチマークに用いられたデータセットを見てみましょう。どのデータセットも Web 上で見つかると思いますが、一番サイズが小さいところで不整脈のデータは以下に落ちてました。
UCI Machine Learning Repository: Arrhythmia Data Set
これは一番最後のカラムが不整脈の種類ラベルみたいですね。それで、論文には dimension が 274 とあるのにラベルを除いても 279 カラムあってどういうことだろうかと思ったんですが、11~15カラム目に欠損値があったのでおそらくそこを除いていると思います。なので欠損カラムを取り除いてとりあえず自己符号化器にかけてみました。ニューロン数も活性化関数もバッチサイズもエポック数も全て論文に明記されていますからね。あ、論文には tensorflow で実装したとありますが、さしあたり keras で書きます。
# -*- coding: utf-8 -*- import numpy as np import pandas as pd from keras.models import Sequential from keras.layers import Dense if __name__ == '__main__': df = pd.read_csv('arrhythmia.data', header=None) df = df.drop(df.columns[[10,11,12,13,14]], axis=1) y = df.iloc[:,274].values x = df.drop(df.columns[[274]], axis=1).values print(y.shape) print(x.shape) encoder = Sequential() encoder.add(Dense(10, activation='tanh', input_shape=(274,))) encoder.add(Dense(2)) decoder = Sequential() decoder.add(Dense(10, activation='tanh', input_shape=(2,))) decoder.add(Dense(274)) compression_net = Sequential() compression_net.add(encoder) compression_net.add(decoder) compression_net.compile(loss='mean_squared_error', optimizer='RMSProp') compression_net.fit(x, x, shuffle=True, epochs=10000, batch_size=128)
じゃあもうちょっと頑張ろうよ!?
今日はもう遅いので…。ところで、R を書いた直後に Python を書くと混乱しませんか?
知らないよ…。
論文読みメモ: 深層自己符号化器+混合ガウスモデルによる教師なし異常検知(その3)
以下の論文を読みます。
前回までのあらすじです。
あらすじにはなってないよね!?
ここで一旦2節の Related Work に戻りましょうか。高次元データに対する異常検知の先行手法は3タイプに分類されると書いています(この辺りの話、全体的に抽象的ですが…)。
- 「異常サンプルは低次元に圧縮しにくいだろう」という考えのもと、次元削減を試行するタイプ。
- 次元削減したときにデコードが上手くいかないようなデータは異常なはずだ、ということです。このアプローチでは元々 PCA や kernel PCA やその他の PCA の亜種が用いられ、近年では深層自己符号化器を用いた手法が提案されています。ただ、サンプルの異常性を専ら「再構築エラー」のみから判断しているために限界がある、と書かれていますね。普通に正常サンプル並みの再構築エラーになる異常サンプルもあるだろうと。特にデータが全体的に再構築しにくい場合や、逆に次元削減手法の表現力があらゆるサンプルをカバーする場合はそうなるだろうと言っています。
- (特徴空間に写像した後に)クラスタリングしてから孤立サンプル/少数クラスタを判別するタイプ。
- そのままですが、このアプローチでもクラスタリングをする以上、高次元データに対しては次元削減必須です。この手法では次元削減とクラスタリングの学習が分離しているために、クラスタリングに必要な情報が次元削減の段階で失われうると指摘されています。これに対処するために、深層自己符号化器を利用して次元削減とクラスタリングを一貫で学習する手法も提案されていますが、クラスタリング時のモデルが単純すぎたり、自己符号化器の事前学習がクラスタリング側からの modify を妨げていると。
- 3タイプの分類とは別枠で「次元削減と混合分布の学習の結合にも関心が高まっていた」という記述があるのですが(別枠なのはこれは必ずしも異常検知でないからですね)、話としてはこの2タイプ目に該当するのではないかと思うのでここに書いておきますね。といっても、この種の先行手法は次元削減が線形であったり、次元削減が事前学習を前提としていて柔軟性がなかったり、という主張が繰り返されているだけですね。それらに比べて本手法 DAGMM は「次元削減が事前学習不要で」「かつ非線形で」「かつGMMと結合して学習する」というのがよいのだと。それに加えて、特に異常検知のために再構築エラーも活用していると。
- (特徴空間に写像した後に)一定割合の外れ値を覗いた正常データを囲む境界面を求めようとするタイプ(=One Class SVM)。
- これもそのままです。特徴空間で正常データと異常データを分離する超平面を探そうということですね。このアプローチは高次元だと次元の呪いのために局所最適解に陥りやすいと書かれています。あ、Qiita で以下のような記事を見つけました。
異常検知のための One Class SVM - Qiita
OC-SVM (Chen2001) | これは上の3番目の One Class SVM です。カーネル関数は通常の RBF カーネルを採用したとのことです。 |
DSEBM-e (Zhai2016) | これらは上の1番目のアプローチで、ナブラを取ると深層自己符号化器の再構築エラーとなるようなエネルギー関数を定義するようですね。それで、DSEBM-e ではエネルギーが大きいサンプルを異常とみなし、DSEBM-r では再構築エラーが大きいサンプルを異常とみなします。 |
DSEBM-r (Zhai2016) | |
DCN (Yang2017) | 異常検知に限らない次元削減と混合分布の結合学習のところで出てきた先行手法ですが、3タイプの分類だと2番目に該当するでしょうね。これは自己符号化器(深層ではない)の学習を後段の k-means が制御します。今回の異常検知の用途では、所属するクラスタのクラスタ中心から距離が離れたデータを異常とみなします。 |
あと、上の比較対象の先行手法とは別に、DAGMM のフレームワークの各要素の有効性の検証のため、以下の DAGMM の亜種でも異常検知を行って DAGMM の結果と比較してみます。
GMM-EN | 学習時のみ目的関数から「再構築エラー」部分を取り除いたものです。学習後の異常検知は元の DAGMM で行います。 |
PAE | 目的関数から「エネルギー」ごと取り除いたものです。なのでもはやただの深層自己符号化器です。再構築エラーによって異常検知します。また、この場合は深層自己符号化器に事前学習(Vincent2010)を施すようです。 |
E2E-AE | モデルの設定は上の PAE と同じそうなのですが、end-to-end で学習するようです。ちょっとよくわからなかったのですが、Zhai2016 と同様のエネルギー関数を利用して尤度を最大化しようとするということなのでしょうか。再構築エラーによって異常検知するということです。 |
PAE-GMM-EM | まず事前学習済の深層自己符号化器を学習してから、EMアルゴリズムによってGMMのパラメータを推定します。学習後の異常検知は元の DAGMM と同じエネルギー関数で行います。 |
PAE-GMM | 上の PAE-GMM-EM とほとんど同じですが、EMアルゴリズムではなく推定ネットワークによってGMMのパラメータを推定します。 |
DAGMM-p | 上の PAE-GMM と似ているのですが、まず圧縮ネットワークを学習した後、次にモデル全体を結合学習します。 |
DAGMM-NVI | DAGMM のエネルギー関数を、neural variational inference のそれに置き換えたものです。 |
亜種多いな!
なんかもう楽しそうですね。それで、再構築エラーには relative Euclidean distance 及びコサイン類似度 を採用したと書いてあるんですが、これは ってことなんですよね? あ、これらの距離関数を選定した理由は Appendix を読むようにと。
論文読みメモ: 深層自己符号化器+混合ガウスモデルによる教師なし異常検知(その2)
以下の論文を読みます。
異常検知するのに有効なデータの密度推定をするのに、次元削減する「圧縮ネットワーク」と、次元削減後の点が混合正規分布のうち何番目の分布に帰属するか予測する「推定ネットワーク」を同時に学習しようという話でした。時間の都合で2節の Related Work は後回しにしますね。3節も3.3節まではイントロの時点で透けてた内容なんで3.4節までとばしますが、ここで示される DAGMM の目的関数は以下です。 はエンコーダ、デコーダ、推定ネットワークのパラメータです。
このうち はサンプル とその再構築 の誤差関数で、通常L2ノルム にするのがよいとか書いてありますね。 はサンプル に対応する確率密度の対数にマイナスをかけたものですね。 は の低次元表現です。 を自己符号化器でエンコードした に加えて、再構築エラー が concatinate されているのに注意ですね。 はこれも と の誤差=距離の関数ですが、必ずしも距離の定義を1つに絞る必要はなく、色々な尺度での誤差を並べて多次元にしてもよいだろうということみたいです。この論文では のことをエネルギーといっていますね。 はネットワークの学習時につかうのみならず、学習し終えていざ異常検知するという段で「閾値よりも高エネルギーなら異常」というようにつかうと。
前回、「圧縮ネットワーク」の目的関数は再構築エラーで「推定ネットワーク」の目的関数は尤度のはずだけどどのように2つのネットワークを同時に学習するんだろう、って気になってたけど、双方を重み付きで足し合わせたものを全体の目的関数とするんだね。ただこの場合、重みのバランスってどうなるんだろう…。あと、最後の項の は?
正則化項です。次元削減と密度推定の結果、得られた密度が特徴空間内で各サンプルに対応する点の周りに局在してしまったら困りますよね。そもそも次元削減と密度推定によってサンプルとサンプルの隙間の密度を埋めたかったのに。このような悲惨な事態を避けるために以下の正則化項を導入します。
は混合されている分布のうち 番目の分布の分散共分散行列の 番目の対角要素です。どの分布のどの対角要素もゼロになってほしくないので、このようなペナルティを導入するというわけです。この正則化項を入れることによって、自己符号化器部分の性能が、事前学習した自己符号化器並みによくなるとか(イントロ部分でメモに記していませんでしたが、自己符号化器は事前学習した方が自己符号化器部分の性能はよくなるが、今回の目的でそれをしてしまうと密度推定側からの要請で自己符号化器側を modify するということがしづらくなってしまうので事前学習はしないというスタンスです、すみません)。
確かに、避けるべきトラップがそれだけなのかはぱっとわからないけど、その事態を避けなければいけないのはマストだね。でもその正則化項もどんな重みで足せばいいのかわからないな…。 はどう決めるの?
がオススメらしいです。おそらく試行錯誤の結果なんじゃないでしょうか。
そっか。
3.5節はDAGMM の密度推定プロセスを、通常の variational inference と対比するとこうって話でしょうか。ただモデルの選定基準や性能に直接関わる話ではなさそうなのでとばしますね。3.6節の内容は上で少し触れました。なので次は4節の検証ですね。
最適化アルゴリズムの話は?
少なくとも3節にはないですね。目的関数はわかったんで、プログラミング部の人に「これを最小化してください」って実装してもらえばいいんじゃないですか?
迷惑だよね!?
今回検証に用いられているベンチマークデータセットですが、論文にはそれぞれ何のデータか明記されていないので、軽く調べておきましょう(リンク先は論文に記述されているリポジトリとは限りません)。
KDDCUP (KDD Cup 99 Data Set) | これは「マルウェア攻撃」と「正常通信」の両方を含む通信データで、494,021件のデータが含まれています(これは10%抽出版の件数であって、元々はサイズが約10倍のデータセットです)。「正常通信」の方が20%と少ないので、DAGMM の検証では「正常通信」の側を「検知すべき異常」とみなしています。調べるとこのデータセットは「マルウェア攻撃」にも22種類の攻撃が含まれているらしいので、だから混合分布によるモデリングが適するのかもしれません。 http://kdd.ics.uci.edu/databases/kddcup99/kddcup99.html |
Thyroid | Thyroidとは「甲状腺」ですね。3772件のデータには「甲状腺機能低下」「やや低下」「正常」の3クラスのデータが含まれ、検証ではこのうち「甲状腺機能低下」を「検知すべき異常」としているようです。 http://odds.cs.stonybrook.edu/thyroid-disease-dataset/ |
Arrhythmia | Arrhythmiaは「不整脈」です。452件のデータにはそれぞれ1~16のラベルが付されており、1が「正常」、2~15がそれぞれタイプの異なる不整脈、16がその他という意味とのことです。DAGMM の検証では、データの絶対数が少ないラベル 3~5, 7~9, 14, 15 を異常とみなしたようです。 https://archive.ics.uci.edu/ml/datasets/arrhythmia |
KDDCUP-Rev | この論文の著者が KDDCUP データセットから改めて抽出したデータセットですね。元々の KDDCUP データセットは全体の20%が「正常通信」で残りの80%が「マルウェア攻撃」ですが、DAGMM による異常検知でも「正常通信」を正常として取り扱うため、「正常通信」のデータは全て保持しておいて、それに加えて「正常通信」のデータサイズの20%の件数にあたる「マルウェア攻撃」をランダムに抽出して、全体の80%が「正常通信」であるような新しいデータセットを用意したということのようです。 |