識別機として作ったネットワークの中間層の値をエンコード値として使う、オートエンコーダもどきがつくりたかったのでテスト。
誤差関数には、y(OneHotにした3列のクラス値 )を入れているので、オートエンコーダではないが、実質的には同じもの
ネットワーク設計
ネットワークの設計とトレーニングはNeural Network Console(NNC)で実施。
2層では識別率が上がらなかったので、3層。
左側がエンコーダ、右側がデコーダ。
実行結果
(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)