2019年3月9日土曜日

SonyのNeural Network Libraries(NNabla)でFCNもどきを学習させる







 研究室配属も無事終了した中の人です。研究室の本格始動は4月からなので、3月中はマウスの設計やFPGA、NNablaと戯れたいと思います。さて、前の投稿ではNeural Network Libraries(NNabla)でnumpy-arrayの読み込みを行いました。そこで今回は読み込んだデータを使用して、FCNもどきの学習を行いたいと思います。

今回のコードもこちらのサイトを参考に実装していきます。

NNabla(Neural Network Libraries)のシンプルチュートリアルをPython3.5でやってみる。

NNablaで学習を行う場合、
  • データセットの読み込み
  • モデルの構築
  • 損失関数の定義
  • 学習部の実装
が必要になります(この辺はほかのライブラリとあまり変わらない)。まずはデータセットの読み込み、と見せかけて必要なライブラリ群のimportとデータセットを入れたファイル名、パラメータファイルから

import nnabla as nn
import nnabla.functions as F
import nnabla.parametric_functions as PF
import nnabla.solvers as S
import nnabla.initializer as I
from nnabla.utils.data_iterator import data_iterator_simple

import os
import numpy as np

NPZ = "data/img2train_data_test.npz"
param_file = "nnabla_parameters.h5"

 データセットの読み込みはこんな感じで実装
#Read .npz File
def load_data(npz, input="img", teacher="img_test"):
    print("loading dataset for training")
    #loading data from NPZ file
    with np.load(npz) as data:
        tmp_train = data[input]
        tmp_train_label = data[teacher]
    
    print(tmp_train.shape)
    print(tmp_train_label.shape)

    return tmp_train, tmp_train_label

#Loading Data
def data_iterator_my_dateset(train, teach, batch_size=8, shuffle=False, rng=None):
    def load_func(index):
         """Loading an image and its label"""
         img = train[index]
         label = teach[index]
         return img, label
    return data_iterator_simple(load_func, train.shape[0], batch_size, shuffle, rng, with_file_cache=False)

 .npzでデータセットを保持している関係で、それを読み込む関数を実装しました。下のデータセットの取り込みは前回と同じ。
 モデルはこんな感じの奴。
#Define network
def network(x):
    with nn.parameter_scope("cnn"):
        with nn.parameter_scope("conv0"):
            h = F.relu(PF.convolution(x, 6, (2,2)))
        with nn.parameter_scope("deconv0"):
            h = F.relu(PF.deconvolution(h, 3, (2,2)))
        with nn.parameter_scope("conv1"):
            h = F.relu(PF.convolution(x, 6, (4,8), stride=(2,4)))
        with nn.parameter_scope("conv2"):
            h = F.relu(PF.convolution(h, 16, (9,9), stride=(3,3)))
        with nn.parameter_scope("deconv2"):
            h = F.relu(PF.deconvolution(h, 16, (9,9), stride=(3,3)))
        with nn.parameter_scope("deconv1"):
            h = PF.deconvolution(h, 6, (4,8), stride=(2,4))
    return h

 Raspberry Piでそこそこ速く動かそうと思うと、こうなりました。ここはもっと手を入れる予定。損失関数はSigmoid Cross Entropyを使用。

#Define Loss Function
def loss_func(y, t):
    loss_f = F.sigmoid_cross_entropy(y, t)
    return loss_f
実の話をすると損失関数に最初はSoftmax Cross Entropyを使っていたのですが、要素(今回はピクセル)ごとのクラス分類がうまくいきませんでした。(ここで1週間溶ける)
 そこで公式のDCGAN実装を見たところ Sigmoid Cross Entropyを使っていたので、使ってみたところうまく学習できました。やったね!
(1つのピクセルが各ラベルに属するかどうかを見ているのでこれでもよいってだけで、Softmax Cross Entropyでも原理的にはできるはず)(参考:損失関数の紹介 - renom.jp)
 学習部はこんな感じ。
#Define Training Function
def training(xt,tt,data,loss,steps):
     solver = S.Adam()
     solver.set_parameters(nn.get_parameters()) # Set parameter variables to be updatd.
         
     for i in range(steps):
         xt.d, tt.d = data.next()
         solver.zero_grad() # Initialize gradients of all parameters to zero.
         loss.forward()
         loss.backward()
         solver.update()
         if i % 100 == 0: # Print for each 10 iterations
              print(str(i) +":" + str(np.mean(loss.d)))


 教師データ読み込み→とりあえず勾配を初期化→推論する→誤差逆伝播→パラメータを更新、を繰り返す感じ。後はこれらを実行していく形になります。

try:
    #Loading Dataset
    train, teach = load_data(NPZ,"img","img_test")
    data = data_iterator_my_dateset(train, teach, batch_size=30, shuffle=True)

    #Set Params to network
    nn.clear_parameters()
    img, label = data.next()

    x = nn.Variable(img.shape)
    y = network(x)
    t = nn.Variable(label.shape)
    loss = loss_func(y, t)

    #Search if Params file or not
    if os.path.exists(param_file) == True:
        yn = input("parameter is exist! use this? y/n : ")
        if yn == "Y" or yn == "y":
            nn.load_parameters(param_file)

    #Training
    training(x,t,data,loss,500)
    
except:
    import traceback
    traceback.print_exc()

finally:
    #Save Params
    nn.save_parameters(param_file)
    input(">>")

パラメータのクリアをモデル構築前にするのを忘れなければうまく動くはず...です。次回は実装になるはず。この記事長すぎるのでは?
©2018 shts All Right Reserved.

0 件のコメント:

コメントを投稿