”はやぶさ”の技術ノート

NNablaと深層学習で非線形回帰モデルを生成

以前、Chainerによる深層学習入門チュートリアルの記事を書いています↓

【深層学習入門】超実践!Chainerと深層学習でシステム解析する方法|はやぶさの技術ノート

これと同じことをSony製の深層学習フレームワーク "Neural Network Libraries(NNabla)" で実践してみます。

import

nnablaの各モジュールをimportします。

In [117]:
import nnabla as nn
import nnabla.functions as F
import nnabla.parametric_functions as PF
import nnabla.solvers as S

その他、今回使用する(定番)モジュールもimportします。

In [118]:
import random
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

ダミーの実験データ生成

In [119]:
# 実験データ用の配列
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
Out[119]:
X Y
0 [0] [0.48553285662222057]
1 [1] [0.5682445473171013]
2 [2] [0.2501340394599]
3 [3] [0.2755610434298492]
4 [4] [0.2096552315901229]
5 [5] [0.7021469381630536]
6 [6] [0.013578511360852086]
7 [7] [0.05954086086222077]
8 [8] [0.2561801636080614]
9 [9] [0.2793924448794002]

nnabla用の入れ物を用意

In [120]:
batch_size = 1
xt = nn.Variable((batch_size, 1))
yt = nn.Variable((batch_size, 1))

list ⇒ numpy変換

In [121]:
x = np.array(x)
y = np.array(y)

ニューラルネットワーク設計

In [122]:
def MyChain(x):    
    h1 = F.relu(PF.affine(x, 50, name = "l1"))
    h2 = F.relu(PF.affine(h1, 100, name = "l2"))
    y = PF.affine(h2, 1, name = "l3")
    return y

モデルの宣言

In [123]:
t = MyChain(xt)

損失関数とsolver定義(+パラメータを登録)

In [124]:
loss = F.mean(F.squared_error(t, yt))
solver = S.Adam()
solver.set_parameters(nn.get_parameters())

学習

In [125]:
loss_list = []
step = []
for i in range(0, 80000):
    n = random.randrange(10)
    xt.d = x[n]
    yt.d = y[n]
    
    loss.forward()
    solver.zero_grad()
    loss.backward()
    solver.update()
    loss_list.append(loss.d.copy())
    step.append(i)
    if i % 1000 == 0:  # Print for each 1000 iterations
        print(i, loss.d)
0 0.00045301687
1000 3.0827425e-06
2000 1.8982263e-08
3000 4.5757124e-06
4000 2.4628455e-06
5000 0.0015066643
6000 0.0004153926
7000 0.00035775683
8000 4.003342e-05
9000 5.2947726e-08
10000 0.0027805748
11000 2.5190453e-05
12000 7.2855346e-07
13000 0.00011313024
14000 0.0003291338
15000 0.00037526808
16000 1.5033086e-05
17000 0.000118966425
18000 0.006062618
19000 5.222312e-05
20000 1.46056245e-05
21000 0.00031599615
22000 1.0206433e-06
23000 0.001544834
24000 1.2553372e-06
25000 0.003999153
26000 4.5309218e-05
27000 7.965768e-06
28000 0.00066639937
29000 1.9856163e-06
30000 0.000103444014
31000 7.3733674e-05
32000 4.1614385e-05
33000 6.878679e-06
34000 5.4189293e-08
35000 6.970591e-08
36000 9.5094055e-07
37000 3.686685e-06
38000 7.8245125e-07
39000 6.8686774e-08
40000 2.2965828e-08
41000 1.3066386e-06
42000 1.2093526e-08
43000 1.6191848e-07
44000 2.2537881e-06
45000 1.0804545e-10
46000 8.285624e-06
47000 3.2963874e-09
48000 5.0044505e-06
49000 2.7481798e-08
50000 8.419016e-06
51000 1.514957e-10
52000 5.829125e-07
53000 1.8587524e-07
54000 3.3221035e-09
55000 0.00013502613
56000 2.5862844e-06
57000 1.3021798e-06
58000 0.00789921
59000 2.8898064e-10
60000 9.517254e-07
61000 9.672262e-07
62000 2.9355398e-09
63000 9.39526e-06
64000 4.6810343e-05
65000 6.404986e-07
66000 3.508161e-05
67000 3.721835e-05
68000 1.46397e-05
69000 2.5175396e-08
70000 3.5020528e-06
71000 2.8470424e-06
72000 2.4117096e-05
73000 0.00015579927
74000 7.582823e-07
75000 6.3268146e-10
76000 3.8131259e-06
77000 9.984251e-07
78000 1.1723699e-07
79000 2.4714078e-07
In [138]:
# 学習過程のグラフ
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([50000,70000])
plt.ylim([0,0.002])
plt.title("Training Data")
plt.xlabel("step")
plt.ylabel("loss")
plt.grid(True)
plt.show()
'''
Out[138]:
'\n# 学習過程グラフを一部拡大\nplt.plot(step, loss_list)\nplt.xlim([50000,70000])\nplt.ylim([0,0.002])\nplt.title("Training Data")\nplt.xlabel("step")\nplt.ylabel("loss")\nplt.grid(True)\nplt.show()\n'

推論準備

学習済みモデルを使って推論を行います。基本的には学習のとき同様の手順です。

nnabla用の入れ物を用意

In [139]:
xm = nn.Variable((batch_size, 1))

モデル読込み

In [140]:
ym = MyChain(xm)

推論したいデータ用意

本来はセンサ値を使うが、今回は適当な学習で使用していない未知のデータを生成した。

In [141]:
xe = np.array([[0.5], [1.8], [2.3], [3.3], [4.5], [5.4], [6.3], [6.7], [7.4], [8.2]])

推論

In [142]:
ym_list = []

for i in xe:
    xm.d = i
    ym.forward()
    ym_list.append(ym.d.copy())

推論結果

推論結果を確認します。

In [143]:
print(xe)
ym_list
[[0.5]
 [1.8]
 [2.3]
 [3.3]
 [4.5]
 [5.4]
 [6.3]
 [6.7]
 [7.4]
 [8.2]]
Out[143]:
[array([[0.5818206]], dtype=float32),
 array([[0.28624797]], dtype=float32),
 array([[0.2572706]], dtype=float32),
 array([[0.25293332]], dtype=float32),
 array([[0.48244265]], dtype=float32),
 array([[0.48221466]], dtype=float32),
 array([[0.02079037]], dtype=float32),
 array([[0.02079037]], dtype=float32),
 array([[0.14031371]], dtype=float32),
 array([[0.25689483]], dtype=float32)]

グラフ化したいのでxmに合わせてymを形状を変換します。

In [144]:
ym_test = np.reshape(ym_list, [10, 1])
ym_test
Out[144]:
array([[0.5818206 ],
       [0.28624797],
       [0.2572706 ],
       [0.25293332],
       [0.48244265],
       [0.48221466],
       [0.02079037],
       [0.02079037],
       [0.14031371],
       [0.25689483]], dtype=float32)
In [145]:
plt.plot(x, y)
plt.plot(xe, ym_test, "ro")
plt.title("comparison")
plt.xlabel("input")
plt.ylabel("output")
plt.grid(True)
plt.show()

青グラフが解析対象・赤プロットがx(少数)をMyChainに入力したときの推論結果

うん!イイ感じですね!!

学習済みモデル保存

良いモデルを生成できたので、このモデルを保存しておきます。
そうすれば、次回からは学習せずに、このモデル使って推論できます。

In [146]:
nn.save_parameters("MyChain.h5")
2019-03-02 00:18:23,241 [nnabla][INFO]: Parameter save (.h5): MyChain.h5
In [ ]: