Neural Network Console上での推論結果とNNablaを使用した推論結果が異なる

727 views
Skip to first unread message

ライニコ

unread,
Jan 6, 2018, 10:46:58 AM1/6/18
to Neural Network Console Users (JP)
はじめまして。

Neural Network Console(version 1.1.6519.49966)上で学習させたパラメータを使用して、
Neural Network Consoleで推論した結果と、
NNabla(0.9.7)を使用したPython3コード上から推論した結果が異なるという現象が発生しております。

独力では解決に詰まってしまったところがあるため、申し訳ないですがなにか情報をご教示いただければ幸いです。

以下のような、3層のConvolutionレイヤーを用い、32x32の低解像度グレースケール画像を
超解像し、高解像度グレースケール画像を生成するタスクを行おうとしております。


これをNNabla上で動作させた際に、推論結果が異なってしまっている状態です。



(a) Neural Network Consoleで推論した超解像結果は以下です。
(※簡単のため、Evaluation対象のデータは1つとしています)


(b) NNabla経由で推論した超解像結果は以下です。
(※ (a)のNeural Network Console上で推論させたデータセットと全く同じものを使用しています。)




かなり分かりづらくて申し訳ないですが、Neural Network Console上の推論結果と違い、
ほとんどの画素値が255(Normalize後の値だと1.0)近くなってしまっています。

NNablaを使用した推論コードは以下です。

# coding: utf-8

import nnabla as nn
import nnabla.functions as F
import nnabla.parametric_functions as PF
from nnabla.utils.data_iterator import data_iterator_csv_dataset
import numpy
import argparse
from PIL import Image

def network(x, y):
# Input -> 1,32,32
# Convolution -> 64,32,32
with nn.parameter_scope('Convolution'):
h = PF.convolution(x, 64, (9,9), (4,4))
# PReLU
with nn.parameter_scope('PReLU'):
h = PF.prelu(h)
# Convolution_2 -> 32,32,32
with nn.parameter_scope('Convolution_2'):
h = PF.convolution(h, 32, (5,5), (2,2))
# PReLU_2
with nn.parameter_scope('PReLU_2'):
h = PF.prelu(h)
# Convolution_3 -> 1,32,32
with nn.parameter_scope('Convolution_3'):
h = PF.convolution(h, 1, (5,5), (2,2))
# Sigmoid
h = F.sigmoid(h)
return h



if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument("-ic", "--input_csv_path", type = str, required = True)
parser.add_argument("-ih", "--input_h5_path", type = str, required = True)
args = parser.parse_args()

# prediction in NNabla
input_data = nn.Variable((1, 1, 32, 32))
correct_data = nn.Variable((1, 1, 32, 32))

nn.clear_parameters()
network_graph = network(input_data, correct_data)
nn.parameter.load_parameters(args.input_h5_path)

test_data = data_iterator_csv_dataset(args.input_csv_path, 1, shuffle=False, normalize=True, with_memory_cache=False, with_file_cache=False)
input_data.d, correct_data.d = test_data.next()
network_graph.forward()
predict_data = network_graph.d[0][0]

# output prediction image(grayscale)
predict_data *= 255
predict_data = numpy.round(predict_data)
predict_data = numpy.int32(predict_data)
Image.fromarray(numpy.uint8(predict_data)).save("tmp.png")

入力値として受け取るCSVのパスには(a)のデータセットのCSVパス、
パラメータにも(a)の推論実行に使用したh5ファイルのパスを指定しています。
実行自体は最後まで行えているので、ネットワーク入出力のshape形状が間違っているとかではなさそうです。

おそらく、NNablaを使用したコードの書き方に間違いがあるのだと思うのですが、それが何であるのか不明な状況です。
何か、間違っている部分などありましたらご指摘願います。
よろしくお願いいたします。

余談:
Neural Network Console上でPReLUレイヤーを含んだネットワークをexportすると、
以下のように関数名がPF.p_re_l_uとなり、最新のNNablaのPReLUと互換が取れない名前になってしまっているようです。
(上のコードでは手動で「PF.prelu」に直しています)
# PReLU
with nn.parameter_scope('PReLU'):
h = PF.p_re_l_u(h)
既に指摘済みの事項でしたら恐縮ですが、取り急ぎご報告まで。

Auto Generated Inline Image 1

小林由幸

unread,
Jan 9, 2018, 8:42:38 PM1/9/18
to Neural Network Console Users (JP)
ソースを拝見したところ、輝度0~255で読み込まれた画像をネットワークに入力する際、
輝度値が1/255.0されていないようです。
DATASETタブでImage Normalization (1.0/255)にチェックが入っている場合(デフォルト)、
学習時に画像の輝度値を1/255し、0.0~1.0に正規化します。

今回の実装では入力画像の輝度が実質255倍されていることになるため、
出力画像の輝度もほぼ最大値に張り付いてしまっていると考えられます。


forwardの前に、

input_data.d /= 255.0

などをお試しください。


また、PReLUのコードについてご指摘いただきありがとうございます。
今後のバージョンでの修正を検討させていただきます。

ライニコ

unread,
Jan 10, 2018, 5:26:38 AM1/10/18
to Neural Network Console Users (JP)
小林由幸様

ご回答頂き、誠にありがとうございます。

今回のケースですと、 data_iterator_csv_dataset() の引数のnormalizeをTrueにして実行しているため、
ご指摘の現象は発生しないと思います。
実際に、デバッガ上で追ってみましたがnormalize=True時には0.0~1.0に正規化された値が入力されていました。

(データセットの読み込みを行っている nnabla.utils.data_source_implements のCsvDataSourceでも
255.0で割っているようなので、間違いはないと思います)

ちなみに、ネットワーク構造のPReLUをReLUに置き換えて再学習し、network関数のみ置き換えた上で
今回の推論コードを実行したところ、学習時と同様の結果が得られました。
そのため、PReLUレイヤーとReLUレイヤーの動作上の違いが今回の問題の原因となっていると推測しますが、
はっきりとした原因は不明です。

(なんとなく、 nn.parameter_scope('PReLU') でスコープを作っているところが怪しそうですが、
スコープに対する理解が浅くはっきりとした原因は分かっていません…。)

以上、よろしくお願いいたします。

小林由幸

unread,
Jan 15, 2018, 1:28:59 AM1/15/18
to Neural Network Console Users (JP)

既に正規化した値を入力されていたのですね。
ご指摘の通り、原因はPReLUを正しく実行できていない点にあるようです。


現在ConsoleはPReLUの負の傾きを「slope」と呼んでいるのに対し、
Librariesでは「W」と呼んでおり、Consoleで学習したパラメータを
NNablaで読み込めていないことが原因と考えられます。

こちらの問題については今後のバージョンで修正する予定です。
Reply all
Reply to author
Forward
0 new messages