スギノウエメモ

機械学習とか雑記とか

カルティエ展

妻の付き添いで「カルティエ、時の結晶展」に行ってきた。

何かとキラキラしていたが、こういった芸術の分野にも、幾何学的要素が散りばめられていると思うと興味深い。

午前中早いうちに行ったが、午後帰る時は入場に並び順ができていた、早めに行ってよかった。今日寒かったが、良い1日だった、今からハンバーグを食べに行こう。

機械学習による異常検知メモ1

お仕事柄、異常検知の題材をよく扱うが、知識0からだったので、右往左往していた。
どっかのセミナーに行った時、基本以下の本がとても参考になると聞いたので買ってみて勉強中。

入門 機械学習による異常検知―Rによる実践ガイド

入門 機械学習による異常検知―Rによる実践ガイド

チョットずつわからないところを内容そのままにならないようにメモしておく。

異常検知の基本的な流れ

  1. 分布推定
  2. 異常度の定義
  3. 閾値の設定

分布を推定し、何を異常か定義し、その異常度の閾値を超えるものを異常とする。

正規分布の式について

f(X) = \frac{1}{\sqrt{2πσ^2}}\exp{(-\frac{(x-μ)^2}{2σ^2})}

式の意味は、以下がとてもわかりやすかった。色々融通が効くようにパラメータを追加した結果の式。
to-kei.net

ホテリング理論

正規分布を仮定し観測できるデータが十分大きければ、異常度を負の対数尤度とすると、異常度が自由度1スケール因子1のカイ2乗分布に従う。
これによって閾値を統計的に設定できる所が利点。

尤度:確率分布の引数に観測値を代入したもの。
正規分布の負の対数尤度:
 \begin{align}  \frac{1}{2\sigma^2}(x’ – \mu)^2 + \frac{1}{2}\ln(2\pi\sigma^2)  \end{align}
2項目にx'はないので定数とみて無視
 \begin{align}  a(x’) = \frac{1}{\sigma^2}(x’ – \mu)^2 =  (\frac{x’ – \mu}{\sigma})^2  \end{align}

カイ二乗分布

確率変数Z1,Z2,...,Znが互いに独立であり、それぞれが標準正規分布N(0,1)に従うとき、

χ^2 = Z^2_1 + Z^2_2 +,...,+Z^2_k

のχ2に従う分布を、自由度k(足される標準正規分布の数)のカイ二乗分布(chi-sqare distribution)と言う。

F分布はカイ二乗分布の仲間。

・・・つづく

ロマサガ3

先週から、つい懐かしさから、スマホロマサガ3を購入し遊んでいる。

確か高校生の時に、中古でやってクリアした記憶がある。

とりあえず2と違って、クイックタイムが使い難かったり、技が全然閃かなかった思い出。

 4日ほどやって、初めてファイナルレターと地ずり残月を覚えた。インターネットって便利。アスラ道場なんて初めて聞いた、いつも術を覚えさせてて王冠がついていなかったから昔は閃かなかったのかな。うーむ。

全然ストーリー進めてないけど、HP700位あるので、術覚えさせてからクリアに向けて遊んでみよう。追加要素に期待

 

ではでは。

 

Keras で AutoEncoder 実行するまでのメモ

python を触り始めて半年、色々学んだ事を記録しておく。
環境はGoogle Collaborators 使用。

実装してみる

データ概要

100点のxから生成したa*sin(x) を作る。
a は平均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)

f:id:sugino_ue:20191110000858p:plain
こんな感じのデータ

学習データ、テストデータ作成

学習データ : 平均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の型に整形している。
今回、テストデータがある想定なので全部対象にできたが、テストデータが手元にない場合は、正規化の方法をもっと工夫する必要がありそう。
f:id:sugino_ue:20191110131331p:plain
青が学習データ、赤がテストデータ。
上が正規化する前、下が正規化した後。
値の縮尺のみが変わっている。

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
f:id:sugino_ue:20191110131853p:plain
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')

f:id:sugino_ue:20191110141124p:plain
標準偏差3の範囲のx_trainを学習させたので、3\sigmaにあたる±9の範囲を青で、それ以外の範囲を赤で示している。
x_testは一様分布なのだが、3つ目、4つ目のグラフをみる通り、MSEの値は青の範囲はほとんど0となり、期待通り。
sin波が、学習したデータから外れるほどMSEの値が大きくなっている。

ブログ始めました

初めまして、スギノと申します。

新しい職場にも慣れ、少しずつでもスキルアップしようと

ブログを始めることにしました。

簡単な 経歴

大手組込系SEから平成最後の年に、36歳にして初転職。

未経験の製造業にて、データサイエンティスト として就任。

プログラミングスキル的には、Cを5年やっていた程度。

最近 Python, C# あたりを業務で触っていて四苦八楽。

 

ブログの主旨

大きく2つあって、

  • アウトプットによるスキルアップ
  • その時期に何をやっていたかの記録を残し振り返る

技術的に分からなかった事やつまづいて調べた事を、備忘録的な意味で

残しておきたい。後は、雑多な日記なども気軽に書いていこうかなと。

週一くらいでまったり続けていけるかなぁ、ちょいわからず。

 

それではまた。