FC2カウンター FPGAの部屋 TensorFlow, Keras
fc2ブログ

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

FPGAの部屋

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

「Keras Tutorial : Using pre-trained Imagenet models」を試してみる

Keras Tutorial : Using pre-trained Imagenet models」を試してみようと思う。このページでは、ImagNet で事前に学習させた各ネットワークの重みやバイアスを使用して、vgg_model、inception_model、resnet_model、mobilenet_model の実力を探る企画のようだ。

Jupyter Notebook で試してみたので、それを貼っておく。
imagenet_models_1_180813.png
imagenet_models_2_180813.png
imagenet_models_3_180813.png
imagenet_models_4_180813.png
imagenet_models_5_180813.png
imagenet_models_6_180813.png
imagenet_models_7_180813.png
imagenet_models_8_180813.png
imagenet_models_9_180813.png
imagenet_models_10_180813.png
imagenet_models_11_180813.png
imagenet_models_12_180813.png
  1. 2018年08月13日 07:05 |
  2. TensorFlow, Keras
  3. | トラックバック:0
  4. | コメント:0

Kerasで学習した重みとバイアスを使用した白線間走行用CNNのVivado プロジェクト1

だいぶ前になってしまったが、”Kerasで学習した重みとバイアスを使用した白線間走行用CNNをIPにする2”で、”カーブ、直線用白線間走行用畳み込みニューラルネットワーク13(AXI4 Stream版CNN IP 1)”の curve_conv_nn2_axis3 プロジェクトを利用して、curve_conv_nn2_axis3_k プロジェクトを作成し、Export RTLでIP 化を行った。

今回は、そのIP を使用して、”カーブ、直線用白線間走行用畳み込みニューラルネットワーク15(Vivadoプロジェクト)”のVivado プロジェクトをバージョン 2018.2 に変更し、curve_conv_nn2_axis3 を”Kerasで学習した重みとバイアスを使用した白線間走行用CNNをIPにする2”で作成したIP と交換して、ZYBO_0_182_9_k フォルダに保存した。

ZYBO_0_182_9_k フォルダのVivado 2018.2 プロジェクトを示す。
keras_curve_line_14_1808010.png

、”カーブ、直線用白線間走行用畳み込みニューラルネットワーク15(Vivadoプロジェクト)”のVivado プロジェクトと同じだが、もう一度、ブロックデザイン、Address Editor を示す。
keras_curve_line_15_1808010.png
keras_curve_line_16_1808010.png

keras_curve_line_18_1808010.png

camera_module のブロックデザインを示す。
keras_curve_line_17_1808010.png

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

タイミングエラーが出ている。
Open Implemented Design を開いて、原因を見てみよう。
keras_curve_line_20_1808010.png

やはり、curve_conv_nn2_axi3 IP でタイミングエラーが出ている。

もう一度、”Kerasで学習した重みとバイアスを使用した白線間走行用CNNをIPにする2”に戻って、Uncertainty を 2 ns に設定して、C コードの合成を行った。結果を示す。
keras_curve_line_21_1808010.png
keras_curve_line_22_1808010.png

Estimated は9.634 ns で前よりも悪くなっているが、Vivado での解析結果を見ないと何とも言えない。
Latency は、178833 クロックが 194745 クロックに延びているが、まだ、1.95 ms なので問題ない。
リソース使用量はFF と LUT が多少増えている。

Export RTLで IP 化を行った。結果を示す。
keras_curve_line_23_1808010.png

CP achiveved post-implementation が 7.937 ns になった。これで大丈夫だろう?

Vivadoプロジェクトで、curve_conv_nn2_axi3 IP を入れ替えて、もう一度、論理合成、インプリメンテーション、ビットストリームの生成を行った。結果を示す。
keras_curve_line_24_1808010.png

今度はタイミング制約を満足している。
  1. 2018年08月10日 06:47 |
  2. TensorFlow, Keras
  3. | トラックバック:0
  4. | コメント:0

Kerasで学習した重みとバイアスを使用した白線間走行用CNNをIPにする2

Kerasで学習した重みとバイアスを使用した白線間走行用CNNをIPにする1”の続き。

前回は、”カーブ、直線用白線間走行用畳み込みニューラルネットワーク13(AXI4 Stream版CNN IP 1)”の curve_conv_nn2_axis3 プロジェクトを利用して、curve_conv_nn2_axis3_k プロジェクトを作成し、C シミュレーションを行った。今回は、C コードの合成、Export RTLを行う。

C Synthesis ボタンをクリックして、C コードの合成を行った。結果を示す。
keras_curve_line_11_180804.png
keras_curve_line_12_180804.png

Estimated は 8.313 ns でTarget の 10 ns に比べて余裕がある。
Latency は 178833 クロックで、クロックが 100 MHz とすると 1.79 ms ということになる。以前は、1.94 ms だったので、Vivado HLS のバージョンが進んで最適化が進んだのかもしれない?
リソース使用量はBRAM_18Kが 13 個、DSP48E が 8 個、FF が 977 個、LUT が 2801 個で、以前と比べて大体減っているが、LUT は大幅に増えている。

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

LUT が 794 個、FF が 673 個、DSP が 3 個、BRAM が 16 個という結果になった。LUT、FF、DSP、は減っているが、BRAM は増えている。特にDSP はどうして 8 個から 3 個に減ってしまったのか?
  1. 2018年08月04日 05:42 |
  2. TensorFlow, Keras
  3. | トラックバック:0
  4. | コメント:0

Kerasで学習した重みとバイアスを使用した白線間走行用CNNをIPにする1

Kerasで学習した重みとバイアスを使用した白線間走行用CNNをVivado HLSで確かめる
Kerasで学習した重みとバイアスを使用した白線間走行用CNNをVivado HLSで確かめる2
で、Kerasで学習した重みとバイアスは使えるということが分かったので、実際にIP 化してみよう。

カーブ、直線用白線間走行用畳み込みニューラルネットワーク13(AXI4 Stream版CNN IP 1)”の curve_conv_nn2_axis3 プロジェクトを利用して、curve_conv_nn2_axis3_k プロジェクトを作成した。とりあえずは、ZYBO 用だ。

curve_conv_nn2_axis3_k プロジェクトを作成し、さっそく、C シミュレーションを行ったが、エラーとなってしまった。
keras_curve_line_8_180802.png

エラー内容は

./csim.exe: error while loading shared libraries: libOpenCL.so.1

でOpenCL のライブラリがないということかな?
ググると、”libOpenCL.so.1 error when starting claymore”がヒットした。
それによると解決策は、

sudo apt update
sudo apt install ocl-icd-opencl-dev

ということだったので、早速インストールした。
keras_curve_line_9_180802.png

その後、C シミュレーションを行ったところ、問題なく終了した。
keras_curve_line_10_180802.png

59 枚の実際にZYBOt の車載カメラから撮影した画像を使用して、エラーを見たところ、直進データはすべて正解、左旋回データもすべて正解だが、右旋回の 1 個だけ、正解は2 だけど、1 に間違っていた。

Straight error is 0

Left error is 0

*test_images_171129/right_turn_test8.bmp
correct data = 2, outs = 1
dot2[0] = -1.498047 dot2[1] = 1.787109 dot2[2] = -0.345703
Right error is 1


カーブ、直線用白線間走行用畳み込みニューラルネットワーク13(AXI4 Stream版CNN IP 1)”の curve_conv_nn2_axis3 プロジェクトでは、左旋回で 1 回、間違っていたが、今回の curve_conv_nn2_axis3 プロジェクトでは、左旋回でのエラーは無かったが、右旋回でのエラーが出てしまっている。
  1. 2018年08月03日 04:19 |
  2. TensorFlow, Keras
  3. | トラックバック:0
  4. | コメント:0

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

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

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

C コードの合成を行った。結果を示す。
keras_curve_line_6_180801.png
keras_curve_line_7_180801.png

Estimated 8.682 ns で問題ない。
Latency は 171774 クロックで、100 MHz 動作では約 1.72 ms となる。
リソース使用量はBRAM_18Kが 14 個、DSP48E が 8 個、FF が 791 個、LUT が 2704 個だった。
  1. 2018年08月01日 05:09 |
  2. TensorFlow, Keras
  3. | トラックバック:0
  4. | コメント:0

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
»