Cucco’s Compute Hack

コンピュータ関係の記事を書いていきます。

Neural Network Consoleによる学習済みニューラルネットワークの利用(その2)

識別機として作ったネットワークの中間層の値をエンコード値として使う、オートエンコーダもどきがつくりたかったのでテスト。
誤差関数には、y(OneHotにした3列のクラス値 )を入れているので、オートエンコーダではないが、実質的には同じもの

ネットワーク設計

ネットワークの設計とトレーニングはNeural Network Console(NNC)で実施。
2層では識別率が上がらなかったので、3層。
左側がエンコーダ、右側がデコーダ

f:id:Cucco:20200523124503p:plain
ネットワーク

実行結果
(base) C:\dev\SampleCodes\hello_autoenc>python network.py
2020-05-23 12:39:58,407 [nnabla][INFO]: Initializing CPU extension...
2020-05-23 12:39:59,117 [nnabla][INFO]: Parameter load (<built-in function format>): C:\dev\SampleCodes\hello_autoenc\hello_autoenc.files\20200523_112705\results.nnp
入力データ(アヤメ3種類それぞれ1個づつ)
[[4.3 3.  1.1 0.1]
 [4.9 2.4 3.3 1. ]
 [4.9 2.5 4.5 1.7]]
もともとのネットワークの計算結果(エンコード+デコード)
[[9.9999666e-01 1.6275737e-06 1.6897608e-06]
 [1.0858843e-05 9.9997306e-01 1.6078509e-05]
 [1.0666966e-05 1.2271330e-02 9.8771799e-01]]
エンコードした値
[[1.8855007e-02 3.9558447e-08]
 [9.2018157e-01 1.9496704e-03]
 [9.9969387e-01 9.8213345e-01]]
エンコードされた値をもとに、デコードした値
[[9.9999666e-01 1.6275737e-06 1.6897608e-06]
 [1.0858843e-05 9.9997306e-01 1.6078509e-05]
 [1.0666966e-05 1.2271330e-02 9.8771799e-01]]
ソースコード

訓練結果のloadコマンドの引数ファイルが、2年前とは変わっていた。

import nnabla as nn
import nnabla.functions as F
import nnabla.parametric_functions as PF


def original_network(x, test=False):

    # Edit画面から、右クリック→Export→Python Code(NNC)
    # 引数yは削除
    # def original_network(x, y, test=False):
    # Input:x -> 4
    # Affine -> 100
    h = PF.affine(x, (100,), name='Affine')
    # ReLU
    h = F.relu(h, True)
    # Affine_2
    h = PF.affine(h, (100,), name='Affine_2')
    # ReLU_2
    h = F.relu(h, True)
    # Affine_6
    h = PF.affine(h, (100,), name='Affine_6')
    # ReLU_3
    h = F.relu(h, True)

    # Affine_3 -> 2
    h = PF.affine(h, (2,), name='Affine_3')
    # Sigmoid
    h = F.sigmoid(h)

    # Affine_7 -> 100
    h = PF.affine(h, (100,), name='Affine_7')
    # ReLU_5
    h = F.relu(h, True)
    # Affine_4
    h = PF.affine(h, (100,), name='Affine_4')
    # ReLU_6
    h = F.relu(h, True)
    # Affine_8
    h = PF.affine(h, (100,), name='Affine_8')
    # ReLU_4
    h = F.relu(h, True)
    # Affine_5 -> 3
    h = PF.affine(h, (3,), name='Affine_5')

    # Softmax
    h = F.softmax(h)

    # BinaryCrossEntropy
    # h = F.binary_cross_entropy(h, y)
    return h


def encorder_network(x, test=False):
    # original_networkの前半
    # Input:x -> 4
    # Affine -> 100
    h = PF.affine(x, (100,), name='Affine')
    # ReLU
    h = F.relu(h, True)
    # Affine_2
    h = PF.affine(h, (100,), name='Affine_2')
    # ReLU_2
    h = F.relu(h, True)
    # Affine_6
    h = PF.affine(h, (100,), name='Affine_6')
    # ReLU_3
    h = F.relu(h, True)

    # Affine_3 -> 2
    h = PF.affine(h, (2,), name='Affine_3')
    # Sigmoid
    h = F.sigmoid(h)

    return h


def decorder_network(x, test=False):
    # original_networkの後半
    # Input:x -> 2

    # Affine_7 -> 100
    h = PF.affine(x, (100,), name='Affine_7')
    # ReLU_5
    h = F.relu(h, True)
    # Affine_4
    h = PF.affine(h, (100,), name='Affine_4')
    # ReLU_6
    h = F.relu(h, True)
    # Affine_8
    h = PF.affine(h, (100,), name='Affine_8')
    # ReLU_4
    h = F.relu(h, True)
    # Affine_5 -> 3
    h = PF.affine(h, (3,), name='Affine_5')

    # Softmax
    h = F.softmax(h)

    return h


# https://support.dl.sony.com/docs-ja/%E3%83%81%E3%83%A5%E3%83%BC%E3%83%88%E3%83%AA%E3%82%A2%E3%83%AB%EF%BC%9Aneural-network-console%E3%81%AB%E3%82%88%E3%82%8B%E5%AD%A6%E7%BF%92%E6%B8%88%E3%81%BF%E3%83%8B%E3%83%A5%E3%83%BC%E3%83%A9/
# nn.load_parameters(‘{training result path}/results.nnp’)
nn.load_parameters(
    r"C:\dev\SampleCodes\hello_autoenc\hello_autoenc.files\20200523_112705\results.nnp")

x = nn.Variable((3, 4))
x.d = [4.3, 3, 1.1, 0.1], [4.9, 2.4, 3.3, 1], [4.9, 2.5, 4.5, 1.7]

print("入力データ(アヤメ3種類それぞれ1個づつ)")
print(x.d)

y_origin = original_network(x, test=True)
y_origin.forward()
print("もともとのネットワークの計算結果(エンコード+デコード)")
print(y_origin.d)

y_encoder = encorder_network(x, test=True)
y_encoder.forward()
print("エンコードした値")
print(y_encoder.d)

y_decoder = decorder_network(y_encoder, test=True)
y_decoder.forward()
print("エンコードされた値をもとに、デコードした値")
print(y_decoder.d)