FC2カウンター FPGAの部屋 2020年05月10日
FC2ブログ

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

NNgenをやってみる3(NNgen オペレーターで表す DNNのデータフロー)

NNgenをやってみる2(hello_nngen)”の続き。

前回は、NNgen/nngenGetting started の hello_nngen.py を実行した。今回は、 hello_nngen.py の Python コードの内の DNN のデータフローの NNgen オペレーターでの表し方を見ていこう。
なお、これから書くことは、私の推測を含んでいるので、間違いがあったら指摘してください。お願いします。

NNgen/nngen(1) Represent a DNN model as a dataflow by NNgen operators からコードを引用する。

入力層

# input
input_layer = ng.placeholder(dtype=act_dtype,
                             shape=(1, 32, 32, 3),  # N, H, W, C
                             name='input_layer')


shape の N は何だろうか?(バッチかな?)
H = 32 は画像の縦ピクセル、 W = 32 は画像の横ピクセル、 C = 3 はチャネルつまり、RGB 3 色ということだろう?

畳み込み層1層目 layer 0: conv2d (with bias and scale (= batchnorm)), relu, max_pool

w0 = ng.variable(dtype=weight_dtype,
                 shape=(64, 3, 3, 3),  # Och, Ky, Kx, Ich
                 name='w0')
b0 = ng.variable(dtype=bias_dtype,
                 shape=(w0.shape[0],), name='b0')
s0 = ng.variable(dtype=scale_dtype,
                 shape=(w0.shape[0],), name='s0')

a0 = ng.conv2d(input_layer, w0,
               strides=(1, 1, 1, 1),
               bias=b0,
               scale=s0,
               act_func=ng.relu,
               sum_dtype=ng.int64)

a0p = ng.max_pool_serial(a0,
                         ksize=(1, 2, 2, 1),
                         strides=(1, 2, 2, 1))


w0 の shape で Och = 64 は出力チャネルが 64 チャネルのようだ。
ky = 3 はカーネルの縦が 3 で、kx = 3 はカーネルの横が 3 のようだ。つまり 3 x 3 のカーネルを 64 個、畳み込みする。

conv2d の strides の最初の 1 は always 1 で、次の 1 が縦、その次の 1 が横、最後の 1 が always 1 なのか?
そして活性化関数は relu を使用している。
sum_dtype は途中の演算結果のデータタイプを指定しているようだ。つまり、int64 で演算する?
畳み込み層でパッディングしていないようなので、出力は 30 x 30 ピクセルになっているはず?

max_pool_serial のカーネルも最初と最後の 1 は除いて、 2 x 2 でマックス・プーリングして、stride も同様に縦 2 ピクセルと横 2 ピクセルをストライドするようだ。
2 x 2 のマックス・プーリングなので縦横 1/2 の 15 x 15 ピクセルになっているはず?

畳み込み層2層目 layer 1: conv2d, relu, reshape

w1 = ng.variable(weight_dtype,
                 shape=(64, 3, 3, a0.shape[-1]),
                 name='w1')
b1 = ng.variable(bias_dtype,
                 shape=(w1.shape[0],),
                 name='b1')
s1 = ng.variable(scale_dtype,
                 shape=(w1.shape[0],),
                 name='s1')

a1 = ng.conv2d(a0p, w1,
               strides=(1, 1, 1, 1),
               bias=b1,
               scale=s1,
               act_func=ng.relu,
               sum_dtype=ng.int64)

a1r = ng.reshape(a1, [1, -1])


w1 の a0.shape[-1] は 64 チャネル?となると、やはり 3 x 3 カーネルで出力も 64 チャネルか?
今度の畳み込み層もストライド縦横 1 ピクセル。
畳み込み層の活性化関数は relu
次が全結合層なので、reshape(a1, [1, -1]) でチャネルも2次元画像も一次元に変換している?
となると、64 チャネル x 13 ピクセル x 13 ピクセルで 10816 要素かな?

全結合層1層目 layer 2: full-connection, relu

w2 = ng.variable(weight_dtype,
                 shape=(256, a1r.shape[-1]),
                 name='w2')
b2 = ng.variable(bias_dtype,
                 shape=(w2.shape[0],),
                 name='b2')
s2 = ng.variable(scale_dtype,
                 shape=(w2.shape[0],),
                 name='s2')

a2 = ng.matmul(a1r, w2,
               bias=b2,
               scale=s2,
               transposed_b=True,
               act_func=ng.relu,
               sum_dtype=ng.int64)


a1r.shape[-1] は 10816 要素のはず、それを 256 出力の全結合層に入力する。

全結合層2層目、出力層も一緒 layer 3: full-connection, relu output

w3 = ng.variable(weight_dtype,
                 shape=(10, a2.shape[-1]),
                 name='w3')
b3 = ng.variable(bias_dtype,
                 shape=(w3.shape[0],),
                 name='b3')
s3 = ng.variable(scale_dtype,
                 shape=(w3.shape[0],),
                 name='s3')

# output
output_layer = ng.matmul(a2, w3,
                         bias=b3,
                         scale=s3,
                         transposed_b=True,
                         name='output_layer',
                         sum_dtype=ng.int64)


全結合層は 256 入力 10 出力のようだ。やはり MNIST かな?
活性化関数はなし。全結合層の出力がそのまま出力されているようだ。softmax は無いようだ。
  1. 2020年05月10日 10:51 |
  2. NNgen
  3. | トラックバック:0
  4. | コメント:0