「ゼロから作るDeep Learning」のCNNをNNgenでハードウェア化する1”の続き。

2017年の 6 月にやってみたオライリー出版社の”「ゼロから作るDeep Learning」”の deep-learning-from-scratch/ch07/ の畳み込みニューラルネットワーク(CNN)を NNgen でハードウェア化してみることにしたということで、前回は、”「ゼロから作るDeep Learning」の畳み込みニューラルネットワークのハードウェア化1”の量子化ビット数を変更して MNIST CNN を学習した。今回は、NNgen の hello_nngen.py の CNN を参考に、前回学習した MNIST CNN を NNgen のデータフローを使用した CNN として書き直した。そして、「ゼロから作るDeep Learning」のMNIST CNNの重みやバイアスの配列の形状を見て、reshapeでNNgenに合わせた。

前回学習した MNIST CNN を NNgen のデータフローを使用した CNN として書き直すにあって問題となるのは、hello_nngen.py の CNN の conv2d はパッディングがされているのだが、MNIST CNN はパッディングなしということだった。
そこで、ツィッターで NNgen の作者にお聞きしたところ、

padding='VALID'を指定するか、padding=0とすれば良いはずです

ということだったので、conv2d に”padding='VALID'”を追加した。
NNgen のデータフローを使用した CNN として書き直した MNIST CNN を示す。
85b258ab.png

31038045.png

from __future__ import absolute_import
from __future__ import print_function

import sys
import os

import nngen as ng


# data types
act_dtype = ng.int8
weight_dtype = ng.int8
bias_dtype = ng.int8
scale_dtype = ng.int8
batchsize = 1

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

# layer 0: conv2d (with bias and scale (= batchnorm)), relu, max_pool
wn0 = ng.variable(dtype=weight_dtype,
                 shape=(10, 5, 5, 1),  # Och, Ky, Kx, Ich
                 name='wn0')
bn0 = ng.variable(dtype=bias_dtype,
                 shape=(wn0.shape[0],), name='bn0')
sn0 = ng.variable(dtype=scale_dtype,
                 shape=(wn0.shape[0],), name='sn0')

a0 = ng.conv2d(input_layer, wn0,
               strides=(1, 1, 1, 1),
               bias=bn0,
               scale=sn0,
               padding='VALID',
               act_func=ng.relu,
               dtype=act_dtype,
               sum_dtype=ng.int16)

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

a0r = ng.reshape(a0p, [batchsize, -1])

# layer 1: full-connection, relu
wn1 = ng.variable(weight_dtype,
                 shape=(100, a0r.shape[-1]),
                 name='wn1')
bn1 = ng.variable(bias_dtype,
                 shape=(wn1.shape[0],),
                 name='bn1')
sn1 = ng.variable(scale_dtype,
                 shape=(wn1.shape[0],),
                 name='sn1')

a1 = ng.matmul(a0r, wn1,
               bias=bn1,
               scale=sn1,
               transposed_b=True,
               act_func=ng.relu,
               dtype=act_dtype,
               sum_dtype=ng.int16)

# layer 2: full-connection, relu
wn2 = ng.variable(weight_dtype,
                 shape=(10, a1.shape[-1]),
                 name='wn2')
bn2 = ng.variable(bias_dtype,
                 shape=(wn2.shape[0],),
                 name='bn2')
sn2 = ng.variable(scale_dtype,
                 shape=(wn2.shape[0],),
                 name='sn2')

# output
output_layer = ng.matmul(a1, wn2,
                         bias=bn2,
                         scale=sn2,
                         transposed_b=True,
                         name='output_layer',
                         dtype=act_dtype,
                         sum_dtype=ng.int16)


NNgenのMIST CNNの重みやバイアスの配列の形状を確認する
22fb3067.png

print(wn0.shape)
print(bn0.shape)
print(wn1.shape)
print(bn1.shape)
print(wn2.shape)
print(bn2.shape)
print(a0.shape)
print(a0p.shape)
print(a0r.shape)


「ゼロから作るDeep Learning」のMNIST CNNの重みやバイアスの配列の形状を見て、reshapeでNNgenに合わせる
8eba435e.png

print(network.params['W1'].shape)
print(network.params['b1'].shape)
print(network.params['W2'].shape)
print(network.params['b2'].shape)
print(network.params['W3'].shape)
print(network.params['b3'].shape)

W1n = network.params['W1'].reshape(10,5,5,1)
print(W1n.shape)
B1n = network.params['b1']
W2n=network.params['W2'].reshape(100,1440)
print(W2n.shape)
B2n = network.params['b2']
W3n=network.params['W3'].reshape(10,100)
print(W3n.shape)
B3n = network.params['b3']