サロンでショコラ
先週は妻とチョコのイベントに行ってきた。
人がすごかった。チョコ5万ほど買ったのだが、指定のクレジットカードしか
使えないのが辛い。これがなければ解約したいのだが、しょうがない。
健康診断
最近健康診断に引っかかって、要精密検査となった。
年末年始と飲み会が多いが、肝臓のALTの値だけ高く。
とりあえず先週からエアロバイクを漕ぎ出した。20分頑張って毎日漕ぐ。
1月に病院に行って診てもらおう。
機械学習による異常検知メモ1
お仕事柄、異常検知の題材をよく扱うが、知識0からだったので、右往左往していた。
どっかのセミナーに行った時、基本以下の本がとても参考になると聞いたので買ってみて勉強中。
チョットずつわからないところを内容そのままにならないようにメモしておく。
正規分布の式について
式の意味は、以下がとてもわかりやすかった。色々融通が効くようにパラメータを追加した結果の式。
to-kei.net
Keras で AutoEncoder 実行するまでのメモ
python を触り始めて半年、色々学んだ事を記録しておく。
環境はGoogle Collaborators 使用。
実装してみる
データ概要
100点のから生成した を作る。
は平均0,標準偏差3の正規分布とする。
試しに5つ描いてみる。
import numpy as np from matplotlib import pyplot as plt import random fig = plt.figure() ax1 = fig.add_subplot(1, 1, 1) n = 100 x = np.linspace(0, 2*np.pi, n) for i in range(5): a = np.random.normal(0, 3) y = a * np.sin(x) ax1.plot(y)
こんな感じのデータ
学習データ、テストデータ作成
学習データ : 平均0,標準偏差3の正規分布 * sin(x) を200データ
テストデータ: -20~20 の一様分布 * sin(x)を200データ
上記データを作成
train_list = [] test_list = [] for i in range(200): a = np.random.normal(0, 3) b = random.uniform(-20, 20) y_train = a * np.sin(x) y_test = b * np.sin(x) train_list.append(y_train) test_list.append(y_test) x_train = np.vstack(train_list) x_test = np.vstack(test_list) print("x_train.shape=", x_train.shape) print("x_test.shape=", x_test.shape)
x_train.shape= (200, 100)
x_test.shape= (200, 100)
for文の中で、list を append、最後に結合というのよくやる。
正規化
学習データ、テストデータ共に、最大値、最小値が-1~1の範囲を超えている。
この後、非線形関数の活性化関数を使って学習するが、活性化関数では最大、最小で表現できる値が決まっているので、正規化するのが一般的。
今回はtanhを使うので、-1〜1 の範囲に値が収まるようにMinMaxScalerで正規化する。
活性化関数の例:
ReLU:最小値=0, 最大値は幾つでも。
tanh:最小値=-1, 最大値=1
from sklearn.preprocessing import MinMaxScaler fig = plt.figure(figsize=(10, 10)) ax1 = fig.add_subplot(2, 1, 1) ax2 = fig.add_subplot(2, 1, 2) for i in range(len(x_train)): ax1.plot(x_train[i], color="blue") ax1.plot(x_test[i], color="red") scaler = MinMaxScaler(feature_range=(-1, 1)) all_val = np.hstack((x_train, x_test)).reshape(-1, 1) scaler.fit(all_val) x_train = scaler.transform(x_train) x_test = scaler.transform(x_test) for i in range(len(x_train)): ax2.plot(x_train[i], color="blue") ax2.plot(x_test[i], color="red")
学習データ、テストデータ合わせた全部で、-1~1にしたいので、all_valで結合し、fitの型に整形している。
今回、テストデータがある想定なので全部対象にできたが、テストデータが手元にない場合は、正規化の方法をもっと工夫する必要がありそう。
青が学習データ、赤がテストデータ。
上が正規化する前、下が正規化した後。
値の縮尺のみが変わっている。
AutoEncoderで学習
AutoEncoderのモデルを定義。
100 -> 50 -> 100 で次元を50にした後復元している。
損失関数はMSE(最小二乗誤差)。
EarlyStoppingを指定する事で、学習を良い所で止めている。
from keras.layers import Input, Dense from keras.models import Model from keras.callbacks import EarlyStopping input_sin = Input(name="input_sin", shape=(100,)) encoder = Dense(50, name="encoder1", activation='tanh')(input_sin) decoder = Dense(100, name="decoder1", activation='tanh')(encoder) autoenc = Model(inputs=input_sin, outputs=decoder) autoenc.summary() autoenc.compile(loss='mean_squared_error', optimizer='adam') early_stop = EarlyStopping(monitor='val_loss', patience=5, verbose=1, mode='auto') history = autoenc.fit(x_train, x_train, epochs=1000, batch_size=100, shuffle=True, validation_split=0.1, verbose=0, callbacks=[early_stop] ) loss = history.history['loss'] val_loss = history.history['val_loss'] nb_epoch = len(loss) fig = plt.figure() ax1 = fig.add_subplot(1, 1, 1) ax1.plot(range(nb_epoch), loss, label='loss') ax1.plot(range(nb_epoch), val_loss, label='val_loss') ax1.set_xlabel('epoch') ax1.set_ylabel('loss') ax1.legend()
________________________________________________________
Layer (type) Output Shape Param #
=======================================
input_sin (InputLayer) (None, 100) 0
________________________________________________________
encoder1 (Dense) (None, 50) 5050
________________________________________________________
decoder1 (Dense) (None, 100) 5100
=======================================
Total params: 10,150
Trainable params: 10,150
Non-trainable params: 0
________________________________________________________
Epoch 00079: early stopping
79 epoch で学習終了している。
以前ハマったのが、
- Dense の nameは、表示だけのもので、引数指定には使えない。
- Input の shape には、データのセット数は入らない。
x_train.shape= (200, 100)なので、100個のsin(x)データが200セット。
- trainとtestは、データのセット数以外は同じshapeでないとエラー。
上記モデルは、trainだけでなく、test時も同じように使うので。
テストデータで評価
テストデータを入れ、結果を見てみる。
評価としては、損失関数と同じ、MSEの値で、INPUTしたデータがどれだけOUTPUTしたデータと差があるかを確認する。
pre = autoenc.predict(x_test) pre = scaler.inverse_transform(pre) x_test = scaler.inverse_transform(x_test)
基本
- model定義 -> fit()で学習 -> 学習曲線で収束しているか確認 -> predict()でテストデータを入れる
の流れは、AutoEncoderだけでなく、他DNNのモデルや scikit-learnの機械学習なども同様。
わかりやすいように、inverse_transformで正規化を元に戻してから
以下、predictした結果をグラフ化して確認。
from sklearn.metrics import mean_squared_error fig = plt.figure(figsize=(10, 20)) ax1 = fig.add_subplot(4, 1, 1) ax2 = fig.add_subplot(4, 1, 2) ax3 = fig.add_subplot(4, 1, 3) ax4 = fig.add_subplot(4, 1, 4) mse_red = [] mse_blue = [] for i in range(len(pre)): mse_val = mean_squared_error(x_test[i], pre[i]) if np.max(x_test[i]) > 9: ax1.plot(x_test[i], color="red") ax2.plot(pre[i], color="red") ax3.scatter(i, mse_val, color="red") mse_red.append(mse_val) else: ax1.plot(x_test[i], color="blue") ax2.plot(pre[i], color="blue") ax3.scatter(i, mse_val, color="blue") mse_blue.append(mse_val) ax1.set_xlabel('x') ax1.set_ylabel('sin(x)') ax2.set_xlabel('x') ax2.set_ylabel('after autoenc sin(x)') ax3.set_xlabel('file') ax3.set_ylabel('mse value') # ax3.set_ylim(0, 0.5) ax4.hist([mse_blue, mse_red], bins=50, color=["blue", "red"], stacked=True) ax4.set_xlabel('mse value') ax4.set_ylabel('file count')
標準偏差3の範囲のx_trainを学習させたので、にあたる±9の範囲を青で、それ以外の範囲を赤で示している。
x_testは一様分布なのだが、3つ目、4つ目のグラフをみる通り、MSEの値は青の範囲はほとんど0となり、期待通り。
sin波が、学習したデータから外れるほどMSEの値が大きくなっている。
ブログ始めました
初めまして、スギノと申します。
新しい職場にも慣れ、少しずつでもスキルアップしようと
ブログを始めることにしました。
簡単な 経歴
大手組込系SEから平成最後の年に、36歳にして初転職。
未経験の製造業にて、データサイエンティスト として就任。
プログラミングスキル的には、Cを5年やっていた程度。
最近 Python, C# あたりを業務で触っていて四苦八楽。
ブログの主旨
大きく2つあって、
- アウトプットによるスキルアップ
- その時期に何をやっていたかの記録を残し振り返る
技術的に分からなかった事やつまづいて調べた事を、備忘録的な意味で
残しておきたい。後は、雑多な日記なども気軽に書いていこうかなと。
週一くらいでまったり続けていけるかなぁ、ちょいわからず。
それではまた。