非線形回帰モデルが生成できれば、ブラックボックス解析・リバースエンジニアリンなどに応用でき、ビジネスにも使えるよ!
!apt -y install libcusparse8.0 libnvrtc8.0 libnvtoolsext1
!ln -snf /usr/lib/x86_64-linux-gnu/libnvrtc-builtins.so.8.0 /usr/lib/x86_64-linux-gnu/libnvrtc-builtins.so
!pip install 'cupy-cuda80' 'chainer'
数値演算やChainer用のモジュールをimportします
import math
import random
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from chainer import Chain, Variable
import chainer.functions as F
import chainer.links as L
from chainer import optimizers
解析したいシステムの入出力値をセンサ等で取得します。
今回は、入力値x、出力値yの実験データ(ダミー)※を生成します。
※解析しやすい数値で”ドヤ顔”できないように、実験データは乱数で生成します
# 実験データ用の配列
x = []
y = []
get_values = 0
for i in range(10):
get_values = random.random()
x.append([i])
y.append([get_values])
# データフレーム生成(列基準)
df = pd.DataFrame({'X': x,
'Y': y})
# グラフ出力
plt.plot(x, y)
plt.title("Training Data")
plt.xlabel("input_x")
plt.ylabel("output_y")
plt.grid(True)
df
↑が解析対象の入出力関係です。
この対象をモデルベース開発などのエンジニアリングに活用するには、↑のデータを解析して対象システムの特性を把握する必要があります。
この”対象システムの特性を把握”というのは”対象の数式モデル(運動方程式)を算出”と同義と考えて良いよー。(←私的にはね)
もう少し噛砕いて説明すると、y = f(x)を算出できたということは、入力値xに対する出力値yが既知になったということです。
具体的には、このシステムに x = 5 を入力すれば、y = f(5)で出力値が得られるということ。
このように、システムの特性(入出力関係)を把握できれば、システムを制御できるようになります。
システム解析の基本は、システムを構成している部品を調べ、その部品の物理特性から運動方程式を導くのが王道です。
しかし、この手法には以下の問題があります。
このような問題があるため、システムに適当な入力を与え、そのときの出力から実験的にシステムの特性を把握するのが有効です。
…で↑のような非線形な実験データが得られると、どーやって数式モデル(運動方程式)を算出するんだよ…という問題が発生する。
この問題解決に”深層学習”を使います!!
実験値x,yをChainerで使えるようにnumpy配列のfloat32に変換する
x = Variable(np.array(x, dtype=np.float32))
y = Variable(np.array(y, dtype=np.float32))
# print(x)
# print(y)
オリジナルのニューラルネットワーク『MyChain』を設計します!
『MyChain』の重み数は”100⇒50”とした。100と50にした理由は特になし。(無理やり理由を付けるならキリの良い数字にしました。)
また、活性化関数に悩んだら"relu"使うようにしています。
class MyChain(Chain):
def __init__(self):
super(MyChain, self).__init__(
l1 = L.Linear(1, 100),
l2 = L.Linear(100, 50),
l3 = L.Linear(50, 1)
)
def predict(self, x):
h1 = F.relu(self.l1(x))
h2 = F.relu(self.l2(h1))
return self.l3(h2)
↑で設計した『MyChaine』を使うための宣言をします。
# NNモデルの宣言
model = MyChain()
print(model)
# 損失関数の計算(二乗誤差(MSE)を採用)
def forward(x, y, model):
t = model.predict(x)
loss = F.mean_squared_error(t, y)
return loss
# 最適化アルゴリズムにAdamを採用
optimizer = optimizers.Adam()
optimizer.setup(model)
# パラメータの学習を繰り返す
loss_list = []
step = []
for i in range(0, 80000): # 10000
loss = forward(x, y, model)
step.append(i)
loss_list.append(loss.data)
# print("loss: {}".format(loss.data))
optimizer.update(forward, x, y, model)
plt.plot(step, loss_list)
plt.title("Training Data")
plt.xlabel("step")
plt.ylabel("loss")
plt.grid(True)
plt.show()
plt.plot(step, loss_list)
plt.xlim([60000,70000])
plt.ylim([0,0.04])
plt.title("Training Data")
plt.xlabel("step")
plt.ylabel("loss")
plt.grid(True)
plt.show()
結果を可視化して、効果を確認します。
可視化したグラフは上から以下の順に並んでいます。
また、コードの最後に1入力1出力(SISO)の推論結果も算出してます。
今回、ランダムな数値を出力するシステムに対し、推論を行いましたが、
実存するシステムが非線形な場合でも、もう少し滑らかな出力をする可能性が高いと考えています。
その点も考慮すれば、未知の入力に対する出力値(赤プロット)は許容できるレベルかと…
# 教師データ(実験データ)
plt.plot(x.data, y.data)
plt.title("Training Data")
plt.xlabel("x axis")
plt.ylabel("y axis")
plt.grid(True)
plt.show()
# 推論結果
ym = model.predict(x)
plt.plot(x.data, ym.data)
plt.title("Predict")
plt.xlabel("input x")
plt.ylabel("output ym")
plt.grid(True)
plt.show()
# 推論結果2
xt = [[0.5], [1.8], [2.3], [3.3], [4.5], [6.8], [7.2], [7.7], [8.0], [8.2]]
xt = Variable(np.array(xt, dtype=np.float32))
yt = model.predict(xt)
plt.plot(xt.data, yt.data, "ro")
plt.title("Predict2")
plt.xlabel("input xt")
plt.ylabel("output yt")
plt.grid(True)
plt.show()
# グラフを重ねる
plt.plot(x.data, y.data)
plt.plot(x.data, ym.data)
plt.plot(xt.data, yt.data, "ro")
plt.title("comparison")
plt.xlabel("input")
plt.ylabel("output")
plt.grid(True)
plt.show()
# 1入力1出力の推論も可
n = [[5.5]]
n = Variable(np.array(n, dtype=np.float32))
yn = model.predict(n)
print(yn)
本稿では、あらゆるエンジニアリングに必須なシステム解析を深層学習で実施しました。
本記事が、ビジネスや研究で深層学習を使ってみたい!という人のヒントになれば嬉しい。
この記事で某企業のディープラーニングお兄さんから、日本のディープラーニングお兄さんになれたかな?
以上