FC2カウンター FPGAの部屋 2018年08月11日
fc2ブログ

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

FPGAの部屋

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

SqueezeNet for MNIST 1

Squeezenet をFPGA に実装したいので、重みとバイアスを C のヘッダにしたいと思っているのだが、ImagkeNetの画像を使って学習するのも大変だけど、ImagkeNetの画像を集めて学習する方法を探っていた。その時に、SqueezeNet for MNIST を見つけた。とりあえず、MNISTのデータだったらKeras に標準で付いているし、手始めにこれをやってみることにした。それにLicense も Apache License 2.0 なので、都合が良い。
なお、統計情報を取る必要性から Activation を分けた。ReLU は独立した Activation に分けてある。
変更したSqueezeNet for MNISTを示す。なお、こちらの環境に合わせてある。
squeezenet4mnist_1_180811.png
squeezenet4mnist_2_180811.png
squeezenet4mnist_3_180811.png
squeezenet4mnist_5_180811.png

約 98.5 % の精度が出ている。

# SqueezeNet for MNIST
# 2018/08/02 by marsee
# Keras / Tensorflowで始めるディープラーニング入門 https://qiita.com/yampy/items/706d44417c433e68db0d
# のPythonコードを再利用させて頂いている
# https://www.kaggle.com/somshubramajumdar/squeezenet-for-mnist (Apache License 2.0)を引用して
# Keras 2に変更し独自のコードを加えた

import keras
from keras.datasets import mnist
from keras import backend as K
import pandas as pd
import numpy as np 
from keras.models import Model, Input
from keras.layers import Dense, Dropout, Flatten, Concatenate
from keras.layers import Conv2D, MaxPooling2D, Activation, AveragePooling2D
import keras.utils.np_utils as kutils

batch_size = 128
num_classes = 10
epochs = 5

img_rows, img_cols = 28, 28

(x_train, y_train), (x_test, y_test) = mnist.load_data()

#Kerasのバックエンドで動くTensorFlowとTheanoでは入力チャンネルの順番が違うので場合分けして書いています
if K.image_data_format() == 'channels_first':
    x_train = x_train.reshape(x_train.shape[0], 1, img_rows, img_cols)
    x_test = x_test.reshape(x_test.shape[0], 1, img_rows, img_cols)
    input_shape = (1, img_rows, img_cols)
else:
    x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
    x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)
    input_shape = (img_rows, img_cols, 1)

x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
print('x_train shape:', x_train.shape)
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')

y_train = y_train.astype('int32')
y_test = y_test.astype('int32')
y_train = keras.utils.np_utils.to_categorical(y_train, num_classes)
y_test =  keras.utils.np_utils.to_categorical(y_test, num_classes)

# Setup of SqueezeNet (http://arxiv.org/abs/1602.07360), which offers similar performance
# to AlexNet, while using drastically fewer parameters. Tested on CIFAR10, it also performs
# well on MNIST problem

# Uses the latest keras 1.0.2 Functional API

input_layer = Input(shape=(28, 28, 1), name="input")

#conv 1
conv1 = Conv2D(96, (3, 3), padding="valid", kernel_initializer="glorot_uniform", strides=(2, 2))(input_layer)
relu1 = Activation(activation='relu')(conv1)

#maxpool 1
maxpool1 = MaxPooling2D(pool_size=(2,2))(relu1)

#fire 1
fire2_squeeze = Conv2D(16, (1, 1), padding="same", kernel_initializer="glorot_uniform")(maxpool1)
relu2_squeeze = Activation(activation='relu')(fire2_squeeze)

fire2_expand1 = Conv2D(64, (1, 1), padding="same", kernel_initializer="glorot_uniform")(relu2_squeeze)
relu2_expand1 = Activation(activation='relu')(fire2_expand1)
fire2_expand2 = Conv2D(64, (3, 3), padding="same", kernel_initializer="glorot_uniform")(relu2_squeeze)
relu2_expand2 = Activation(activation='relu')(fire2_expand2)

merge1 = Concatenate()([relu2_expand1, relu2_expand2])
fire2 = Activation("linear")(merge1)

#fire 2
fire3_squeeze = Conv2D(16, (1, 1),  padding="same", kernel_initializer="glorot_uniform")(fire2)
relu3_squeeze = Activation(activation='relu')(fire3_squeeze)

fire3_expand1 = Conv2D(64, (1, 1), padding="same", kernel_initializer="glorot_uniform")(relu3_squeeze)
relu3_expand1 = Activation(activation='relu')(fire3_expand1)
fire3_expand2 = Conv2D(64, (3, 3),  padding="same", kernel_initializer="glorot_uniform")(relu3_squeeze)
relu3_expand2 = Activation(activation='relu')(fire3_expand2)

merge2 = Concatenate()([relu3_expand1, relu3_expand2])
fire3 = Activation("linear")(merge2)

#fire 3
fire4_squeeze = Conv2D(32, (1, 1), padding="same", kernel_initializer="glorot_uniform")(fire3)
relu4_squeeze = Activation(activation='relu')(fire4_squeeze)

fire4_expand1 = Conv2D(128, (1, 1), padding="same", kernel_initializer="glorot_uniform")(relu4_squeeze)
relu4_expand1 = Activation(activation='relu')(fire4_expand1)
fire4_expand2 = Conv2D(128, (3, 3), padding="same", kernel_initializer="glorot_uniform")(relu4_squeeze)
relu4_expand2 = Activation(activation='relu')(fire4_expand2)

merge3 = Concatenate()([relu4_expand1, relu4_expand2])
fire4 = Activation("linear")(merge3)

#maxpool 4
maxpool4 = MaxPooling2D((2,2))(fire4)

#fire 5
fire5_squeeze = Conv2D(32, (1, 1), padding="same", kernel_initializer="glorot_uniform")(maxpool4)
relu5_squeeze = Activation(activation='relu')(fire5_squeeze)

fire5_expand1 = Conv2D(128, (1, 1), padding="same", kernel_initializer="glorot_uniform")(relu5_squeeze)
relu5_expand1 = Activation(activation='relu')(fire5_expand1)
fire5_expand2 = Conv2D(128, (3, 3), padding="same", kernel_initializer="glorot_uniform")(relu5_squeeze)
relu5_expand2 = Activation(activation='relu')(fire5_expand2)

merge5 = Concatenate()([relu5_expand1, relu5_expand2])
fire5 = Activation("linear")(merge5)

#fire 6
fire6_squeeze = Conv2D(48, (1, 1), padding="same", kernel_initializer="glorot_uniform")(fire5)
relu6_squeeze = Activation(activation='relu')(fire6_squeeze)

fire6_expand1 = Conv2D(192, (1, 1), padding="same", kernel_initializer="glorot_uniform")(relu6_squeeze)
relu6_expand1 = Activation(activation='relu')(fire6_expand1)
fire6_expand2 = Conv2D(192, (3, 3), padding="same", kernel_initializer="glorot_uniform")(relu6_squeeze)
relu6_expand2 = Activation(activation='relu')(fire6_expand2)

merge6 = Concatenate()([relu6_expand1, relu6_expand2])
fire6 = Activation("linear")(merge6)

#fire 7
fire7_squeeze = Conv2D(48, (1, 1), padding="same", kernel_initializer="glorot_uniform")(fire6)
relu7_squeeze = Activation(activation='relu')(fire7_squeeze)

fire7_expand1 = Conv2D(192, (1, 1), padding="same", kernel_initializer="glorot_uniform")(relu7_squeeze)
relu7_expand1 = Activation(activation='relu')(fire7_expand1)
fire7_expand2 = Conv2D(192, (3, 3), padding="same", kernel_initializer="glorot_uniform")(relu7_squeeze)
relu7_expand2 = Activation(activation='relu')(fire7_expand2)

merge7 = Concatenate()([relu7_expand1, relu7_expand2])
fire7 =Activation("linear")(merge7)

#fire 8
fire8_squeeze = Conv2D(64, (1, 1), padding="same", kernel_initializer="glorot_uniform")(fire7)
relu8_squeeze = Activation(activation='relu')(fire8_squeeze)

fire8_expand1 = Conv2D(256, (1, 1), padding="same", kernel_initializer="glorot_uniform")(relu8_squeeze)
relu8_expand1 = Activation(activation='relu')(fire8_expand1)
fire8_expand2 = Conv2D(256, (3, 3), padding="same", kernel_initializer="glorot_uniform")(relu8_squeeze)
relu8_expand2 = Activation(activation='relu')(fire8_expand2)

merge8 = Concatenate()([relu8_expand1, relu8_expand2])
fire8 = Activation("linear")(merge8)

#maxpool 8
maxpool8 = MaxPooling2D((2,2))(fire8)

#fire 9
fire9_squeeze = Conv2D(64, (1, 1),  padding="same", kernel_initializer="glorot_uniform")(maxpool8)
relu9_squeeze = Activation(activation='relu')(fire9_squeeze)

fire9_expand1 = Conv2D(256, (1, 1), padding="same", kernel_initializer="glorot_uniform")(relu9_squeeze)
relu9_expand1 = Activation(activation='relu')(fire9_expand1)
fire9_expand2 = Conv2D(256, (3, 3), padding="same", kernel_initializer="glorot_uniform")(relu9_squeeze)
relu9_expand2 = Activation(activation='relu')(fire9_expand2)

merge8 = Concatenate()([relu9_expand1, relu9_expand2])
fire9 = Activation("linear")(merge8)
fire9_dropout = Dropout(0.5)(fire9)

#conv 10
conv10 = Conv2D(10, (1, 1), padding="valid", kernel_initializer="glorot_uniform")(fire9_dropout)

# The original SqueezeNet has this avgpool1 as well. But since MNIST images are smaller (1,28,28)
# than the CIFAR10 images (3,224,224), AveragePooling2D reduces the image size to (10,0,0), 
# crashing the script.

#avgpool 1
#avgpool10 = AveragePooling2D((13,13))(conv10)

flatten = Flatten()(conv10)

softmax = Dense(10, activation="softmax")(flatten)

model = Model(inputs=input_layer, outputs=softmax)


model.compile(loss=keras.losses.categorical_crossentropy,
              optimizer=keras.optimizers.Adadelta(),
              metrics=['accuracy'])
history = model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs,
          verbose=1, validation_data=(x_test, y_test))

  1. 2018年08月11日 13:31 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0