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

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

FPGAの部屋

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

Kerasで学習した重みとバイアスを使用した白線間走行用CNNをVivado HLSで確かめる

白線間走行用CNNをKerasで学習する3(各層の重みとバイアスをCのヘッダファイルに変換)”でKeras で学習した重みとバイアスをC のヘッダファイルに変換することができた。

すでに、「ゼロから作るDeep Learning」のPython コードを使用して、学習した重みとバイアスをC のヘッダファイルにしたものを使用してVivado HLSで精度を確かめたブログ記事が”カーブ、直線用白線間走行用畳み込みニューラルネットワーク11(Vivado HLS でCNN を実装)”だ。これを重みとバイアス以外は使用して、Kerasで学習した重みとバイアスのVivado HLS 2018.2 での精度を見てみよう。

なお、Kerasで学習した重みとバイアスは、前回学習した重みとバイアスではなく新たに学習しなおした重みとバイアスを使用した。学習結果を示す。

x_train shape: (34650, 1, 10, 56)
y_train shape: (34650,)
x_train shape: (34650, 10, 56, 1)
34650 train samples
26550 test samples
Train on 34650 samples, validate on 26550 samples
Epoch 1/8
34650/34650 [==============================] - 5s 154us/step - loss: 0.4760 - acc: 0.8065 - val_loss: 0.2648 - val_acc: 0.9200
Epoch 2/8
34650/34650 [==============================] - 5s 150us/step - loss: 0.2083 - acc: 0.9254 - val_loss: 0.2098 - val_acc: 0.9264
Epoch 3/8
34650/34650 [==============================] - 5s 151us/step - loss: 0.1419 - acc: 0.9484 - val_loss: 0.1368 - val_acc: 0.9551
Epoch 4/8
34650/34650 [==============================] - 5s 149us/step - loss: 0.1098 - acc: 0.9595 - val_loss: 0.1200 - val_acc: 0.9601
Epoch 5/8
34650/34650 [==============================] - 5s 150us/step - loss: 0.0908 - acc: 0.9668 - val_loss: 0.1065 - val_acc: 0.9650
Epoch 6/8
34650/34650 [==============================] - 5s 149us/step - loss: 0.0753 - acc: 0.9724 - val_loss: 0.1002 - val_acc: 0.9650
Epoch 7/8
34650/34650 [==============================] - 5s 152us/step - loss: 0.0645 - acc: 0.9763 - val_loss: 0.0983 - val_acc: 0.9666
Epoch 8/8
34650/34650 [==============================] - 5s 149us/step - loss: 0.0546 - acc: 0.9805 - val_loss: 0.0872 - val_acc: 0.9705


keras_curve_line_5_180731.png

少し、過学習のような気がするが、まあやってみよう。

Vivado HLS 2018.2 でZYBO 用の curve_conv_nn2_k プロジェクトを作成した。
keras_curve_line_1_180731.png

最初に curve_data_0_100.h をインクルードして、C シミュレーションを行った。結果を示す。
keras_curve_line_2_180731.png

hw_err_cnt = 13, sw_err_cnt = 16
hw accuracy = 95.666665%, sw accuracy = 94.666666%


300 個のデータを推論してハードウェアつまり、固定小数点演算でのエラーが 13 個、ソフトウェアつまり、浮動小数点演算でのエラーが 16 個だった。

次に、curve_data_2500_2600.h だけを生かして、C シミュレーションを行った。結果を示す。
keras_curve_line_3_180731.png

hw_err_cnt = 4, sw_err_cnt = 6
hw accuracy = 98.666668%, sw accuracy = 98.000002%


やはり300個データを推論している。

最後に、curve_data_5000_5100.h だけを生かして、C シミュレーションを行った。結果を示す。
keras_curve_line_4_180731.png

hw_err_cnt = 27, sw_err_cnt = 25
hw accuracy = 91.000003%, sw accuracy = 91.666669%


やはり300個データを推論している。

3 つの推論で合計 900 回推論しているので、
ハードウェアつまり、固定小数点演算でのエラーが 13 + 4 + 27 = 44 個
ハードウェアの精度は、(900 - (13 + 4 + 27)) / 900 *100 ≒ 95.11 %

ソフトウェアつまり、浮動小数点演算でのエラーが 16 + 6 + 25 = 47 個
ソフトウェアの精度は、(900 - (16 + 6 + 25)) / 900 *100 ≒ 94.78 %

前回よりも精度は、出ている。
  1. 2018年07月31日 05:07 |
  2. TensorFlow, Keras
  3. | トラックバック:0
  4. | コメント:0

白線間走行用CNNをKerasで学習する4(白線走行用テスト・データの一部をC のヘッダ・ファイルに変換)

白線間走行用CNNをKerasで学習する3(各層の重みとバイアスをCのヘッダファイルに変換)”の続き。

前回は、重みやバイアスをPython コードを使用して C 言語のヘッダファイルに変換した。今回は、白線走行用テスト・データの一部をC のヘッダ・ファイルに変換する。

MNISTのデータの一部をC のヘッダファイルに変換するPython コードは前から作っていて、”TensorFlow + Kerasを使ってみた12(MNISTのデータの一部をC のヘッダに変換)”でもMNISTのデータの一部をC のヘッダ・ファイルに変換した。
今回は、白線走行用テスト・データなので、シャッフルされていないので、シャッフルしてから、1000個の白線走行用テスト・データをC ヘッダ・ファイルに変換する。やってみると、量子化した固定小数点数のメンバに、[] が付いてしまった。よって、[] を取り除くコードを追加した。

x_test_str = x_test_str[1:] # 文字列の内で最初の文字を削除
x_test_str = x_test_str[:-1] # 文字列の内で最後の文字を削除


Python コードを貼っておく。

# 白線走行用テスト・データをCの配列に出力し、ファイルに書き込み
# 2018/07/30 by marsee

# coding: utf-8
import sys, os
sys.path.append(os.pardir)
from dataset_curve.curve_dataset import load_mnist

import numpy as np
import datetime

OUTPUT_DATA_NUM = 1000 # 出力するMNISTのテストデータ数 10000までの数
OFFSET = 0 # MNISTデータセットのオフセット、100だったら100番目からOUTPUT_DATA_NUM個を出力する

# データの読み込み
(x_train, y_train), (x_test, y_test) = load_mnist(normalize=False, flatten=False)

# トレーニングデータとテストデータをシャッフル
trainzip = list(zip(y_train, x_train))
np.random.shuffle(trainzip)
y_train, x_train = zip(*trainzip)
x_train = np.asarray(x_train)
y_train = np.asarray(y_train)

testzip = list(zip(y_test, x_test))
np.random.shuffle(testzip)
y_test, x_test = zip(*testzip)
x_test = np.asarray(x_test)
y_test = np.asarray(y_test)

img_rows, img_cols = 10, 56
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 /= 256
x_test /= 256

print(x_test.shape)

f = open("curve_line_data.h", 'w')
todaytime = datetime.datetime.today()
f.write('// curve_line_data.h\n')
strdtime = todaytime.strftime("%Y/%m/%d %H:%M:%S")
f.write('// {0} by marsee\n'.format(strdtime))
f.write("\n")

f.write('ap_ufixed<8, 0, AP_TRN, AP_WRAP> x_test['+str(OUTPUT_DATA_NUM)+']['+str(x_test.shape[1]*x_test.shape[2])+'] = {\n')
for i in range(OFFSET, OFFSET+OUTPUT_DATA_NUM):
    f.write("\t{")
    for j in range(x_test.shape[1]):
        for k in range(x_test.shape[2]):
            if (x_test[i][j][k] == 1.0):
                x_test[i][j][k] = x_test[i][j][k] * 256
                x_test[i][j][k] = (x_test[i][j][k]-1)/256
            x_test_str = str(x_test[i][j][k])
            x_test_str = x_test_str[1:]  # 文字列の内で最初の文字を削除
            x_test_str = x_test_str[:-1] # 文字列の内で最後の文字を削除
            f.write(x_test_str)
            if (j==x_test.shape[1]-1 and k==x_test.shape[2]-1):
                if (i==OFFSET+OUTPUT_DATA_NUM-1):
                    f.write("}\n")
                else:
                    f.write("},\n")
            else:
                f.write(", ")
f.write("};\n")

f.write('int x_test_256['+str(OUTPUT_DATA_NUM)+']['+str(x_test.shape[1]*x_test.shape[2])+'] = {\n')
for i in range(OFFSET, OFFSET+OUTPUT_DATA_NUM):
    f.write("\t{")
    for j in range(x_test.shape[1]):
        for k in range(x_test.shape[2]):
            f.write(str(int(x_test[i][j][k]*256)))
            if (j==x_test.shape[1]-1 and k==x_test.shape[2]-1):
                if (i==OFFSET+OUTPUT_DATA_NUM-1):
                    f.write("}\n")
                else:
                    f.write("},\n")
            else:
                f.write(", ")
f.write("};\n")

f.write("\n")
f.write('int y_test['+str(OUTPUT_DATA_NUM)+'] = {\n')
for i in range(OFFSET, OFFSET+OUTPUT_DATA_NUM):
    f.write(str(y_test[i]))
    if (i==OFFSET+OUTPUT_DATA_NUM-1):
        f.write("};\n")
    else:
        f.write(", ")
        
f.close() 


出力された curve_line_data.h の一部を示す。
keras_mnist_zero_19_180730.png
  1. 2018年07月30日 04:45 |
  2. TensorFlow, Keras
  3. | トラックバック:0
  4. | コメント:0

白線間走行用CNNをKerasで学習する3(各層の重みとバイアスをCのヘッダファイルに変換)

白線間走行用CNNをKerasで学習する2(各層の重みとバイアスの統計情報)”の続き。

前回は、学習した結果の重みやバイアスの統計情報を見た。今回は、その重みやバイアスをPython コードを使用して C 言語のヘッダファイルに変換してみよう。

重みやバイアスを C のヘッダファイルに変換するPython コードは以下のブログ記事を見てほしい。

TensorFlow + Kerasを使ってみた9(畳み込み層の重みをC のヘッダに変換)
TensorFlow + Kerasを使ってみた10(バイアスをC のヘッダに変換)


これらのPython コードを使用して、畳み込み層、全結合層第1層目、全結合層第2層目の重みとバイアスを C ヘッダファイルに変換した。

畳み込み層の重みとバイアスの C ヘッダファイルを示す。
keras_mnist_zero_13_180729.png

keras_mnist_zero_14_180729.png

全結合層第1層目の重みとバイアスの C ヘッダファイルの一部を示す。
keras_mnist_zero_15_180729.png

keras_mnist_zero_16_180729.png

全結合層第2層目の重みとバイアスの C ヘッダファイルの一部を示す。
keras_mnist_zero_17_180729.png

keras_mnist_zero_18_180729.png

全結合層第2層目の重みは、最大値が 1.27 程度なのだが、ハードウェアにするときの固定小数点のビット幅は、整数部が 1 ビット、小数部が 8 ビットなので、表現できる数は、-1.0 ~ (1.0 - 1/256) なので、1.27 は飽和演算されて、1.0 - 1/256 に変更される。
  1. 2018年07月29日 05:45 |
  2. TensorFlow, Keras
  3. | トラックバック:0
  4. | コメント:0

白線間走行用CNNをKerasで学習する2(各層の重みとバイアスの統計情報)

白線間走行用CNNをKerasで学習する”の続き。

前回は、白線間走行用CNN をKeras で学習できた。今回は、学習した結果の重みやバイアスの統計情報を見ていこう。

まずは、層の構成から見ていく。
_________________________________________________________________

Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_22 (Conv2D)           (None, 6, 52, 2)          52        
_________________________________________________________________
activation_64 (Activation)   (None, 6, 52, 2)          0         
_________________________________________________________________
max_pooling2d_22 (MaxPooling (None, 3, 26, 2)          0         
_________________________________________________________________
flatten_22 (Flatten)         (None, 156)               0         
_________________________________________________________________
dense_43 (Dense)             (None, 100)               15700     
_________________________________________________________________
activation_65 (Activation)   (None, 100)               0         
_________________________________________________________________
dense_44 (Dense)             (None, 3)                 303       
_________________________________________________________________
activation_66 (Activation)   (None, 3)                 0         
=================================================================
Total params: 16,055
Trainable params: 16,055
Non-trainable params: 0


畳み込み層の統計情報を見ていく。

conv_layer_bias = [-0.3386867 -0.5459513]
np.max(conv_layer_weight) = 0.6478661894798279
np.min(conv_layer_weight) = -0.44461962580680847
np.max(abs_conv_layer_weight) = 0.6478661894798279
np.min(abs_conv_layer_weight) = 0.01398547738790512
np.max(conv_layer_bias) = -0.3386867046356201
np.min(conv_layer_bias) = -0.5459513068199158
np.max(abs_conv_layer_bias) = 0.5459513068199158
np.min(abs_conv_layer_bias) = 0.3386867046356201
conv_output = (26550, 6, 52, 2)
np.std(conv_output) = 0.2930081784725189
np.max(conv_output) = 1.9703364372253418
np.min(conv_output) = -0.6579744815826416
np.max(abs_conv) = 1.9703364372253418
np.min(abs_conv) = 7.748603820800781e-07


畳み込み層の重みの最大値は約 0.65 で、最小値は約 -0.44 だった。(この下からは約を外します)
重みの絶対値の最小値は 0.014 程度だった。
バイアスの最大値は -0.34 で、最小値は -0.55 だった。バイアスの絶対値の最小値は 0.34 だった。
畳み込み層の出力の最大値は 1.97 で、最小値は -0.66 だった。
畳み込み層の重みとバイアスのグラフを示す。
keras_mnist_zero_10_180729.png

次に、全結合層第1層目の統計情報を見ていく。

np.max(dence_layer1_weight) = 0.6284171938896179
np.min(dence_layer1_weight) = -0.452088862657547
np.max(abs_dence_layer1_weight) = 0.6284171938896179
np.min(abs_dence_layer1_weight) = 2.8568319976329803e-07
np.max(dence_layer1_bias) = 0.11784756183624268
np.min(dence_layer1_bias) = -0.08143308758735657
np.max(abs_dence_layer1_bias) = 0.11784756183624268
np.min(abs_dence_layer1_bias) = 0.0
dence_layer1_output = (26550, 100)
np.std(dence_layer1_output) = 0.9401099681854248
np.max(dence_layer1_output) = 5.256106853485107
np.min(dence_layer1_output) = -5.39329195022583
np.max(abs_dence_layer1_output) = 5.39329195022583
np.min(abs_dence_layer1_output) = 8.740462362766266e-07


全結合層第1層目の重みの最大値は 0.63 、最小値は -0.45 だった。バイアスの最大値は 0.12 、最小値は -0.08 だった。
全結合層第1層目の出力の最大値は 5.26 、最小値は -5.39 だった。
全結合層第1層目の重みとバイアスのグラフを示す。
keras_mnist_zero_11_180729.png

最後に全結合層第2層目の統計情報を見ていく。

np.max(dence_layer2_weight) = 1.2727510929107666
np.min(dence_layer2_weight) = -1.23631751537323
np.max(abs_dence_layer2_weight) = 1.2727510929107666
np.min(abs_dence_layer2_weight) = 0.002743939170613885
np.max(dence_layer2_bias) = 0.009167053736746311
np.min(dence_layer2_bias) = -0.028219975531101227
np.max(abs_dence_layer2_bias) = 0.028219975531101227
np.min(abs_dence_layer2_bias) = 0.007371054962277412
dence_layer2_output = (26550, 3)
np.std(dence_layer2_output) = 5.037158012390137
np.max(dence_layer2_output) = 17.514923095703125
np.min(dence_layer2_output) = -16.942663192749023
np.max(abs_dence_layer2_output) = 17.514923095703125
np.min(abs_dence_layer2_output) = 0.00031781941652297974


全結合層第2層目の重みの最大値は 1.27 で、最小値は 0.003 だった。バイアスの最大値は 0.009 で、最小値は -0.03 だった。
全結合層第2層目の出力の最大値は 17.51 で、最小値は -16.94 だった。
全結合層第2層目の重みとバイアスのグラフを示す。
keras_mnist_zero_12_180729.png
  1. 2018年07月28日 05:15 |
  2. TensorFlow, Keras
  3. | トラックバック:0
  4. | コメント:0

白線間走行用CNNをKerasで学習する

「ゼロから作るDeep Learning」のMNISTデータを使用してKerasで学習する”で「ゼロから作るDeep Learning」のMNISTデータを使用してKerasで学習した。今回は、白線間走行用CNN をKeras で学習する。

まずは、白線間走行用CNN の学習データはデータのシャッフルができていないので、今回 Keras で学習するときにデータをシャッフルしたい。ミニバッチで学習するときに不利だと思うからだ。
Python でトレーニングデータをシャッフルするのだが、トレーニング用のラベルデータも同時にシャッフルする必要がある。どうやるか考えながら検索していると、”zip()を使って複数配列(array, list)をshuffleする-python”を見つけた。これはやりたいことにぴったりだった。
実際に使用したPython コードを示す。

(x_train, y_train), (x_test, y_test) = load_mnist(normalize=False, flatten=False)
print('x_train shape:', x_train.shape)
print('y_train shape:', y_train.shape)

# トレーニングデータとテストデータをシャッフル
trainzip = list(zip(y_train, x_train))
np.random.shuffle(trainzip)
y_train, x_train = zip(*trainzip)
x_train = np.asarray(x_train)
y_train = np.asarray(y_train)

testzip = list(zip(y_test, x_test))
np.random.shuffle(testzip)
y_test, x_test = zip(*testzip)
x_test = np.asarray(x_test)
y_test = np.asarray(y_test)


結果を示す。
keras_mnist_zero_6_180727.png
keras_mnist_zero_7_180727.png
keras_mnist_zero_8_180727.png

x_train shape: (34650, 1, 10, 56)
y_train shape: (34650,)
x_train shape: (34650, 10, 56, 1)
34650 train samples
26550 test samples
Train on 34650 samples, validate on 26550 samples
Epoch 1/8
34650/34650 [==============================] - 6s 170us/step - loss: 0.5659 - acc: 0.7551 - val_loss: 0.4968 - val_acc: 0.7847
Epoch 2/8
34650/34650 [==============================] - 5s 152us/step - loss: 0.2709 - acc: 0.8988 - val_loss: 0.2481 - val_acc: 0.9006
Epoch 3/8
34650/34650 [==============================] - 5s 152us/step - loss: 0.1726 - acc: 0.9386 - val_loss: 0.1631 - val_acc: 0.9456
Epoch 4/8
34650/34650 [==============================] - 5s 158us/step - loss: 0.1273 - acc: 0.9540 - val_loss: 0.2028 - val_acc: 0.9261
Epoch 5/8
34650/34650 [==============================] - 5s 158us/step - loss: 0.1025 - acc: 0.9616 - val_loss: 0.1651 - val_acc: 0.9376
Epoch 6/8
34650/34650 [==============================] - 6s 163us/step - loss: 0.0861 - acc: 0.9673 - val_loss: 0.1170 - val_acc: 0.9532
Epoch 7/8
34650/34650 [==============================] - 5s 154us/step - loss: 0.0760 - acc: 0.9705 - val_loss: 0.1007 - val_acc: 0.9618
Epoch 8/8
34650/34650 [==============================] - 5s 153us/step - loss: 0.0672 - acc: 0.9733 - val_loss: 0.0957 - val_acc: 0.9647


テストデータでの精度は 0.9647 だった。
この白線間走行用CNN の学習は、うまく行かないことも多い。何度もトライして一番良さそうな値を採用した。
epochs ごとの精度のグラフを示す。
keras_mnist_zero_9_180727.png

テストデータがあばれているのが分かる。
最後にPython コードを貼っておく。

# My Mnist CNN (Convolution layerの特徴マップは5個)
# Conv2D - ReLU - MaxPooling - Dence - ReLU - Dence
# 2018/05/25 by marsee
# Keras / Tensorflowで始めるディープラーニング入門 https://qiita.com/yampy/items/706d44417c433e68db0d
# のPythonコードを再利用させて頂いている

import sys, os
sys.path.append(os.pardir)  # 親ディレクトリのファイルをインポートするための設定
from dataset_curve.curve_dataset import load_mnist
import keras
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D, Activation
from keras import backend as K

import numpy as np

batch_size = 128
num_classes = 3
epochs = 8

img_rows, img_cols = 10, 56

(x_train, y_train), (x_test, y_test) = load_mnist(normalize=False, flatten=False)
print('x_train shape:', x_train.shape)
print('y_train shape:', y_train.shape)

# トレーニングデータとテストデータをシャッフル
trainzip = list(zip(y_train, x_train))
np.random.shuffle(trainzip)
y_train, x_train = zip(*trainzip)
x_train = np.asarray(x_train)
y_train = np.asarray(y_train)

testzip = list(zip(y_test, x_test))
np.random.shuffle(testzip)
y_test, x_test = zip(*testzip)
x_test = np.asarray(x_test)
y_test = np.asarray(y_test)

#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)

model = Sequential()
model.add(Conv2D(2, kernel_size=(5, 5),
                 input_shape=input_shape))
model.add(Activation(activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(100))
model.add(Activation(activation='relu'))
model.add(Dense(num_classes))
model.add(Activation(activation='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年07月27日 04:32 |
  2. TensorFlow, Keras
  3. | トラックバック:0
  4. | コメント:0

「ゼロから作るDeep Learning」のMNISTデータを使用してKerasで学習する

「ゼロから作るDeep Learning」のMNISTデータを使用してKerasで学習してみた。これができると、「ゼロから作るDeep Learning」のMNISTデータの形にした白線間走行用CNNをKerasで学習させることができる。

まずは、「ゼロから作るDeep Learning」の mnist.py を使用するのだが、そのPython ファイルの入ったフォルダ dataset は、Jupyter Notebook ファイルの入った keras_mnist_zero フォルダと同じフォルダに置いてある。
keras_mnist_zero_1_180726.png

TensorFlow + Kerasを使ってみた3(以前使用したCNNを使った学習)”で使ったPython コードを使用して、(x_train, y_train), (x_test, y_test) にデータをロードする部分だけ、「ゼロから作るDeep Learning」の mnist.py を使ったコードに置き換えた。

(x_train, y_train), (x_test, y_test) = load_mnist(normalize=False, flatten=False)
print('x_train shape:', x_train.shape)
print('x_train shape:', y_train.shape)

load_mnist() の引数で、normalize=False は下のPython コードで 0 ~ 1.0 に正規化しているので、0 ~ 255 の値とした。flatten=False は、(28, 28) の手書き数字画像が必要なので指定している。
x_train, x_test にロードしたタプルの次元だが、

x_train shape: (60000, 1, 28, 28)

だったのだが、下の if 文の中の reshape で配列の形を変えている。最後が 1 次元なので、形を変えても問題無いようだ。
Python コードと学習結果を示す。
keras_mnist_zero_2_180726.png
keras_mnist_zero_3_180726.png
keras_mnist_zero_4_180726.png
keras_mnist_zero_5_180726.png
  1. 2018年07月26日 04:54 |
  2. TensorFlow, Keras
  3. | トラックバック:0
  4. | コメント:0

FILCO Majestouch2 91テンキーレス・キーボードを買いました

昨日、FILCO Majestouch2 91テンキーレス茶軸日本語配列 USB&PS2両対応 Nキーロールオーバー対応 独Cherry茶軸採用メカニカルキーボード ブラック FKBN91M/JB2 が届きました。

FPGAの部屋のブログの記事「FILCO Majestouchテンキーレス 茶軸キーボードを買いました」からちょうど8年経ちましたが、キーボードのキーがつるつるになって、特に暑い今年の夏では、指にくっついて不快なので、思い切って新品交換しました。
今度のFILCO Majestouch2 の型番は、FKBN91M/JB2 です。前は、FKBN91M/JB なので、バージョンが変わったようです。
キータッチも少し柔らかくなったような?まだ慣れないですが、前のキーボード同様に使っていきたいと思っています。
価格は、前のよりも少し上がって、12,603 円でした。
FILCO_keyboard_180725.jpg

机の上が散らかっていますが、夏暑いときは、机にタオルを引いてやっています。汗でべたべたにならないように。
  1. 2018年07月25日 04:02 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0

Ultra96用PMOD拡張ボード5

Ultra96用PMOD拡張ボード4”の続き。

前回は、フットプリントを基板上に置いて配線を行った。今回は、ガーバー・ファイルを出力してSeeedStudio で発注した。

前回、ビアを開けすぎたので、ビアを少なくして、ボード名のシルクを追加した。
なお、ビアをたくさん開ける方法は、「KiCadでベタGNDにたくさんviaを打つ」を参考にさせて頂いた。
Ultra96_ext_board_10_180724.png

さて、「KiCADからガーバーファイルを出力する方法」を参考に、ガーバー・ファイルを出力する。
ファイルからプロットを選択して、製造ファイル出力ダイアログを開いた。「KiCADからガーバーファイルを出力する方法」を参考に設定し、製造ファイル出力ボタンをクリックして、ガーバー・ファイルを出力した。
Ultra96_ext_board_11_180724.png

ドリルファイルの生成ボタンをクリックすると、ドリルファイルの生成ダイアログが表示された。
Ultra96_ext_board_12_180724.png

ドリルファイルボタンをクリックして、ドリルファイルを生成した。
Ultra96_ext_board_13_180724.png

生成されたファイルをZIP圧縮した。
Ultra96_ext_board_16_180724.png

Kicad のガーバー・ファイル・ビューアーで見てみよう。
Ultra96_ext_board_15_180724.png

大丈夫そうだ。

SeeedStudio のPCB製作ページに行って、ガーバー・ファイルをアップロードした。赤の基板にした。
Ultra96_ext_board_14_180724.png

Shipping はDHL で頼んだ。これが、$15.8 で、PCB 製造費が $4.9 で合計 $20.7 だった。
支払いはPayPal で 2,392 円だった。ドル円レートは、115.6 円だった。ちなみに現在のレートは 111.42 円 なので、4 円程度多くなっている計算だ。
  1. 2018年07月24日 05:03 |
  2. Ultra96
  3. | トラックバック:0
  4. | コメント:0

Ultra96用PMOD拡張ボード4

Ultra96用PMOD拡張ボード3”の続き。

前回は、パーツのフットプリントを作成し、部品のフットプリントを決定した。今回は、フットプリントを基板上に置いて配線を行った。

Pcbnew でネットリストをインポートして、パーツのフットプリントと配線情報を読み込んだ。フットプリントにはラッツネットがつながっている。
最初にフットプリントを配置した。

基板外形は、Edge.Cuts を選択して、”図形ライン(またはポリゴン)を入力”を選択して、基板外形を書くことができる。

基板外形は55.5 mm X 39.4 mm になった。

Freeruoter を使用して、自動で配線を行った。なお、電源、GNDの配線幅は太くした。

表面のパターンを貼っておく。
Ultra96_ext_board_6_180722.png

裏面のパターンを貼っておく。
Ultra96_ext_board_7_180722.png

両面のパターンを貼っておく。
Ultra96_ext_board_8_180722.png

(2018/07/23:追記)
ツィッターのアドバイスにより、ビアを追加した。
Ultra96_ext_board_9_180723.png
  1. 2018年07月22日 09:36 |
  2. Ultra96
  3. | トラックバック:0
  4. | コメント:0

Ultra96用PMOD拡張ボード3

Ultra96用PMOD拡張ボード2”の続き。

前回は、回路図を作成した。今回は、パーツのフットプリントを作成し、部品のフットプリントを決定した。

今回は、2つのフットプリントを作成した。
PMOD コネクタのPIN_SOCKET_2x6_ANGL と3.3Vスイッチングレギュレータの M78AR033-5.5 だ。
PIN_SOCKET_2x6_ANGL のフットプリントを示す。
Ultra96_ext_board_4_180721.png

M78AR033-5.5 のフットプリントを示す。
Ultra96_ext_board_5_180721.png

2つのフットプリントを使用し、パーツ全部のフットプリントを指定した。
Ultra96_ext_board_3_180721.png
  1. 2018年07月21日 05:20 |
  2. Ultra96
  3. | トラックバック:0
  4. | コメント:0

Ultra96のmini DisplayPort の変換ケーブル

Ultra96 ボードにはmini DisplayPort があるが家のディスプレイにはDisplayPort の入力がない。そこで、変換ケーブルを使用するわけだが、最初に買った「QTop Mini DisplayPort to HDMI変換ケーブル 高解像度4K,3D対応 Thunderbolt DP to HDMI HDTV変換アダプター 」では付属のMicroSDカードでブートしたときの画像がディスプレイに表示できなかった。

次に、「ICZI Mini Displayport VGA アダプタ ミニディスプレイポート(Thunderbolt ) - VGA 出力 PC プロジェクター ケーブル」を購入したところ、付属のMicroSDカードでブートしたときの画像がディスプレイに表示できた。
Ultra96_8_180719.jpg

あくまで、私の環境で表示できたということで、全部の環境で表示できるわけではないと思うが、ご参考までに。。。
  1. 2018年07月19日 04:58 |
  2. Ultra96
  3. | トラックバック:0
  4. | コメント:4

Ultra96用PMOD拡張ボード2

Ultra96用PMOD拡張ボードの回路図の配線が終了した。

LSF0108-Q1 の Verf_B と EN は 200 kΩ で 3.3V (Verf_Bの電圧)にプルアップするようだ。(Arduino Forum Topic: Level Shifter - LSF0108

一応配線は終了した。PMODのヘッダのシンボルも作成した。
Ultra96_ext_board_2_180717.png

(2018/07/20:追記)
2mmピッチ2x20ピンのヘッダはフリップするので、回路図上でフリップした。
秋月電子に 200KΩが無かったので、100KΩを2つ直列にした。

(2018/07/22:追記)
M78AR033-0.5の入力に C5、10uF と C6、0.1uF を追加。
  1. 2018年07月18日 05:52 |
  2. Ultra96
  3. | トラックバック:0
  4. | コメント:0

Ultra96用PMOD拡張ボード1

Ultra96用PMOD拡張ボードを作ることにした。
2mmピッチ40ピンの低速用拡張コネクタから信号を引き出してPMODに変換する予定だ。(低速用拡張コネクタは回路図の17ページ)
このコネクタの信号の電圧は、VCC_PSAUXの1.8Vなので、PMOD用の3.3Vにするには電圧変換ICが必要となる。秋月電子で売っている変換基板を使おうと思うが、ツィッターで相談したところ遅すぎるということでTIのLSF0108-Q1 にした。また、このICはMOUSER でLSF0108QPWRQ1 が売っているところも良い。

後は電源を選定する必要がある。低速用拡張コネクタには、1.8V, 5V, 入力電圧(12V)が出ているので、12V -- 3.3V 変換をとりあえず探すことにした。秋月電子の3端子型スイッチングレギュレータの「超高効率DC-DCコンバーター(3.3V0.5A) M78AR033-0.5」を選定した。入力電圧範囲はDC4.75~32V ととっても広い。

基板CADは KiCad を久しぶりに使うことにして、4.0.7 をapt でインストールした。
まずは回路図を書くということで、LSF0108 とM78AR033-0.5 のシンボルを作って、回路を書き始めた。
Ultra96_ext_board_1_180717.png
  1. 2018年07月17日 05:33 |
  2. Ultra96
  3. | トラックバック:0
  4. | コメント:0

Ultra96のGetting Startedをやってみた

Ultra96が来ました”でUltra96ボードが来たことをブログに書いたが、電源変換ケーブルが届いたので、Getting Startedをやってみた。

Ultra96 に電源ケーブルを接続して、Power スイッチを押すとUltra96が起動した。

ノートパソコンで、Ultra96_MAC address のアクセスポイントに接続した。

192.168.2.1 に接続すると、Ultra96 のWeb ページが見えた。
Ultra96_5_180716.png

Ultra96_6_180716.png

Ultra96 GPIO LEDs をクリックする。
Ultra96_7_180716.png

LED0〜LED3 をON、OFF などがの表示を変更することができる。確かに、LED はプラウザからON, OFF することが出来た。

なお、Display Port の出力も出ているということだったので、ミニDisplay Port ー HDMI 変換器を購入して、HDMI のディスプレイに接続したのだが画像が出なかった。

ミニDisplay Port に関して、写ったよとか情報を教えてください。よろしくお願いいたします。
  1. 2018年07月16日 06:55 |
  2. Ultra96
  3. | トラックバック:0
  4. | コメント:0

Accelerating SqueezeNet on FPGAの構造について2

Accelerating SqueezeNet on FPGAの構造について”の続き。

前回は、Accelerating SqueezeNet on FPGAの構造でネットワークを構成する構造体を見ていった。今回は、そのlayer_t 構造体にどんな値が入力されているかを見ていこう。

network.cppのvoid set_layers(network_t* network)で設定される層構成

第1層目(ReLU+Max Pooling付CONV層)
1. 入力高さ - 224
2. 入力幅 - 224
3. 入力チャネル数 - 3
4. 出力チャネル数 - 64
5. カーネル数 - 3
6. ストライド数 - 2
7. パディング数 - 0
8. ReLU実装 - true
9. conv実装 - true
10. fire実装 - false
11. fire_t fire_params_one - 0、コンストラクタ
12. max_pool実装 - true
13. pooling_t pool_params_one
 1. カーネル数 - 3
 2. ストライド数 - 2
14. global_pool実装 - false
15. weight_offset – 0
16. num_weights – 1792
17. img_offset – 1235496 (すべてのWeightの数)
18. output_offset – 1386024 (画像の総ピクセル数 150528を足した数)
19. scratch_offset – 1586728

第2層目
1. 入力高さ - 56
2. 入力幅 - 56
3. 入力チャネル数 - 64
4. 出力チャネル数 - 128
5. カーネル数 - -1
6. ストライド数 - -1
7. パディング数 - 0
8. ReLU実装 - true
9. conv実装 - false
10. fire実装 - true
11. fire_t fire_params_two
 1. squeeze層カーネル数 - 1
 2. squeeze層ストライド数 - 1
 3. squeeze層出力チャネル数 - 16
 4. expand層e1カーネル数 - 1
 5. expand層e1ストライド数 - 1
 6. expand層e1出力チャネル数 - 64
 7. expand層e2カーネル数 - 3
 8. expand層e2ストライド数 - 3
 9. expand層e2出力チャネル数 - 64
12. max_pool実装 - false
13. pooling_t pool_params_two - 0, コンストラクタ
14. global_pool実装 - false
15. weight_offset – 1792
16. num_weights – 11408
17. img_offset – 1386024 (前の層の出力)
18. output_offset – 1586728 (前の層のscratch_offset の値)
19. scratch_offset – 1988136

第3層目
1. 入力高さ - 56
2. 入力幅 - 56
3. 入力チャネル数 - 128
4. 出力チャネル数 - 128
5. カーネル数 - -1
6. ストライド数 - -1
7. パディング数 - 0
8. ReLU実装 - true
9. conv実装 - false
10. fire実装 - true
11. fire_t fire_params_three
 1. squeeze層カーネル数 - 1
 2. squeeze層ストライド数 - 1
 3. squeeze層出力チャネル数 - 16
 4. expand層e1カーネル数 - 1
 5. expand層e1ストライド数 - 1
 6. expand層e1出力チャネル数 - 64
 7. expand層e2カーネル数 - 3
 8. expand層e2ストライド数 - 3
 9. expand層e2出力チャネル数 - 64
12. max_pool実装 - true
13. pooling_t pool_params_three
 1. カーネル数 - 3
 2. ストライド数 - 2
14. global_pool実装 - false
15. weight_offset – 13200
16. num_weights – 12432
17. img_offset – 1586728 (前の層の出力)
18. output_offset – 1988136 (前の層のscratch_offset の値)
19. scratch_offset – 2088488

第4層目
1. 入力高さ - 28
2. 入力幅 - 28
3. 入力チャネル数 - 128
4. 出力チャネル数 - 256
5. カーネル数 - -1
6. ストライド数 - -1
7. パディング数 - 0
8. ReLU実装 - true
9. conv実装 - false
10. fire実装 - true
11. fire_t fire_params_four
 1. squeeze層カーネル数 - 1
 2. squeeze層ストライド数 - 1
 3. squeeze層出力チャネル数 - 16
 4. expand層e1カーネル数 - 1
 5. expand層e1ストライド数 - 1
 6. expand層e1出力チャネル数 - 64
 7. expand層e2カーネル数 - 3
 8. expand層e2ストライド数 - 3
 9. expand層e2出力チャネル数 - 64
12. max_pool実装 - false
13. pooling_t pool_params_four - 0, コンストラクタ
14. global_pool実装 - false
15. weight_offset – 25632
16. num_weights – 45344
17. img_offset – 1988136 (前の層の出力)
18. output_offset – 2088488 (前の層のscratch_offset の値)
19. scratch_offset – 2289192

第5層目
1. 入力高さ - 28
2. 入力幅 - 28
3. 入力チャネル数 - 256
4. 出力チャネル数 - 256
5. カーネル数 - -1
6. ストライド数 - -1
7. パディング数 - 0
8. ReLU実装 - true
9. conv実装 - false
10. fire実装 - true
11. fire_t fire_params_five
 1. squeeze層カーネル数 - 1
 2. squeeze層ストライド数 - 1
 3. squeeze層出力チャネル数 - 32
 4. expand層e1カーネル数 - 1
 5. expand層e1ストライド数 - 1
 6. expand層e1出力チャネル数 - 128
 7. expand層e2カーネル数 - 3
 8. expand層e2ストライド数 - 3
 9. expand層e2出力チャネル数 - 128
12. max_pool実装 - true
13. pooling_t pool_params_five
 1. カーネル数 - 3
 2. ストライド数 - 2
14. global_pool実装 - false
15. weight_offset – 70976
16. num_weights – 49440
17. img_offset – 2088488 (前の層の出力)
18. output_offset – 2289192 (前の層のscratch_offset の値)
19. scratch_offset – 2339368

第6層目
1. 入力高さ - 14
2. 入力幅 - 14
3. 入力チャネル数 - 256
4. 出力チャネル数 - 384
5. カーネル数 - -1
6. ストライド数 - -1
7. パディング数 - 0
8. ReLU実装 - true
9. conv実装 - false
10. fire実装 - true
11. fire_t fire_params_six
 1. squeeze層カーネル数 - 1
 2. squeeze層ストライド数 - 1
 3. squeeze層出力チャネル数 - 48
 4. expand層e1カーネル数 - 1
 5. expand層e1ストライド数 - 1
 6. expand層e1出力チャネル数 - 192
 7. expand層e2カーネル数 - 3
 8. expand層e2ストライド数 - 3
 9. expand層e2出力チャネル数 - 192
12. max_pool実装 - false
13. pooling_t pool_params_six - 0, コンストラクタ
14. global_pool実装 - false
15. weight_offset – 120416
16. num_weights – 104880
17. img_offset – 2289192 (前の層の出力)
18. output_offset – 2339368 (前の層のscratch_offset の値)
19. scratch_offset – 2414632

第7層目
1. 入力高さ - 14
2. 入力幅 - 14
3. 入力チャネル数 - 384
4. 出力チャネル数 - 384
5. カーネル数 - -1
6. ストライド数 - -1
7. パディング数 - 0
8. ReLU実装 - true
9. conv実装 - false
10. fire実装 - true
11. fire_t fire_params_seven
 1. squeeze層カーネル数 - 1
 2. squeeze層ストライド数 - 1
 3. squeeze層出力チャネル数 - 48 
 4. expand層e1カーネル数 - 1
 5. expand層e1ストライド数 - 1
 6. expand層e1出力チャネル数 - 192
 7. expand層e2カーネル数 - 3
 8. expand層e2ストライド数 - 3
 9. expand層e2出力チャネル数 - 192
12. max_pool実装 - false
13. pooling_t pool_params_seven - 0, コンストラクタ
14. global_pool実装 - false
15. weight_offset – 225296
16. num_weights – 111024
17. img_offset – 2339368 (前の層の出力)
18. output_offset – 2414632 (前の層のscratch_offset の値)
19. scratch_offset – 2489896

第8層目
1. 入力高さ - 14
2. 入力幅 - 14
3. 入力チャネル数 - 384
4. 出力チャネル数 - 512
5. カーネル数 - -1
6. ストライド数 - -1
7. パディング数 - 0
8. ReLU実装 - true
9. conv実装 - false
10. fire実装 - true
11. fire_t fire_params_eight
 1. squeeze層カーネル数 - 1
 2. squeeze層ストライド数 - 1
 3. squeeze層出力チャネル数 - 64
 4. expand層e1カーネル数 - 1
 5. expand層e1ストライド数 - 1
 6. expand層e1出力チャネル数 - 256
 7. expand層e2カーネル数 - 3
 8. expand層e2ストライド数 - 3
 9. expand層e2出力チャネル数 - 256
12. max_pool実装 - false
13. pooling_t pool_params_eight - 0, コンストラクタ
14. global_pool実装 - false
15. weight_offset – 336320
16. num_weights – 188992
17. img_offset – 2414632 (前の層の出力)
18. output_offset – 2489896 (前の層のscratch_offset の値)
19. scratch_offset – 2590248

第9層目
1. 入力高さ - 14
2. 入力幅 - 14
3. 入力チャネル数 - 512
4. 出力チャネル数 - 512
5. カーネル数 - -1
6. ストライド数 - -1
7. パディング数 - 0
8. ReLU実装 - true
9. conv実装 - false
10. fire実装 - true
11. fire_t fire_params_nine
 1. squeeze層カーネル数 - 1
 2. squeeze層ストライド数 - 1
 3. squeeze層出力チャネル数 - 64
 4. expand層e1カーネル数 - 1
 5. expand層e1ストライド数 - 1
 6. expand層e1出力チャネル数 - 256
 7. expand層e2カーネル数 - 3
 8. expand層e2ストライド数 - 3
 9. expand層e2出力チャネル数 - 256
12. max_pool実装 - false
13. pooling_t pool_params_nine - 0, コンストラクタ
14. global_pool実装 - false
15. weight_offset – 525312
16. num_weights – 197184
17. img_offset – 2489896 (前の層の出力)
18. output_offset – 2590248 (前の層のscratch_offset の値)
19. scratch_offset – 2690600

第10層目
1. 入力高さ - 14
2. 入力幅 - 14
3. 入力チャネル数 - 512
4. 出力チャネル数 - 1000
5. カーネル数 - 1
6. ストライド数 - 1
7. パディング数 - 0
8. ReLU実装 - true
9. conv実装 - true
10. fire実装 - false
11. fire_t fire_params_ten - 0, コンストラクタ
12. max_pool実装 - false
13. pooling_t pool_params_eight - 0, コンストラクタ
14. global_pool実装 - true
15. weight_offset – 722496
16. num_weights – 513000
17. img_offset – 2590248 (前の層の出力)
18. output_offset – 2690600 (前の層のscratch_offset の値)
19. scratch_offset – 2691600
  1. 2018年07月15日 05:30 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

Ultra96が来ました

昨日、Ultra96が来ました。
小さいですね。

Ultra96 のパッケージです。
Ultra96_1_180714.jpg

中を開けるとウレタンフォームで包まれています。
説明書と1枚とVivado のバウチャーが入っています。Vivado のバウチャーは必要でしたっけ?WebPACKで開発できるのでは?
Ultra96_2_180714.jpg

下を見るとMicro SDカードと袋に入ったUltra96 が。。。
Ultra96_3_180714.jpg

Ultra96 ボードです。下にZynq Ultrascale+ が付いていて、その下にファンがあって風を送るようになっています。
Ultra96_4_180714.jpg

動かすの楽しみですが、まだ電源とDCコードのアダプタが来ていません。
DCコードのアダプタは7月19日(木)に到着する予定です。そこまで電源入りません。。。
  1. 2018年07月14日 05:36 |
  2. Ultra96
  3. | トラックバック:0
  4. | コメント:0

Accelerating SqueezeNet on FPGAの構造について

Accelerating SqueezeNet on FPGAを実装してみた5(Vivado 編 4)”で一応動いているように見えているのだが、画像はロードしていないし、重みもロードされいない気がする。
今回は、Accelerating SqueezeNet on FPGAの構造をメモしてみようと思う。
まずは、network構造体に層数や重みの数と層構成(layer_t 構造体の配列)のメンバがある。

Struct network_tのメンバーについて
1. int num_layers
 1. 層数
2. int num_weights
 1. 重みの数
3. layer_t* layers
 1. 層の構造体へのポインタ


network 構造体のlayer_t* layersにリンクされるのが、layer_t 構造体だ。

Struct layer_t のメンバーについて
1. int height (h)
 1. 入力の高さ
2. int width (w)
 1. 入力の幅
3. int channel_in (chan_in)
 1. 入力チャネル数
4. int channel_out (chan_out)
 1. 出力チャネル数
5. int kernel (k)
 1. カーネル数
6. int stride (stride)
 1. ストライド数
7. int padding (pad)
 1. パッディング数
8. bool relu (relu)
 1. ReLU実装
9. bool conv (conv)
 1. conv実装
10. bool fire (fire)
 1. fire実装
11. fire_t fire_params (fire_params)
 1. fireのパラメータ
12. bool max_pool (max_pool)
 1. max_pool実装
13. pooling_t pool_params (pool_params)
 1. pool_paramsのパラメータ
14. bool global_pool (global_pool)
 1. global_pool実装
15. offset_t weight_offset (weight_offset) (ここからオプション)
 1. weight_offset(重みのアドレスへのオフセット)
 重みは最初の層ですべての重みをロードできるスペースを確保して、その次からの層は最初の層の重みを使用する。weight_offsetは最初の層の重みへのオフセット値となる
16. int num_weights (num_weights)
 1. 重みの数
17. offset_t img_offset (img_offset)
 1. 画像のアドレスへのオフセット
18. offset_t output_offset (output_offset)
 1. 出力のアドレスへのオフセット
19. offset_t scratch_offset (scratch_offset)
 scratchのオフセット(そのレイヤのメモリのオフセットの終了値を表すようだ)


layer_t構造体にリンクされるのは、 pooling_t 構造体と fire_t 構造体だ。
最初に pooling_t 構造体を示す。

Struct pooling_tのメンバーについて
1. int k (k)
 1. カーネル数
2. int stride (stride)
 1. ストライド数


fire_t 構造体を示す。

Struct fire_tのメンバーについて
1. fire_t s_k
 1. squeeze層カーネル数 (1)
2. int s_stride
 1. squeeze層ストライド数 (1)
3. int s_chan_out
 1. squeeze層出力チャネル数
4. int e1_k
 1. expand層e1カーネル数 (1)
5. int e1_stride
 1. expand層e1ストライド数 (1)
6. int e1_chan_out
 1. expand層e1出力チャネル数
7. int e2_k
 1. expand層e2カーネル数 (3)
8. int e2_stride
 1. expand層e2ストライド数 (3)
9. int e2_chan_out
 1. expand層e2出力チャネル数

  1. 2018年07月13日 05:20 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

Accelerating SqueezeNet on FPGAを実装してみた5(Vivado 編 4)

Accelerating SqueezeNet on FPGAを実装してみた4(Vivado 編 3)”の続き。

前回は、HDL Wrapper を作って、論理合成、インプリメンテーション、ビットストリームの生成を行った。今回は、ハードウェアをエクスポートして、SDKを起動して、アプリケーションソフトを起動してみよう。

最初にハードウェアをエクスポートしよう。
Vivado のFile メニューからExport -> Export Hardware... を選択する。
Export Hardware ダイアログが開く。
Inculde bitstream にチェックを入れてOK ボタンをクリックする。
squeezenet_54_180710.png

Vivado のFile メニューからLaunch SDK を選択する。
Launch SDK ダイアログが開く。
OK ボタンをクリックする。
squeezenet_55_180710.png

SDK が立ち上がった。
squeezenet_56_180710.png

SDK のFile メニューから New -> Application Project を選択する。
New Project ダイアログが開く。
Project name にsqueezenet_test と入力して、Next > ボタンをクリックする。
squeezenet_57_180710.png

次のTemplates でEmpty Application を選択する。Finish ボタンをクリックする。
squeezenet_58_180710.png

lankas/SqueezeNet”のCPU フォルダを用意する。
squeezenet_59_180710.png

lankas/SqueezeNet”のCPU フォルダのmain.cc をSDK の squeezenet_test プロジェクトの main.cc にコピーする。
squeezenet_60_180710.png

squeezenet_test -> src に、”lankas/SqueezeNet”のCPU フォルダの network.cpp, network.hpp, weight.hpp をドラックアンドドロップする。
すると、File Operation ダイアログが開くので、そのままOK ボタンをクリックする。
squeezenet_61_180710.png

コンパイル終了して、squeezenet_test.elf ができている。
squeezenet_62_180710.png

PYNQ ボードを接続して、電源ONする。
SDK のXilinx メニューからProgram FPGA を選択する。
Program FPGA ダイアログが開くので、Program ボタンをクリックする。
squeezenet_63_180710.png

FPGA をコンフィギュレーション中。
squeezenet_64_180710.png

gtkterm を sudo gtkterm で起動する。
起動したら、Configuration メニューから Port を選択する。
Configuration ダイアログで、Port を /dev/ttyUSB1に Baud Rate を 115200 に変更した。
squeezenet_66_180710.png

SDK で squeezenet_test.elf で右クリックして、右クリックメニューからRun As -> 1Launch on Hardware(System Debugger) を選択して、アプリケーションソフトを起動した。

gtkterm にメッセージが表示された。
squeezenet_67_180710.png

動いているようだが、どうも画像がロードされていない気がする。
  1. 2018年07月12日 05:18 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

Accelerating SqueezeNet on FPGAを実装してみた4(Vivado 編 3)

Accelerating SqueezeNet on FPGAを実装してみた3(Vivado 編 2)”の続き。

前回は、SqueezeNet の IP を使用した回路をVivado で作成した。今回は、HDL Wrapper を作って、論理合成、インプリメンテーション、ビットストリームの生成を行う。

まずは、Flow Navigator の横の上のウインドウのSources タブをクリックする。
pynq_sqznet_bd_i を右クリックして、右クリックメニューから、Create HDL Wrapper を選択し、pynq_sqznet_bd_wrapper を作成する。出てくるダイアログはデフォルトでOKだ。
squeezenet_68_180711.png

これで、準備が整った。なお、SqueezeNet の IP の入出力が外部に出ないのと、クロックはPS のクロックを使用していて、そのクロック制約はPS のクロックから回ってくるので、今回の制約ファイルは必要がない。

Flow Navigator のPROGRAM AND DEBUG -> Generate Bitstream をクリックする。
squeezenet_47_180710.png

No Implementation Results Available ダイアログが開く。OK ボタンをクリックする。
squeezenet_48_180710.png

Lanuch Runs ダイアログが開く。デフォルトでOK ボタンをクリックする。
squeezenet_49_180710.png

論理合成が始まる。途中でLaunch Run Critical Message が出るが気にしないで、OK ボタンをクリックする。
squeezenet_50_180710.png

ビットストリームの生成まで終了すると、Bitstream Generation Completed ダイアログが開く。Cancel ボタンをクリックする。
squeezenet_51_180710.png

結果を見てみよう。
Project Summary ボタンをクリックする。
squeezenet_52_180710.png

Project Summary を示す。
squeezenet_53_180710.png

Timing もメットしている。リソース使用量は多い。これは、float でハードウェアでも計算しているので、致し方ない。
  1. 2018年07月11日 05:08 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

Accelerating SqueezeNet on FPGAを実装してみた3(Vivado 編 2)

Accelerating SqueezeNet on FPGAを実装してみた2(Vivado 編 1)”の続き。

前回は、SqueezeNet の IP を使用するVivado 2018.2 のプロジェクトを作成しSqueezeNet の compute IP をIP Catalog に登録した。今回は、Vivado でブロックデザインを作成し、回路を作っていく。

まずは、ブロックデザインを作成する。
PROJECT MANAGER のIP INTEGRATOR のCreate Block Desgin をクリックする。
squeezenet_15_180709.png

Create Block Desgin ダイアログが開く。
Design name に pynq_sqznet_bd と入力した。OK ボタンをクリックする。
squeezenet_16_180709.png

Diagram ウインドウが立ち上がるので、中央の「+」ボタンをクリックして、IP をAdd IP する。
squeezenet_17_180709.png

選択ダイアログが開く。Search に「z」と入れると下にZYNQ7 Processing System が出てくるので、ダブルクリックしてDiagram に追加する。
squeezenet_18_180709.png

Diagram に Processing_system7_0 が追加された。
Processing_system7_0 をダブルクリックして設定を行う。
squeezenet_19_180709.png

ZYNQ7 Proessing System (5.5) が立ち上がる。
Presets をクリックして、Apply Configuration... を選択する。
squeezenet_20_180709.png

ダイアログが開く。前回ダウンロードした pynq_revC.tcl を選択して、OK ボタンをクリックする。
squeezenet_22_180709.png

すると、I/O Peripherals にチェックが入ったのがわかると思う。これで、PYNQ ボードの設定が行われた。
squeezenet_23_180709.png

左のPage Navigator からPS-PL Configuration をクリックし、AXI Non Secure Enablement -> GP Master AXI Interface -> M AXI GP0 interface にチェックを入れる。これは、compute IP のレジスタ設定用だ。
ACP Slave AXI Interface -> S AXI ACP interface にチェックを入れる。こちらはcompute IP のDMA 用のAXI Master を接続するためだ。
squeezenet_24_180709.png

Page Navigator からClock Configuration をクリックし、PL Fabric Clocks を展開してFCLK_CLK0 のRequested Freqency を 100 MHzから 85 MHz に変更する。85 MHz にしても、PLL の関係上、83.333336 MHz となる。これは、前々回、Vivado HLS のExport RTL のCP achieved post-implementation が 11.528 ns で、100 MHz で動作しないためだ。
squeezenet_25_180709.png

OK ボタンをクリックして終了すると、Processing_system7_0 の設定は終了した。
Diagram に戻って、Run Block Automation をクリックする。
squeezenet_26_180709.png

Run Block Automation ダイアログが開く。そのままOK ボタンをクリックする。
squeezenet_27_180709.png

DDR とFIXED_IO のポートが追加された。
「+」ボタンをクリックして、compute IP をAdd IP しよう。
squeezenet_28_180709.png

Search に 「comp」と入力して、Compute をダブルクリックして、Add IP する。
squeezenet_36_180709.png

compute_0 がAdd IP された。
squeezenet_37_180709.png

compute_0 をダブルクリックして設定を行う。
ダイアログが開く。CACHE value を "1111" に変更し、OK ボタンをクリックする。
squeezenet_46_180710.png

Run Block Automation をクリックする。
Run Block Automation ダイアログが開く。
All Automation にチェックを入れて、OK ボタンをクリックする。
squeezenet_41_180709.png

配線が完了した。
squeezenet_42_180709.png

Validate Design をクリックして、回路の整合性をチェックする。
squeezenet_43_180709.png

warning が出ているが、DDR のパラメータに関することやAXI ACP ポートのことなので問題ない。OK ボタンをクリックする。
squeezenet_44_180709.png

最後にRegenerate Layout をクリックしてレイアウトを最適にする。
squeezenet_45_180709.png

最終形態。(ゴジラじゃないってか?)
squeezenet_38_180709.png

Address Editor 画面を示す。
squeezenet_39_180709.png

セーブアイコンをクリックして、ブロックデザインをセーブしておく。
  1. 2018年07月10日 04:55 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

Accelerating SqueezeNet on FPGAを実装してみた2(Vivado 編 1)

Accelerating SqueezeNet on FPGAを実装してみた1(Vivado HLS編)”の続き。

前回は、”lankas/SqueezeNet”のFPGA フォルダの内容をVivado HLS 2018.2 でプロジェクトを作って確かめ、IP 化を行った。今回は、SqueezeNet の IP を使用するVivado 2018.2 のプロジェクトを作成しよう。

Vivado 2018.2 の PYNQ_squeezenet プロジェクトを作成する。
Vivado 2018.2 のWelcome 画面からCreate Project を指定して新規プロジェクトを作成した。
squeezenet_9_180709.png

新規プロジェクト作成のダイアログが開く。
Project name で、新規プロジェクトの名前を入力する。PYNQ_squeezenet にした。
squeezenet_11_180709.png


RTL プロジェクトとして作成した。
squeezenet_12_180709.png

Default Part では、Zynq-7000 の xc7z020clg400-1 を選択した。
squeezenet_13_180709.png

New Project Summary が出てFinish ボタンをクリックしてプロジェクト新規作成が終了する。
squeezenet_14_180709.png

Vivado 2018.2 のPYNQ_squeezenet プロジェクトが作成された。
squeezenet_15_180709.png

まずは、PYNQのZynq のPS のPeset 設定をダウンロードする。
PYNQ-Z1 のページに行って、Zynq Presets をダウンロードする。そしてZIP ファイルがダウンロードできるので、それを解凍しておく。pynq_revC.tcl という名前になる。
squeezenet_21_180709.png

次に、IP Catalog に Vivado HLS で作成したCompute IP を登録しよう。
もうすでに、PYNQ_squeezenet ディレクトリができているはずなので、その下に squeezenet ディレクトリを作成する。
squeezenet ディレクトリの下に、~/Vivado_HLS/PYNQ/squeezenet/solution1/impl/ip/xilinx_com_hls_compute_1_0.zip の内容をすべてコピーする。
squeezenet_29_180709.png

PROJECT MANAGER から IP Catalog をクリックする。
squeezenet_30_180709.png

IP Catalog が開いた。
squeezenet_31_180709.png

IP Catalog で右クリックし、右クリックメニューからAdd Repository... を選択する。

Repositories ダイアログで、 ~/HDL/PYNQ/PYNQ_squeezenet/squeezenet を選択して、Select ボタンをクリックする。
squeezenet_32_180709.png

Compute IP が追加された。ダイアログでOK ボタンをクリックする。
squeezenet_33_180709.png

squeezenet_34_180709.png

これで、ブロックデザインで Compute IP を使うことができる。

今日はここまでとする。
  1. 2018年07月09日 04:03 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

Accelerating SqueezeNet on FPGAを実装してみた1(Vivado HLS編)

Accelerating SqueezeNet on FPGA”を読んでいると、コードが”lankas/SqueezeNet”にあったので、Vivado HLS とVivado で実装してみよう。
今回は、”lankas/SqueezeNet”のFPGA フォルダの内容をVivado HLS 2018.2 でプロジェクトを作って確かめてみよう。

最初に、”lankas/SqueezeNet”をダウンロードして、FPGA フォルダの内容を使って、Vivado HLS 2018.2 の squeezenet プロジェクトを作成した。
squeezenet_1_180708.png

最初にC シミュレーションを行った。成功だ。
squeezenet_2_180708.png

次に C コードの合成を行った。結果を示す。
squeezenet_3_180708.png
squeezenet_4_180708.png

Latency は min 38 クロックで、max は 1620,117,190,84 クロックで、100 MHz で動作時には、1620秒つまり、27 分ということになる。
リソース使用量は、BRAM_18K で 80 % 、DSP48E で 71 % 、FF で 55 % 、LUT が 97 % 使用していて殆どリソースを使い切りそうだ。

C/RTL 協調シミュレーションを行った。
squeezenet_5_180708.png

Latency は min が 2483 クロック、avg が 17619 クロック、 max が 30632 クロックだった。ただし最後にエラーが出てしまった。どうやらRTL シミュレーションは終了しているようなので、C テストベンチに戻す時の領域が足りないのかもしれない?
m_axi INTERFACE 指示子の depth オプションを 256 k まで増やしたがダメだった。マスタの場合はアロケートされたメモリのアドレスまでの領域を確保する必要がある場合があるので、それなのかもしれない?
でも、RTL シミュレーションは終了しているようなので、波形を見る分には問題ないと思う。

C/RTL 協調シミュレーション波形を見てみよう。
squeezenet_6_180708.png
squeezenet_7_180708.png

DMA Write 、DMA Read 共、活発に動作している。

最後に、Export RTL を行った。
squeezenet_8_180708.png

CP achieved post-implementation が 11.528 ns で、100 MHz で動作しないようだ。これは、Vivado HLS で、Uncertainty を 5 ns まで順々に変えて合成しても解消できなかった。動作周波数を下げて動作させる必要があるようだ。
  1. 2018年07月08日 06:32 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

Kerasを使用したMNIST CNNで手書き文字認識11(特徴マップが10個のMNISTのCNNを再学習3)

Kerasを使用したMNIST CNNで手書き文字認識10(特徴マップが10個のMNISTのCNNを再学習2)”の続き。

前回は、Vivado HLS 2018.2 で mnist_conv_nn10_hlss_ko_dma プロジェクトを作成して、IP 化を行い、PYNQ_MNIST_CNN10_182 フォルダのVivado 2018.2 プロジェクトを作成し、論理合成、インプリメンテーション、ビットストリームの生成を行った。今回は、SDK を起動して、PYNQボードをコンフィギュレーションし、アプリケーションソフトを起動して、手書き数字の認識を行った。

まずは、PYNQ_MNIST_CNN10_182 フォルダのVivado 2018.2 プロジェクトで、ハードウェアをエクスポートし、SDK を起動した。
keras_minst_cnn_67_180702.png

PYNQボードの電源ON、SDK からビットファイルをダウンロードし、SDK で mnist_conv_soft_test.c を起動した。
手書き数字の画像を示す。
keras_minst_cnn_18_180629.jpg

まずは、1 を認識させた。
keras_minst_cnn_54_180702.png

正常に認識できた。ハードウェアの認識時間は、約 2.05 ms だった。ソフトウェアの認識時間は、約 35.0 ms だった。約 17 倍ハードウェアの方が高速ということになる。

2 を認識させた。
keras_minst_cnn_55_180702.png

正常に認識できた。

3 を認識させた。
keras_minst_cnn_56_180702.png

正常に認識できた。

4 を認識させた。
keras_minst_cnn_57_180702.png

正常に認識できた。

5 を認識させた。
keras_minst_cnn_58_180702.png

正常に認識できた。

6 を認識させた。
keras_minst_cnn_59_180702.png

正常に認識できた。

7 を認識させた。
keras_minst_cnn_60_180702.png

正常に認識できた。

8 を認識させた。
keras_minst_cnn_61_180702.png

正常に認識できた。

9 を認識させた。
keras_minst_cnn_62_180702.png

正常に認識できたが、少し上にスペースを空ける必要があった。

0 を認識させた。
keras_minst_cnn_63_180702.png

正常に認識できた。

すべての数字が正常に認識できた。ただし、9 は少し字が大きかったのか?すこし上にスペースを空ける必要があったくらいで、気持ちよく認識できた。MNISTの手書き数字のデータを学習して、カメラで撮影した自分の手書き数字の画像を認識させる実験では、特徴マップが 10 個のCNN を使う必要があった。カメラで撮影した自分の手書き数字の画像を使用して学習すれば、もう少し小さい特徴マップ数でも行けるかもしれない?
なお、特徴マップ 5 個の時は 3 個の時よりも間違っていた。
  1. 2018年07月07日 04:58 |
  2. PYNQ
  3. | トラックバック:0
  4. | コメント:0

Kerasを使用したMNIST CNNで手書き文字認識10(特徴マップが10個のMNISTのCNNを再学習2)

Kerasを使用したMNIST CNNで手書き文字認識9(特徴マップが10個のMNISTのCNNを再学習1)”の続き。

前回は、MNIST のCNN の特徴マップが10個の場合を再学習してVivado HLS で精度を確認した。今回は、Vivado HLSで精度を確認できたので、Vivado HLS 2018.2 で mnist_conv_nn10_hlss_ko_dma プロジェクトを作成して、IP 化を行い、PYNQ_MNIST_CNN10_182 フォルダのVivado 2018.2 プロジェクトを作成し、論理合成、インプリメンテーション、ビットストリームの生成を行った。

まずは、Vivado HLS 2018.2 で mnist_conv_nn10_hlss_ko_dma プロジェクトを作成した。
各パラメータは前回の値と同じとした。
keras_minst_cnn_64_180702.png

C シミュレーションを行った。エラーになってしまった。どこが原因でエラーになったのか?は分からない?
keras_minst_cnn_81_180705.png

C コードの合成を行った。
keras_minst_cnn_65_180702.png

Latency の最大値は 2.05 ms 程度だった。約 487 fps になる。
リソース使用量はBRAM_18K が 116 個、DSP48E が 169 個、FF が 10273 個、LUT が 17881 個だった。

次に Export RTL を行った。なお、Vivado synthesis, place and route にチェックを入れてある。
keras_minst_cnn_80_180705.png

LUT は 6564 個、FF が 6128 個、DSP が 172 個、BRAM が 115 個、SRL が 111 個となった。

これでIP 化ができた。
次に、PYNQ_MNIST_CNN10_182 フォルダのVivado 2018.2 プロジェクトを作成というか、特徴マップが 3 個の時のPYNQ_MNIST_CNN3_182 フォルダをPYNQ_MNIST_CNN10_182 フォルダと名前を変えた。

PYNQ_MNIST_CNN10_182 フォルダの下の hls_all_layers フォルダに特徴マップが 3 個のCNN のIP が入っているので、それを今回の特徴マップが 10 個のIP と入れ替えた。
Vivado 2018.2 プロジェクトを示す。
keras_minst_cnn_66_180702.png

ブロックデザインを示す。
keras_minst_cnn_78_180705.png

Address Editor 画面を示す。
keras_minst_cnn_79_180705.png

論理合成、インプリメンテーション、ビットストリームの生成を行った。結果を示す。
keras_minst_cnn_68_180702.png

DSP の使用量が 78 % で多くなっている。
  1. 2018年07月06日 04:48 |
  2. PYNQ
  3. | トラックバック:0
  4. | コメント:0

Kerasを使用したMNIST CNNで手書き文字認識9(特徴マップが10個のMNISTのCNNを再学習1)

Kerasを使用したMNIST CNNで手書き文字認識8(特徴マップが3個のMNISTのCNNを再学習2)”の続き。

前回は、MNIST のCNN の特徴マップが3個の時に過学習が手書き数字の誤認識に影響しているのか?を確かめるために、Epoch 数を変更して再学習を行った時の重みやバイアスをVivado HLS のC ヘッダ・ファイルとして代入した時の結果を示した。今回は、特徴マップが3個の時には、あまり精度の向上が見られなかったため、MNIST のCNN の特徴マップが10個の場合を再学習してVivado HLS で精度を確認してみようと思う。

まずは、MNIST のCNN の特徴マップが10個の場合をKeras で再度学習した。epoch = 3 とした。
keras_mnist_cnn_76_180704.png

keras_mnist_cnn_77_180704.png

np.std(conv_output) = 0.49935710430145264
np.max(conv_output) = 2.8642632961273193
np.min(conv_output) = -3.466301202774048

np.std(dence_layer1_output) = 2.0340144634246826
np.max(dence_layer1_output) = 9.999906539916992
np.min(dence_layer1_output) = -10.721842765808105

np.std(dence_layer2_output) = 6.04936408996582
np.max(dence_layer2_output) = 24.52584457397461
np.min(dence_layer2_output) = -21.551403045654297

重みとバイアスをC のヘッダ・ファイルとして出力してVivado HLS 2017.4 でC シミュレーションを行った。
keras_mnist_cnn_73_180703.png

mnist_conv_nn10_hlss.h の AFFINE_INTEGER_LEN は 5 ビットだったが、np.max(dence_layer2_output) と np.min(dence_layer2_output) を見ると、約 24.5 と約 -21.6 なので、整数部は 6 ビット必要なので、AFFINE_INTEGER_LEN を 6 とした。
keras_mnist_cnn_74_180703.png

これで、もう一度 C シミュレーションを行ったが、ハードウェアのエラーが増えてしまった。
keras_mnist_cnn_75_180703.png

小数点以下の精度が足りなかったのだろうということで、AFFINE_INTEGER_LEN を 5 ビットに戻した。

(2018/07/05 : 追記)
全結合層 2 層目の最大値が 24 程度なのに、全結合層の整数部が 5 ビットではまずい気がしてきたので、全結合層の整数部を 6 ビットにすると同時に、全結合層の総ビット数も 15 ビットから 16 ビットに変更した。
keras_mnist_cnn_82_180705.png

C シミュレーションを行ったところ、ハードウェアとソフトウェアの誤差は共に 20 個になった。
keras_mnist_cnn_83_180705.png

HW_ERROR_COUNT = 20, SW_ERROR_COUNT = 20


これで行こうと思う。
  1. 2018年07月04日 03:51 |
  2. PYNQ
  3. | トラックバック:0
  4. | コメント:0

Kerasを使用したMNIST CNNで手書き文字認識8(特徴マップが3個のMNISTのCNNを再学習2)

Kerasを使用したMNIST CNNで手書き文字認識7(特徴マップが3個のMNISTのCNNを再学習)”の続き。

前回は、過学習が手書き数字の誤認識に影響しているのか?を確かめるために、Epoch 数を変更して再学習を行って、PYNQボードに実装して手書き数字の認識を確認した。今回は、その過程でVivado HLS で行った、精度の確認を書けなかったので、それを書いておく。

学習した重みとバイアスをC ヘッダ・ファイルとして出力し、Vivado HLS の mnist_conv_nn3_hlss_k_org の同じファイル名のヘッダ・ファイルと入れ替えた。
C シミュレーションを行った。結果を示す。
keras_mnist_cnn_69_180703.png

HW_ERROR_COUNT = 26, SW_ERROR_COUNT = 25


ハードウェアの間違いが 26 個なので、精度は (1000 - 26) / 1000 x 100 = 97.4 % で、ソフトウェアの間違いは 25 個なので、精度は (1000 - 25) / 1000 x 100 = 97.5 % だった。

MNIST のCNN の各層の値域を見ると、全結合層 2 層目の最大、最小値が 21.3 と -23.7 程度なので、現在の 5 ビットでは足りない。5 ビットの範囲は +16 弱から -16 なので、値の範囲が足りない。
keras_mnist_cnn_70_180703.png

#define AFFINE_INTEGER_LEN 5

だが、

#define AFFINE_INTEGER_LEN 6

に変更した。こうすれば、 +32 弱から -32 までの値の範囲になる。
keras_mnist_cnn_71_180703.png

これで、C シミュレーションを行った。結果を示す。
keras_mnist_cnn_72_180703.png

HW_ERROR_COUNT = 22, SW_ERROR_COUNT = 25

でハードウェアの間違いが 22 個になった。ハードウェアの精度は (1000 - 22) / 1000 x 100 = 97.8 % となった。これで良いだろう。

今日はブログを 2 つ書く予定だったが、ワールドカップ・サッカーの日本 ー ベルギー戦が 2 - 0 で日本が勝っているので、応援するため、コレで終わりにする。日本頑張れ。。。後半22分。。。

(追記)
2 - 3 で負けました。残念ですが、善戦しました。。。
  1. 2018年07月03日 04:26 |
  2. PYNQ
  3. | トラックバック:0
  4. | コメント:0

Kerasを使用したMNIST CNNで手書き文字認識7(特徴マップが3個のMNISTのCNNを再学習)

Kerasを使用したMNIST CNNで手書き文字認識6(実機確認3)”の続き。

前回は、考えられる 2 つの原因の内の量子化の精度、および飽和演算について検証を行ったが、浮動小数点数による特徴マップが3個のMNISTのCNN の演算でも手書き数字を誤認識していたので、量子化の精度、および飽和演算の問題ではないという結論になった。今回は、過学習が手書き数字の誤認識に影響しているのか?を確かめるために、Epoch 数を変更して再学習を行った。

まずは、jupyter notebook で特徴マップが3個のMNISTのCNN の学習を行った。前の結果からトレーニング・データの精度とテスト・データの精度が一致するEpoch 数は 4 程度だというのが分かったので、最大Epoch 数は 4 とした。学習結果を示す。
keras_minst_cnn_51_180702.png

Epoch = 4 の時のトレーニング・データでの精度は0.9744 でテスト・データでに精度は 0.9745 だった。
グラフを示す。
keras_minst_cnn_52_180702.png

学習した重みとバイアスのC ヘッダファイルを生成して、Vivado HLS 2018.2 の mnist_conv_nn3_hlss_ko_dma プロジェクトの重みとバイアスのC ヘッダファイルと交換した。
この状態で、C コードの合成を行った。結果を示す。
keras_minst_cnn_53_180702.png

Export RTLを行って、できたIP をPYNQ_MNIST_CNN3_182 フォルダのVivado 2018.2 のプロジェクトと入れ替えた。
論理合成、インプリメンテーション、ビットストリームの生成を行った。結果を示す。
keras_minst_cnn_50_180702.png

ハードウェアをエクスポートして、SDK を立ち上げた。
浮動小数点数によるMNISTのCNN のC ヘッダファイルも新しい学習した重みとバイアスに変更した。
これで、FPGA をコンフィギュレーションし、アプリケーションソフトの mnist_conv_soft_test.elf を起動した。

最初に手書き数字の 1 を認識させた。
keras_minst_cnn_40_180701.png

1 のはずなのに、ハードウェア、ソフトウェア共に 8 と誤認識された。

2 を認識させた。
keras_minst_cnn_41_180701.png

ハードウェア、ソフトウェア共に 2 で、正解だ。

3 を認識させた。
keras_minst_cnn_42_180701.png

3 もハードウェア、ソフトウェア共に 3 で、正解だった。

4 を認識させた。
keras_minst_cnn_43_180701.png

4 のはずなのに、ハードウェア、ソフトウェア共に 8 と誤認識された。

5 を認識させた。
keras_minst_cnn_44_180701.png

5 はハードウェア、ソフトウェア共に 5 で、正解だった。

6 を認識させた。
keras_minst_cnn_45_180701.png

6 のはずなのに、ハードウェア、ソフトウェア共に 8 と誤認識された。

7 を認識させた。
keras_minst_cnn_46_180701.png

7 のはずなのに、ハードウェア、ソフトウェア共に 3 と誤認識された。

8 を認識させた。
keras_minst_cnn_47_180701.png

ハードウェア、ソフトウェア共に 8 で正解だ。

9 を認識させた。
keras_minst_cnn_48_180701.png

9 のはずなのに、ハードウェア、ソフトウェア共に 8 と誤認識した。

0 を認識させた。
keras_minst_cnn_49_180701.png

ハードウェア、ソフトウェア共に 0 で正解だ。

どうやら、過学習もカメラで撮影した私の手書き数字の認識をミスる原因ではないようだ。
  1. 2018年07月02日 04:23 |
  2. PYNQ
  3. | トラックバック:0
  4. | コメント:0

Kerasを使用したMNIST CNNで手書き文字認識6(実機確認3)

Kerasを使用したMNIST CNNで手書き文字認識5(実機確認2)”の続き。

前回は、アプリケーションソフトを動作させて、自分で書いた手書き数字を認識させたが、1, 4, 6, 7 が誤認識してしまった。以前の 10 個の特徴マップのCNN では、正常に認識しているので、量子化の精度、および飽和演算に問題があるのか?はたまた過学習になっているのかを検証することになった。今回は、考えられる 2 つの原因の内の量子化の精度、および飽和演算について検証を行った。

量子化の精度、および飽和演算について検証方法は、現在、以前の 10 個の特徴マップのCNN で行っている浮動小数点数によるCNN の演算を今回の特徴マップが 3 個のCNN で行うことだ。こうすれば、量子化の精度、および飽和演算がまずいのであれば、今回の特徴マップが 3 個のCNN の浮動小数点数による演算では、正常に手書き数字が認識できるはずである。

早速、mnist_conv_soft_test.c を特徴マップの個数を指定できるように書き換えた。そして、今回の特徴マップが 3 個の浮動小数点数用の重みのヘッダファイルを用意して、mnist_conv_soft_test.elf をRun した。
keras_minst_cnn_39_180630.png

最初に 1 にピンクの四角枠を合わせて 1 を認識させた。
keras_minst_cnn_29_180630.png

ハードウェアのCNN の認識時間は約 1.03 ms でソフトウェアでは、10.87 ms だった。ハードウェアの方はVivado HLS 2018.2 でのレイテンシとほぼ同じだった。ハードウェアの方が約 10 倍速い。
認識は 1 のはずが、固定小数点のハードウェア、浮動小数点のソフトウェア共に 3 に間違えた。

次に、2 を認識させた。
keras_minst_cnn_30_180630.png

ハードウェアでは、2 と判定され正解だったが、ソフトウェアでは、3 と判定された。

3 を認識させた。
keras_minst_cnn_31_180630.png

ハードウェア、ソフトウェア双方とも 3 で正解だ。

4 を認識させた。
keras_minst_cnn_32_180630.png

ハードウェアは 4 で正解だが、ソフトウェアは 3 で間違っている。ハードウェアも位置をシビアに調整する必要があった。

5 を認識させた。
keras_minst_cnn_33_180630.png

ハードウェアは 5 で正解dが、ソフトウェアは 3 で間違っている。

6 を認識させた。
keras_minst_cnn_34_180630.png

ハードウェア、ソフトウェア共に 8 で間違っている。

7 を認識させた。
keras_minst_cnn_35_180630.png

ハードウェアでは 7 で正解だが、ソフトウェアは 3 で間違っている。ハードウェアも位置をシビアに調整する必要があった。

8 を認識させた。
keras_minst_cnn_36_180630.png

8 はハードウェア、ソフトウェア共に正解だ。

9 を認識させた。
keras_minst_cnn_37_180630.png

9 はハードウェア、ソフトウェア共に正解だが、人間の目で上よりの位置に四角枠を設定する必要があった。

0 を認識させた。
keras_minst_cnn_38_180630.png

0 もハードウェア、ソフトウェア共に正解で問題ない。

特徴マップが 3 個の CNN の演算に浮動小数点演算を使用した結果は、1, 2, 4, 5, 6, 7 を間違えた。特徴マップが 3 個の CNN の演算に固定小数点演算を用いた結果は、1, 6 を間違えた。浮動小数点演算のほうが間違えが多いので、量子化の精度、および飽和演算が原因ではないと思う。
  1. 2018年07月01日 05:46 |
  2. PYNQ
  3. | トラックバック:0
  4. | コメント:0