波形を異常検知させたい(断続的な波形データ)
ある設備の波形を異常検知させたい
初めに、かなりの初学者なので不備などあると思いますが、
解決に必要な情報が足りていない場合はお伝えいただけると幸いです。
よろしくお願いいたします。
早速中身です。
手法は異常検知なのですが
その中でもオートエンコーダを用いて実装しようと
実際に書いてみたのですが、うまくいっていない気がします
環境
使用OS : Windows10
使用言語 : Python
使用データについて
このデータは
1サイクル動作のデータになります
やりたいこと
時系列データにおける異常検知みたいなことがしたいです
その為、
モデルを作成したら、
1サイクル毎に上記のデータを取得し
作成したモデルに通してOKか異常かを判断したいです
この場合にこんなやり方が良い、や
このサイトを参考にすると良いを教えて頂けると嬉しいです
やったこと
参考になるかわかりませんが、一応私がやったことを書きます
①データを準備(取得できているデータがN=1の為、トレインもテストも同じデータを使用)
②「時系列 異常検知」と検索
③オートエンコーダを用いて異常検知実装
(他にもやりましたが全て同じ疑問に当たりやっていることが間違っている気がしました)
まずは自分でネットを参考にしながら書いたものを載せておきます
# モジュールインポート
import os
from glob import glob
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.preprocessing import MinMaxScaler
import tensorflow as tf
from tensorflow.keras import layers,Model
from tensorflow.keras.layers import Input,Dense
from tensorflow.keras import regularizers
##### データの準備 #####
#フォルダ分けしてますが中身は同じです
# データ読み込み - train
Train_Csv_Path = "./csv/train/*.csv"
Train_Csv_Paths = glob(Train_Csv_Path)[0]
# データ読み込み - test
Test_Csv_Path = "./csv/test/*.csv"
Test_Csv_Paths = glob(Test_Csv_Path)[0]
##### データの準備 #####
##### CSV読み込み ######
def Csv_Read(csv_path):
df = pd.read_csv(csv_path, encoding="shift-jis", skiprows=[1])
# データフレームを必要データに絞る
an_df = pd.DataFrame(df["電動シリンダーストローク値"])
return an_df
Train_df = Csv_Read(Train_Csv_Paths)
Test_df = Csv_Read(Test_Csv_Paths)
##### CSV読み込み ######
##### データを分割する #####
def subseq(x, w):
seq = np.zeros((len(x) - w + 1, w))
x_np = x.iloc[:, 0]
for i in range(len(x) - w + 1):
seq[i, :] = x_np[i:w+i]
return pd.DataFrame(seq)
w_size = 100 # ウィンドウサイズ この考え方わからない→とりあえずテキトー
X_train = subseq(Train_df, w_size)
X_test = subseq(Test_df, w_size)
print(X_train.shape)
print(X_test.shape)
##### データを分割する #####
##### 正規化 #####
sc = MinMaxScaler()
# 正規化
X_train = sc.fit_transform(X_train)
X_test = sc.fit_transform(X_test)
##### 正規化 #####
##### モデル作成 #####
l1=10e-9 # L1正則化のパラメータ
enc_dim = 512 # 隠れ層のユニット数
cpu_input = Input(shape=w_size, name="cpu_input")
encoded_cpu = Dense(enc_dim, activation='relu',
activity_regularizer=tf.keras.regularizers.l1(l1))(cpu_input)
encoded_cpu = layers.Dropout(0.2)(encoded_cpu)
decoded_cpu = Dense(w_size, activation='relu',name="cpu_output1")(encoded_cpu)
# decoded_cpu = layers.Dropout(0.3)(decoded_cpu)
decoded_cpu = Dense(w_size, activation='relu',name="cpu_output2")(decoded_cpu)
autoencoder = Model(cpu_input, decoded_cpu)
autoencoder.compile(optimizer='adadelta',
loss=['binary_crossentropy','binary_crossentropy'])
##### モデル作成 #####
##### 学習 #####
epochs = 500
history = autoencoder.fit(X_train,
X_train,
epochs=epochs,
batch_size=None,
verbose=1)
##### 学習 #####
##### 学習精度確認 #####
print("loss確認")
pd.DataFrame(history.history).plot()
##### 学習精度確認 #####
##### 推論 #####
decoded_cpu = pd.DataFrame(autoencoder.predict(X_test))
##### 推論 #####
##### 異常値確認 #####
dist_cpu = np.sqrt( np.sum( (decoded_cpu - X_train)**2, axis=1))
dist_cpu.plot(color="blue")
##### 異常値確認 ######
疑問点
疑問点①
結果が良ければよかったのですが
最後の異常値確認の部分のプロットを見ると
同じデータを渡しているのに
山が出来ている(異常度高い)為、何かがおかしいと感じました
疑問点②
学習に複数サイクル分のデータを入れる必要があるはずだが
単純に波形を繋げて学習させればいいのか?
→これ関しては実際にやってみましたが、
推論させるデータが1サイクル分なので周期?が合わず
異常度を出すための計算の時にエラーが出る
そもそもちゃんと推論できている?
最後に
現状はこんな状態です
まったく見当違いのことをしている可能性が出てきたので
質問させていただきました。
なんとかして、実装させたので、みなさんの力と知恵を貸していただけると嬉しいです
よろしくお願いいたします。