FC2カウンター FPGAの部屋 2017年08月

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

FPGAの部屋

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

白線追従走行用畳み込みニューラルネットワークの製作20(CNN IPの戦略を考える)

白線追従走行用畳み込みニューラルネットワークの製作19(Cコードの合成、IP化)”の続き。

前回で、直進のみだけど白線追従走行用畳み込みニューラルネットワークの推論用Vivado HLSのプロジェクトは完成した。ただしまだ畳み込みニューラルネットワークを固定小数点数で作って性能を確認しただけで、どのようにFPGA上の回路にするかの検討はまだしていない。今回は、どのようにFPGA上の回路にするかの検討を行っていこう。

まずは、白線追従用畳み込みニューラルネットワークを実装する基板だが、ZYBO に実装してみようと思っている。

次に実装方法の検討をしてみよう。
今のトレーニング画像の生成方法を下に示す。

1. 800x600の白線画像を1/13.333...(0.075)の60x45に縮める。
2. 60x45のうちの下から60x14を中間BMPファイルとしてセーブ
3. 60x14のうちの56x10を切り出してBMPファイルに。1つにつき5x5の25個できる。
4. 左右直進をやる。


よって、CMOSカメラからの画像は、800 x 600 ピクセルなので、60 x 45 にリサイズして白黒変換する必要がある。これはDMAマスタのIO インターフェースでVivado HLS のHLS ビデオライブラリの resize() を使用して、作ってみようか?
残念ながら、1/13.333... では割り切れないので、カメラ画像全体をDMA する必要があるようだ。そのリサイズした画像を白線追従用畳み込みニューラルネットワーク回路にAXI4 Streamで入力することにする。
畳み込みニューラルネットワークを使用した白線追従用回路を下の図に示す。
wlt_cnn_98_170831.png

上の図で DMAw4Gabor のDMAエンジンは、カメラの画像フレームの偶数フレームと奇数フレームのDMA領域を分けてDMA を行う。それを下の図に示す。偶数フレームのDMA領域が frame buffer 0 で奇数フレームは frame buffer 1 にDMA する。カメラの画像を書き込んでいないほうのフレームバッファから「1/10 にリサイズして白黒変換」(resize_gray)が画像をDMAしてリサイズして白黒変換を行う。そのデータをAXI4 Streamで「白線追従用畳み込みニューラルネットワーク」に入力して、直進、左旋回、右旋回の判定をすることにしよう。
wlt_cnn_99_170831.png
  1. 2017年08月31日 05:23 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

白線追従走行用畳み込みニューラルネットワークの製作19(Cコードの合成、IP化)

白線追従走行用畳み込みニューラルネットワークの製作18(Vivado HLSでCシミュレーション)”の続き。

前回は、Vivado HLS 用のファイルがそろったので、Vivado HLS 2016.4 でプロジェクトを作成し、C シミュレーションを行って精度を確認した。今回は、Cコードの合成を行って、レイテンシやリソース使用量を確認する。

Vivado HLS 2016.4 で C コードの合成を行った。結果を示す。
wlt_cnn_88_170830.png
wlt_cnn_89_170830.png

レイテンシは、187374 クロックで、クロックは 100 MHz なので、1.87 ms となる。十分な性能ということが言える。
リソース使用量はBRAM_18K が 13 個、DSP48E が 9 個、FF が 716 個、LUT が 1476 個だった。
DSP48E が 7 個になると、現在のZYBO 用の Vivado プロジェクトに入ることになる。超えてしまったら、ガボール・フィルタを取り除く必要がある。現在のVivado HLS プロジェクトはZYBO 用だ。

C/RTL協調シミュレーションを行った。結果を示す。
wlt_cnn_90_170830.png

レイテンシは、187374 クロックで、C コードの合成と同じだった。
wlt_cnn_90_170830.png

C/RTL協調シミュレーション波形を見ていこう。まずは全体波形から紹介する。
wlt_cnn_92_170830.png

画像を転送しているの初めのごく一部なのだが、そこをデータが見えるまで拡大してみよう。
wlt_cnn_93_170830.png

最後にExport RTL をやってみた。今はインターフェースがデフォルトのままで、このままでは使えないが、とりあえず、リソース使用量を見るためにやってみた。Vivado RTL Synthesis と Place and Route にチェックを入れて、実際のリソース使用量を見ている。
wlt_cnn_91_170830.png

C コードの合成の時と、リソース使用量がどれも少なくなっている。DSP は 5 で今のままでZYBO_0 のVivado プロジェクトに入りそうだが、考えてみると、画像の縮小をする必要があるため、ガボール・フィルタはZYBO では除かないと入らないだろうと思う。

次に、Vivado HLS 2017.1 での結果を示す。Vivado HLS 2016.4 と比較してみよう。
最初に C コードの合成結果を示す。
wlt_cnn_94_170830.png
wlt_cnn_95_170830.png

レイテンシは、max が 299264 クロックで 2016.4 よりも時間がかかっている。でもこちらでも性能的には問題ない。
リソース使用量はBRAM_18K は13 で同じ、DSP48E は 2016.4 が 9 で、2017.1 が 7 だった。FF は 2016.4 が 716 に対して、2017.1 が 1122 だった。LUT は、2016.4 が 1476 に対して、2017.1 が 2586 だった。DSP48E は 2017.1 の方が少ないが、それ以外は、同じか 2017.1 の方がリソース使用量が多い。

C/RTL協調シミュレーションをやってみた。結果を示す。
wlt_cnn_96_170830.png

やはり、約 2.99 ms となった。

最後に、Export RTL を行った。やはり、Vivado RTL Synthesis と Place and Route にチェックを入れてある。
wlt_cnn_97_170830.png

BRAM_18K とDSP48E は 2016.4 と同じで、それ以外は 2017.1 の方がリソース使用量が多い。
  1. 2017年08月30日 05:26 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

白線追従走行用畳み込みニューラルネットワークの製作18(Vivado HLSでCシミュレーション)

白線追従走行用畳み込みニューラルネットワークの製作17(白線追従走行用画像データから一部を抜き出して画像にする)”の続き。

前回は、白線追従走行用の画像データを確認するために、白線追従走行用画像データから一部を抜き出して画像にするPython コードを作成した。今回は、いよいよVivado HLS 用のファイルがそろったので、Vivado HLS 2016.4 でプロジェクトを作成し、C シミュレーションを行う。

Vivado HLS 2016.4 で straight_conv_nn2 プロジェクトを作成した。これは、期待を込めてZYBO 用のプロジェクトとした。
wlt_cnn_85_170829.png

C シミュレーションを実行した。
wlt_cnn_86_170829.png

ログを示す。

Starting C simulation ...
/opt/Xilinx/Vivado_HLS/2016.4/bin/vivado_hls /home/masaaki/Vivado_HLS/ZYBO/straight_conv_nn2/solution1/csim.tcl
INFO: [HLS 200-10] Running '/opt/Xilinx/Vivado_HLS/2016.4/bin/unwrapped/lnx64.o/vivado_hls'
INFO: [HLS 200-10] For user 'masaaki' on host 'masaaki-VirtualBox2' (Linux_x86_64 version 4.4.0-92-generic) on Tue Aug 29 04:13:06 JST 2017
INFO: [HLS 200-10] On os Ubuntu 16.04.3 LTS
INFO: [HLS 200-10] In directory '/home/masaaki/Vivado_HLS/ZYBO'
INFO: [HLS 200-10] Opening project '/home/masaaki/Vivado_HLS/ZYBO/straight_conv_nn2'.
INFO: [HLS 200-10] Opening solution '/home/masaaki/Vivado_HLS/ZYBO/straight_conv_nn2/solution1'.
INFO: [SYN 201-201] Setting up clock 'default' with a period of 10ns.
INFO: [HLS 200-10] Setting target device to 'xc7z010clg400-1'
INFO: [SIM 211-2] *************** CSIM start ***************
INFO: [SIM 211-4] CSIM will launch GCC as the compiler.
Compiling ../../../straight_conv_nn_tb.cpp in debug mode
Generating csim.exe
id = 25, max_id_ref = 1, max_id_hw = 2
id = 25, max_id_ref = 1, max_id_sw = 2
id = 26, max_id_ref = 1, max_id_sw = 2
id = 30, max_id_ref = 1, max_id_sw = 2
id = 35, max_id_ref = 1, max_id_sw = 2
INFO: [SIM 211-1] CSim done with 0 errors.
INFO: [SIM 211-3] *************** CSIM finish ***************
Finished C simulation.


25, 26, 30, 35 の画像を見ると、直進指定なのだが、曲がってもおかしくないという画像だった。トレーニング用画像の作りに問題があるかもしれない?
wlt_cnn_87_170829.png

さて、ハードウェアが間違ったのが150 個のうちの 1 個、ソフトウェアが間違ったのが、150 個のうちの 4 個だ。ハードウェアの方が整合が良いという結果になった。ハードウェアの精度が 149 / 150 x 100 = 99.33 % で、ソフトウェアの精度が 146 / 150 x 100 = 97.33 % となった。

straight_conv_nn2.cpp を貼っておく。

// straight_conv_nn2.cpp
// 2017/08/28 by marsee
// 畳み込み層のカーネル数 2
//

#include <ap_fixed.h>

#include "conv1_weight.h"
#include "conv1_bias.h"
#include "af1_weight.h"
#include "af1_bias.h"
#include "af2_weight.h"
#include "af2_bias.h"

#define NUM_OF_KERNELS 2
#define COULMN_PIXELS 56
#define ROW_PIXELS 10
#define ALL_PIXELS 560
#define NUM_OF_OUTPUT 3

int straight_conv_nn(ap_ufixed<80, AP_TRN_ZERO, AP_SAT> in[ALL_PIXELS], ap_fixed<127, AP_TRN_ZERO, AP_SAT> out[NUM_OF_OUTPUT]){
    ap_ufixed<80, AP_TRN_ZERO, AP_SAT> buf[ROW_PIXELS][COULMN_PIXELS];
    ap_fixed<106, AP_TRN_ZERO, AP_SAT> conv_out[NUM_OF_KERNELS][ROW_PIXELS-4][COULMN_PIXELS-4];
    ap_fixed<106, AP_TRN_ZERO, AP_SAT> pool_out[NUM_OF_KERNELS][(ROW_PIXELS-4)/2][(COULMN_PIXELS-4)/2];
    ap_fixed<137, AP_TRN_ZERO, AP_SAT> dot1[100];
    ap_fixed<137, AP_TRN_ZERO, AP_SAT> dot2[NUM_OF_OUTPUT];

    buf_copy1: for(int i=0; i<ROW_PIXELS; i++)
        buf_copy2: for(int j=0; j<COULMN_PIXELS; j++)
            buf[i][j] = in[i*COULMN_PIXELS+j];

    // Convolutional Neural Network 5x5 kernel, Stride = 1, Padding = 0
    // + ReLU
    CONV1: for(int i=0; i<NUM_OF_KERNELS; i++){    // カーネルの個数
        CONV2: for(int j=0; j<ROW_PIXELS-4; j++){
            CONV3: for(int k=0; k<COULMN_PIXELS-4; k++){
                conv_out[i][j][k] = 0;
                CONV4: for(int m=0; m<5; m++){
                    CONV5: for(int n=0; n<5; n++){
                        conv_out[i][j][k] += buf[j+m][k+n] * conv1_weight[i][0][m][n];
                    }
                }
                conv_out[i][j][k] += conv1_bias[i];

                if(conv_out[i][j][k]<0)    // ReLU
                    conv_out[i][j][k] = 0;
            }
        }
    }

    // Pooling Kernel = 2 x 2, Stride = 2
    POOL1: for(int i=0; i<NUM_OF_KERNELS; i++){
        POOL2: for(int j=0; j<ROW_PIXELS-4; j += 2){
            POOL3: for(int k=0; k<COULMN_PIXELS-4; k += 2){
                POOL4: for(int m=0; m<2; m++){
                    POOL5: for(int n=0; n<2; n++){
                        if(m==0 && n==0){
                            pool_out[i][j/2][k/2] = conv_out[i][j][k];
                        } else if(pool_out[i][j/2][k/2] < conv_out[i][j+m][k+n]){
                            pool_out[i][j/2][k/2] = conv_out[i][j+m][k+n];
                        }
                    }
                }
            }
        }
    }

    af1_dot1: for(int col=0; col<100; col++){
        dot1[col] = 0;
        af1_dot2: for(int i=0; i<NUM_OF_KERNELS; i++){
            af1_dot3: for(int j=0; j<(ROW_PIXELS-4)/2; j++){
                af1_dot4: for(int k=0; k<(COULMN_PIXELS-4)/2; k++){
                    dot1[col] += pool_out[i][j][k]*af1_weight[i*((ROW_PIXELS-4)/2)*((COULMN_PIXELS-4)/2)+j*((COULMN_PIXELS-4)/2)+k][col];
                }
            }
        }
        dot1[col] += af1_bias[col];

        if(dot1[col] < 0)    // ReLU
            dot1[col] = 0;
    }

    af2_dot1: for(int col=0; col<NUM_OF_OUTPUT; col++){
        dot2[col] = 0;
        af2_dot2: for(int row=0; row<100; row++){
            dot2[col] += dot1[row]*af2_weight[row][col];
        }
        dot2[col] += af2_bias[col];

        out[col] = dot2[col];
    }

    return(0);
}


straight_conv_nn_tb.cpp を貼っておく。

// straight_conv_nn_tb.cpp
// 2017/08/28 by marsee
// 畳み込み層のカーネル数 2
//

#include <stdio.h>
#include <ap_fixed.h>

#include "conv1_weight.h"
#include "conv1_bias.h"
#include "af1_weight.h"
#include "af1_bias.h"
#include "af2_weight.h"
#include "af2_bias.h"

#include "straight_data.h"

#define NUM_OF_KERNELS 2
#define COULMN_PIXELS 56
#define ROW_PIXELS 10
#define ALL_PIXELS 560
#define NUM_OF_OUTPUT 3

int straight_conv_nn(ap_ufixed<80, AP_TRN_ZERO, AP_SAT> in[ALL_PIXELS], ap_fixed<127, AP_TRN_ZERO, AP_SAT> out[NUM_OF_OUTPUT]);
int straight_conv_nn_float(float in[ALL_PIXELS], float out[NUM_OF_OUTPUT]);
int max_ap_fixed(ap_fixed<127, AP_TRN_ZERO, AP_SAT> out[NUM_OF_OUTPUT]);
int max_float(float out[NUM_OF_OUTPUT]);

#define NUM_ITERATIONS    90 // C Simulation
//#define NUM_ITERATIONS    2 // C/RTL CoSimulation

int main(){
    float t_tran_float[NUM_ITERATIONS][ALL_PIXELS];
    ap_fixed<127, AP_TRN_ZERO, AP_SAT> result_ap_fixed[NUM_ITERATIONS][NUM_OF_OUTPUT];
    float result_float[NUM_ITERATIONS][NUM_OF_OUTPUT];
    int max_id_hw, max_id_sw, max_id_ref;

    for(int i=0; i<NUM_ITERATIONS; i++)
        for(int j=0; j<ALL_PIXELS; j++)
            t_tran_float[i][j] = (float)t_train[i][j];

    for(int i=0; i<NUM_ITERATIONS; i++){
        straight_conv_nn(&t_train[i][0], &result_ap_fixed[i][0]);
        straight_conv_nn_float(&t_tran_float[i][0], &result_float[i][0]);
    }

    int errflag=0;
    for(int i=0; i<NUM_ITERATIONS; i++){
        max_id_hw = max_ap_fixed(&result_ap_fixed[i][0]);
        max_id_sw = max_float(&result_float[i][0]);
        max_id_ref = max_float(&t_test[i][0]);

        if(max_id_ref != max_id_hw){
            printf("id = %d, max_id_ref = %d, max_id_hw = %d\n", i, max_id_ref, max_id_hw);
            errflag = 1;
        }
        if(max_id_ref != max_id_sw){
            printf("id = %d, max_id_ref = %d, max_id_sw = %d\n", i, max_id_ref, max_id_sw);
            errflag = 1;
        }
    }
    if(errflag == 0)
        printf("No Error\n");

    return(0);
}

int straight_conv_nn_float(float in[ALL_PIXELS], float out[NUM_OF_OUTPUT]){
    float buf[ROW_PIXELS][COULMN_PIXELS];
    float conv_out[NUM_OF_KERNELS][ROW_PIXELS-4][COULMN_PIXELS-4];
    float pool_out[NUM_OF_KERNELS][(ROW_PIXELS-4)/2][(COULMN_PIXELS-4)/2];
    float dot1[100];
    float dot2[NUM_OF_OUTPUT];

    buf_copy1: for(int i=0; i<ROW_PIXELS; i++)
        buf_copy2: for(int j=0; j<COULMN_PIXELS; j++)
            buf[i][j] = in[i*COULMN_PIXELS+j];

    // Convolutional Neural Network 5x5 kernel, Stride = 1, Padding = 0
    // + ReLU
    CONV1: for(int i=0; i<NUM_OF_KERNELS; i++){    // カーネルの個数
        CONV2: for(int j=0; j<ROW_PIXELS-4; j++){
            CONV3: for(int k=0; k<COULMN_PIXELS-4; k++){
                conv_out[i][j][k] = 0;
                CONV4: for(int m=0; m<5; m++){
                    CONV5: for(int n=0; n<5; n++){
                        conv_out[i][j][k] += buf[j+m][k+n] * conv1_fweight[i][0][m][n];
                    }
                }
                conv_out[i][j][k] += conv1_fbias[i];

                if(conv_out[i][j][k]<0)    // ReLU
                    conv_out[i][j][k] = 0;
            }
        }
    }

    // Pooling Kernel = 2 x 2, Stride = 2
    POOL1: for(int i=0; i<NUM_OF_KERNELS; i++){
        POOL2: for(int j=0; j<ROW_PIXELS-4; j += 2){
            POOL3: for(int k=0; k<COULMN_PIXELS-4; k += 2){
                POOL4: for(int m=0; m<2; m++){
                    POOL5: for(int n=0; n<2; n++){
                        if(m==0 && n==0){
                            pool_out[i][j/2][k/2] = conv_out[i][j][k];
                        } else if(pool_out[i][j/2][k/2] < conv_out[i][j+m][k+n]){
                            pool_out[i][j/2][k/2] = conv_out[i][j+m][k+n];
                        }
                    }
                }
            }
        }
    }

    af1_dot1: for(int col=0; col<100; col++){
        dot1[col] = 0;
        af1_dot2: for(int i=0; i<NUM_OF_KERNELS; i++){
            af1_dot3: for(int j=0; j<(ROW_PIXELS-4)/2; j++){
                af1_dot4: for(int k=0; k<(COULMN_PIXELS-4)/2; k++){
                    dot1[col] += pool_out[i][j][k]*af1_fweight[i*((ROW_PIXELS-4)/2)*((COULMN_PIXELS-4)/2)+j*((COULMN_PIXELS-4)/2)+k][col];
                }
            }
        }
        dot1[col] += af1_fbias[col];

        if(dot1[col] < 0)    // ReLU
            dot1[col] = 0;
    }

    af2_dot1: for(int col=0; col<NUM_OF_OUTPUT; col++){
        dot2[col] = 0;
        af2_dot2: for(int row=0; row<100; row++){
            dot2[col] += dot1[row]*af2_fweight[row][col];
        }
        dot2[col] += af2_fbias[col];

        out[col] = dot2[col];
    }

    return(0);
}

int max_ap_fixed(ap_fixed<127, AP_TRN_ZERO, AP_SAT> out[NUM_OF_OUTPUT]){
    int max_id;
    ap_fixed<127, AP_TRN_ZERO, AP_SAT> max;

    for(int i=0; i<NUM_OF_OUTPUT; i++){
        if(i == 0){
            max = out[0];
            max_id = 0;
        }else if(out[i]>max){
            max = out[i];
            max_id = i;
        }
    }
    return(max_id);
}

int max_float(float out[NUM_OF_OUTPUT]){
    int max_id;
    float max;

    for(int i=0; i<NUM_OF_OUTPUT; i++){
        if(i == 0){
            max = out[0];
            max_id = 0;
        }else if(out[i]>max){
            max = out[i];
            max_id = i;
        }
    }
    return(max_id);
}

  1. 2017年08月29日 04:39 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

白線追従走行用畳み込みニューラルネットワークの製作17(白線追従走行用画像データから一部を抜き出して画像にする)

白線追従走行用畳み込みニューラルネットワークの製作16(白線追従走行用の画像データをCの配列に出力)”の続き。

前回は、白線追従走行用の画像データをC のヘッダファイルに変換するPython コードを作成した。今回は、白線追従走行用の画像データを確認するために、白線追従走行用画像データから一部を抜き出して画像にするPython コードを作成した。

白線追従走行用画像データから一部を抜き出して画像にするPython コードを書いた。これは、前回の image_data2c_wt.py もそうだが、MNISTの手書き数字認識用に書いたPython コードを書き直したPython コードだ。
wlt_cnn_81_170828.png

Python コードを貼っておく。

def view_straight(first_offset, last_offset):
    # 白線追従走行用データセットのfirst_offset(画像の配列の番号)からlast_offset-1までの画像を表示する
    # 「ゼロから作るDeep_Learning」第8章のコードを一部引用しています
    
    # coding: utf-8
    import sys, os
    sys.path.append(os.pardir)

    import numpy as np
    from dataset_straight.straight_dataset import load_mnist
    import matplotlib.pyplot as plt

    # データの読み込み
    (x_train, t_train), (x_test, t_test) = load_mnist(normalize=False, one_hot_label=True)

    fig = plt.figure()
    fig.subplots_adjust(left=0, right=1, bottom=0, top=1, hspace=0.2, wspace=0.2)
    
    current_view = 1
    for i in range(first_offset, last_offset):
        ax = fig.add_subplot(4, 5, current_view, xticks=[], yticks=[])
        ax.imshow(x_test[i].reshape(10, 56), cmap=plt.cm.gray, interpolation='nearest')
        current_view += 1
    
    plt.show()


view_straight(1000, 1010)


  1. 2017年08月28日 04:34 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

白線追従走行用畳み込みニューラルネットワークの製作16(白線追従走行用の画像データをCの配列に出力)

白線追従走行用畳み込みニューラルネットワークの製作15(重みとバイアスのCヘッダファイル)”の続き。

前回は、重みとバイアスをC のヘッダファイルに変換したものを貼った。今回は、Pythonで白線追従走行用の画像データをC のヘッダファイルに変換する。これは、Vivado HLS のテストベンチに組み込まれて、シミュレーション時に使用する予定だ。

Pythonで白線追従走行用の画像データをC のヘッダファイルに変換する image_data2c_wt.py を作成して実行した。
wlt_cnn_79_170828.png
wlt_cnn_80_170828.png

image_data2c_wt.py を実行することで作成される straight_data.h について、一部を示す。
wlt_cnn_82_170828.png
wlt_cnn_83_170828.png
wlt_cnn_84_170828.png

これで、Vivado HLS のプロジェクトを作成することができる。
image_data2c_wt.py を貼っておく。
(2017/08/28:バグフィックス)

# 白線追従走行用の画像データをCの配列に出力し、ファイルに書き込み
# image_data2c_wt.py

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

import numpy as np
from dataset_straight.straight_dataset import load_mnist
import datetime

OUTPUT_DATA_NUM = 50 # 出力する白線追従走行のテストデータ数 直進、左旋回、右旋回で x 3
OFFSET = 0 # 白線追従走行用データセットのオフセット、100だったら100番目からOUTPUT_DATA_NUM個を出力する

def normal_image(offset, output_data_num, x_test, end):
    for i in range(offset, offset+output_data_num):
        f.write("\t{")
        for j in range(x_test.shape[1]):
            f.write(str(x_test[i][j]))
            if (j==x_test.shape[1]-1):
                if (i==offset+output_data_num-1 and end==1):
                    f.write("}\n")
                else:
                    f.write("},\n")
            else:
                f.write(", ")

def no_normal_image(offset, output_data_num, x_test, end):
    for i in range(offset, offset+output_data_num):
        f.write("\t{")
        for j in range(x_test.shape[1]):
            f.write(str(int(x_test[i][j]*256)))
            if (j==x_test.shape[1]-1):
                if (i==offset+output_data_num-1 and end==1):
                    f.write("}\n")
                else:
                    f.write("},\n")
            else:
                f.write(", ")

def normal_label(offset, output_data_num, t_test, end):
    for i in range(offset, offset+output_data_num):
        f.write("\t{")
        for j in range(t_test.shape[1]):
            f.write(str(t_test[i][j]))
            if (j==t_test.shape[1]-1):
                if (i==offset+output_data_num-1 and end==1):
                    f.write("}\n")
                else:
                    f.write("},\n")
            else:
                f.write(", ")

# データの読み込み
(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, one_hot_label=True)

all_x_test = x_test.shape[0];
all_go_direction = int(all_x_test/3);
print(all_x_test)
print(all_go_direction)

f = open("straight_data.h", 'w')
todaytime = datetime.datetime.today()
f.write('// mnist_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_ZERO, AP_SAT> t_train['+str(OUTPUT_DATA_NUM*3)+']['+str(x_test.shape[1])+'] = {\n')
normal_image(OFFSET, OUTPUT_DATA_NUM, x_test, 0) # 直進
normal_image(OFFSET+all_go_direction, OUTPUT_DATA_NUM, x_test, 0) # 左旋回
normal_image(OFFSET+all_go_direction*2, OUTPUT_DATA_NUM, x_test, 1) # 右旋回
f.write("};\n")

f.write('int t_train_256['+str(OUTPUT_DATA_NUM*3)+']['+str(x_test.shape[1])+'] = {\n')
no_normal_image(OFFSET, OUTPUT_DATA_NUM, x_test, 0) # 直進
no_normal_image(OFFSET+all_go_direction, OUTPUT_DATA_NUM, x_test, 0) # 左旋回
no_normal_image(OFFSET+all_go_direction*2, OUTPUT_DATA_NUM, x_test, 1) # 右旋回
f.write("};\n")

f.write("\n")
f.write('float t_test['+str(OUTPUT_DATA_NUM*3)+']['+str(t_test.shape[1])+'] = {\n')
normal_label(OFFSET, OUTPUT_DATA_NUM, t_test, 0) # 直進
normal_label(OFFSET+all_go_direction, OUTPUT_DATA_NUM, t_test, 0) # 左旋回
normal_label(OFFSET+all_go_direction*2, OUTPUT_DATA_NUM, t_test, 1) # 右旋回
f.write("};\n")
f.close() 

  1. 2017年08月28日 04:28 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

Vivado シミュレータでDPI-C を使用してZynq VIPを使う4(Export Simulation)

昨日、「SystemVerilogによるテストベンチ実践会(2017夏)」で、Venginner さんに、Export Simulation のことを聞いたので、自分でもやってみた。

今回は、下の3つの「Vivado シミュレータでDPI-C を使用してZynq VIPを使う」シリーズをExport Simulation を使用してやってみよう。そうすると、もう一度シミュレーションを行っても、設定が消えてしまうことが無いというメリットがある。
Vivado シミュレータでDPI-C を使用してZynq VIPを使う1
Vivado シミュレータでDPI-C を使用してZynq VIPを使う2
Vivado シミュレータでDPI-C を使用してZynq VIPを使う3

さて、やってみましょう。環境は、VirtualBox 上のUbuntu 16.04 でVivado 2017.2 を使用している。
まずは、Vivado 2017.2 で Zynq Base サンプル・プロジェクトを開いて、FileメニューからExport -> Export Simulation... を選択する。
DPI_examples_41_170826.png

Export Simulation Files ダイアログが表示される。
Target sumulator をVivado Simulator に、Export directory を指定して、Copy source files to export directory にチェックを付ける。
DPI_examples_40_170826.png

~/Vivado/Examples/zynq_ex_172/xsim ができていた。
DPI_examples_42_170826.png

Vivado シミュレータでDPI-C を使用してZynq VIPを使う1」の zynq_dpi.c をディレクトリにコピー&ペーストする。
DPI_examples_43_170826.png

zynq_dpi.c を起動したことがわかるように、2番目のWrite に 1000 のWait を入れた。
DPI_examples_44_170826.png

~/Vivado/Examples/zynq_ex_172/xsim/srcs ディレクトリにzynq_tb.sv をコピー&ペーストした。
DPI_examples_45_170826.png

~/Vivado/Examples/zynq_ex_172/xsim ディレクトリに戻って、tb.sh を開いてDPI-C を実行できるように書き換えよう。
まずは、compile にzynq_dpi.c をコンパイルするコマンドを追加した。

$xv_path/bin/xsc zynq_dpi.c 2>&1 | tee c_compile.log


elaborate に -sv_lib dpi オプションを追加した。
simulate に -g オプションを追加した。
DPI_examples_46_170826.png

次に cmd.tcl の最後の quit を削除した。これを削除しないとGUI が自動終了してしまう。(ひでみさん、ありがとうございました)
DPI_examples_47_170826.png

vlog.prj を編集して、verilog を sv に、zynq_tb.v を zynq_tb.sv に変更した。
DPI_examples_48_170826.png

これで変更は終了。
./tb.sh を実行した。
DPI_examples_49_170826.png

コンパイル、エラボレート、シミュレータが起動した。
DPI_examples_50_170827.png
「AXI VIP Test PASSED」になっている。成功している。

AXI4 インターフェイスの波形を追加しよう。
zynq_sys -> base_zynq_i を選択して、右クリックし、右クリックメニューから、Add Wave Window で波形を全部追加した。
DPI_examples_51_170827.png

Tcl Console に
restart
run all

を行って、今挿入した信号に波形を表示しようとした。
DPI_examples_52_170827.png

ところが、それらのコマンドを実行すると、FAILED してしまう。
DPI_examples_53_170827.png

波形ウインドウでSave Waveform Configuration ボタンをクリックして、波形をセーブしよう。
DPI_examples_54_170827.png

Save Waveform ダイアログが表示されるので、tb.wcfg を確認して、Save ボタンをクリックする。
DPI_examples_55_170827.png

Waveform Configuraiton File ダイアログで、Yes ボタンをクリックする。
DPI_examples_56_170827.png

これで、波形ウインドウの信号を tb.wcfg ファイルにセーブできたので、もう一度、
./tb.sh
を実行する。
今度はきちんと波形が表示できた。
DPI_examples_57_170827.png

タイムスケールが 1ns で #1000 なので、1000 ns Wait しているのが分かる。
しかし、xsim でリスタートすると、シミュレーションがフェイルするのはなぜだろうか?

とりあえず、これでシミュレーション環境が独自に構築できた。ソースもHDL ファイルになっているので、使いやすい。
  1. 2017年08月27日 07:55 |
  2. シミュレーション
  3. | トラックバック:0
  4. | コメント:0

白線追従走行用畳み込みニューラルネットワークの製作15(重みとバイアスのCヘッダファイル)

白線追従走行用畳み込みニューラルネットワークの製作14(固定小数点用に量子化)”の続き。

前回は、畳み込みニューラルネットワークを固定小数点用に量子化し、Vivado HLS に使用する重みやバイアスのヘッダファイルを生成した。今回は、その結果生成できた重みとバイアスのCヘッダファイルを貼っておく。

畳み込み層の重みのファイル名は、conv1_weight.h、バイアスのファイル名は conv1_bias.h、1層目の全結合層のファイル名は af1_weight.h、バイアスのファイル名は af1_bias.h、2層目の全結合層の重みファイル名は af2_weight.h、バイアスのファイル名は af2_bias.h なので、そのファイルを貼っておく。

まずは、conv1_weight.h から貼っておく。

// conv1_weight.h
// 2017/08/24 20:29:30 by marsee

const float conv1_fweight[2][1][5][5] = 
{
    {
        {
            {0.294570413175,0.494004676217,0.44994119544,0.515573789799,0.544610330831},
            {0.40486488371,0.462682035597,0.45391988533,0.428258168527,0.380212999297},
            {0.50351358146,0.495029433364,0.498244962825,0.433375033151,0.377243668748},
            {0.503165711207,0.487963332866,0.444891841935,0.422814642144,0.401928034088},
            {0.411021574202,0.418571893201,0.487229387082,0.491190313386,0.499503929646}
        }
    }
    ,
    {
        {
            {0.00429091281128,-0.00429508065741,0.00521589342041,-0.00542417093149,0.0115336444712},
            {-0.00520812977283,-0.0125367789506,-0.0165218053161,-0.00583519826402,0.0021076978354},
            {0.0105605800117,-0.00306969245547,-0.0136611794413,-0.00504961598515,-0.0163449762107},
            {-0.0086441958247,-0.00414093021477,-0.00716074872487,-0.00832960908688,-0.000113451640109},
            {0.00463348666248,4.79973508012e-05,0.0139718435768,0.000123781195982,0.0105360722489}
        }
    }
};

const ap_fixed<91, AP_TRN_ZERO, AP_SAT> conv1_weight[2][1][5][5] = 
{
    {
        {
            {0.29296875,0.4921875,0.44921875,0.515625,0.54296875},
            {0.40625,0.4609375,0.453125,0.4296875,0.37890625},
            {0.50390625,0.49609375,0.5,0.43359375,0.37890625},
            {0.50390625,0.48828125,0.4453125,0.421875,0.40234375},
            {0.41015625,0.41796875,0.48828125,0.4921875,0.5}
        }
    }
    ,
    {
        {
            {0.00390625,0.0,0.00390625,0.0,0.01171875},
            {0.0,-0.0078125,-0.01171875,0.0,0.00390625},
            {0.01171875,0.0,-0.0078125,0.0,-0.01171875},
            {-0.00390625,0.0,-0.00390625,-0.00390625,0.0},
            {0.00390625,0.0,0.015625,0.0,0.01171875}
        }
    }
};


次に conv1_bias.h を貼っておく。

// conv1_bias.h
// 2017/08/24 20:29:33 by marsee

const float conv1_fbias[2] = {
    -0.4674033430470.0
};

const ap_fixed<91, AP_TRN_ZERO, AP_SAT> conv1_bias[2] = {
    -0.464843750.0
};


af1_weight.h は長すぎて貼るのが無理でした。431KB

af1_bias.h を貼っておく。

// af1_bias.h
// 2017/08/24 20:29:35 by marsee

const float af1_fbias[100] = {
    -0.00538524705766, -0.00598539062265, -0.005655360481320.0, -0.00685936102353, -0.00536698581278, -0.00623459442338, -0.007093949590530.00.158105182373, -0.034250223689, -0.001245154527190.00.1562606357060.02580014942180.08448134373350.0882019232825, -0.07031338233150.0, -0.00528064880736, -0.00423357775603, -0.005996020187080.0741511844097, -0.140380278179, -0.00802484293904, -0.005949261564750.160366829792, -0.00598124395411, -0.005816919651270.0, -0.00433641008826, -0.0581982793318, -0.005948405029840.0, -0.00596392388605, -0.0345905812002, -0.005967000139070.0, -0.005664658350730.0, -0.005433420538680.1067995767210.0416939154099, -0.08776094553340.0572610067402, -0.00588865216287, -0.00598300886618, -0.1190247442370.08514403099570.12963722794, -0.00806675185856, -0.004345842795750.1098254019310.00.0422327145024, -0.005924856338980.0534250925738, -0.0559710722051, -0.00535198913464, -0.0059733490076, -0.0861017024054, -0.005880278057920.004592889931980.0, -0.005915456495150.0897744436782, -0.0059229789071, -0.072504495188, -0.00523629719031, -0.00491575729656, -0.1018396397450.15618643854, -0.00562686983234, -0.00595156113069, -0.00532042799961, -0.005935448414090.0, -0.145186356158, -0.005973354147620.0, -0.007385094132140.0868084556983, -0.00487009622847, -0.00590424120649, -0.00751997670017, -0.1425211097990.0, -0.0969972486866, -0.105567556471, -0.005952902673020.0264242303548, -0.13445683226, -0.007476007473750.00.00.0, -0.00597598643903, -0.1527062520340.0, -0.0660025441402
};

const ap_fixed<91, AP_TRN_ZERO, AP_SAT> af1_bias[100] = {
    0.0, -0.003906250.00.0, -0.003906250.0, -0.00390625, -0.003906250.00.15625, -0.031250.00.00.156250.027343750.08593750.08984375, -0.066406250.00.00.0, -0.003906250.07421875, -0.13671875, -0.00390625, -0.003906250.16015625, -0.003906250.00.00.0, -0.0546875, -0.003906250.0, -0.00390625, -0.03125, -0.003906250.00.00.00.00.105468750.04296875, -0.082031250.05859375, -0.00390625, -0.00390625, -0.113281250.08593750.12890625, -0.003906250.00.1093750.00.04296875, -0.003906250.0546875, -0.050781250.0, -0.00390625, -0.08203125, -0.003906250.003906250.0, -0.003906250.08984375, -0.00390625, -0.07031250.00.0, -0.097656250.156250.0, -0.003906250.0, -0.003906250.0, -0.140625, -0.003906250.0, -0.003906250.08593750.0, -0.00390625, -0.00390625, -0.136718750.0, -0.09375, -0.1015625, -0.003906250.02734375, -0.12890625, -0.003906250.00.00.0, -0.00390625, -0.14843750.0, -0.0625
};



af2_weight.h を貼っておく。

// af2_weight.h
// 2017/08/24 20:29:38 by marsee

const float af2_fweight[100][3] = {
    {-0.008203559709570.00101259251505, -0.00738029792378},
    {-0.00658775205594, -0.00486606234669, -0.0093604152744},
    {-0.00376509576185, -0.003204181568390.00446600986062},
    {-0.00222591145973, -0.0114764282693, -0.0125846717219},
    {-0.0172525876603, -0.0121569822688, -0.0174832203182},
    {-0.004441212470930.003766606703720.00494277572638},
    {0.01441663415110.00571422646049, -0.000451331284046},
    {-0.00773734700282, -0.0127894700042, -0.00316662283778},
    {-0.009803203114970.007741444493320.00466787755531},
    {-0.153223966440.008320433918830.201276629574},
    {-0.06730212004620.090204938319, -0.112073644712},
    {0.002983074645430.006441572451560.00800343766018},
    {-0.00952199361278, -0.00483905084921, -0.0150083862732},
    {-0.100111162346, -0.06674189210180.168230912865},
    {-0.4343895318170.1227618683880.112380800074},
    {-0.1855565389570.117074098232, -0.00454780154485},
    {-0.2081309278940.1281486351270.00580676863725},
    {0.005362935276610.110961879853, -0.200961349249},
    {0.01791324829750.000113803245086, -0.0179738854863},
    {0.00785219154510.004908871626680.00664359090093},
    {0.00279295320522, -0.01178098163320.0233511027877},
    {0.00576400892566, -0.001547139699620.00780394968406},
    {0.0326806385735, -0.1162723607440.104181499231},
    {0.281688127519, -0.050505987361, -0.337821332905},
    {0.004127154572620.005281699452680.00765624887698},
    {-0.000676362650949, -0.006215883624890.0114413980656},
    {-0.152045040818, -0.01977974394750.176308752788},
    {-0.00101985599932, -0.007261180072, -0.00405065562585},
    {-0.01094827778950.002965088469560.00209693843146},
    {-0.00941176993216, -0.01503386398020.0146204542805},
    {0.01087650005030.00221551292604, -0.00943386328304},
    {0.273536715663, -0.439966649596, -0.0483120039363},
    {0.0006413858995790.00176874518582, -0.00283284521959},
    {-0.0114604863243, -0.00768064077955, -0.0105853713444},
    {0.00367602592519, -0.0201054399855, -0.00727753876315},
    {0.130101479837, -0.1284144361010.0249145199096},
    {-0.0008233418872560.01013374819580.00650373443506},
    {-0.00943068902902, -0.00153673986995, -0.00636511125021},
    {0.00756524681284, -0.0009571464814340.00279509536095},
    {-0.0101610421199, -0.01216890947420.00611739537186},
    {0.00277517408640.000687300479967, -0.00142426431398},
    {0.0107963370449, -0.09615631988480.135769397739},
    {0.067479675116, -0.1186809214620.101454270851},
    {0.278649405523, -0.0638102974619, -0.405159676297},
    {-0.1592821761710.120383212282, -0.0300551862799},
    {0.01361898882630.005921762121310.00672759183286},
    {0.01378185597940.01638733933780.00642866861232},
    {0.282523857349, -0.087944438418, -0.238954778183},
    {-0.1902559477020.1455796083590.0075601932195},
    {-0.0315043857812, -0.0836230003090.136702205578},
    {0.0006080333066840.009138864574740.0102832249771},
    {0.005376887515250.01331613466860.00610052322048},
    {-0.2346635518930.1242749544210.0563793991797},
    {0.00587731057438, -0.01586642376820.0284369610688},
    {-0.5436411636250.1300273652450.157524888611},
    {-0.00774212606919, -0.004508433329550.0189166493825},
    {0.0646963727477, -0.108050316130.108404665099},
    {-0.02679235716380.108829036939, -0.121159157504},
    {-0.01840221784860.01698156401080.0154621580396},
    {0.002903019899980.004391103052820.0129160123658},
    {0.295774852423, -0.0564873278638, -0.537593080117},
    {-0.001173046500410.01061915672210.00614773011635},
    {0.00185660062042, -0.00336154769079, -0.00131980922298},
    {0.000711758901132, -0.01694977341510.00983303319272},
    {0.01164804300040.005215837887650.0111912428732},
    {-0.193370068720.1126671727990.004643172569},
    {0.005388462972190.00584099064517, -0.00176371930271},
    {-0.02705904588830.111207364222, -0.13031455024},
    {-0.006397787438060.01674665004880.00998962984116},
    {-0.01242906819650.000692885600751, -0.00959108577132},
    {0.388707026472, -0.490774843687, -0.113918271156},
    {-0.160369252488, -0.0007911600186290.170142601415},
    {0.003277902993050.0129578276680.0128847095396},
    {0.00131031872257, -0.000112629890535, -0.00291128770448},
    {0.101561554831, -0.1105221962340.063784932396},
    {-0.00458738838876, -0.00859014309809, -0.00576967017053},
    {0.005945564559320.005687003579970.00436139354229},
    {0.2775377640750.0147263855709, -0.325946679767},
    {0.002813758619340.006832184890340.00312772971751},
    {-0.01896927253350.0069368813551, -0.000677285718001},
    {0.00786093523784, -0.000952448132357, -0.013087215922},
    {0.0424404088819, -0.11092709470.13765443958},
    {0.00663733102854, -0.01224060891120.00238680007741},
    {0.003353839903730.01164740585890.01331781551},
    {0.00631725835386, -0.0058431887138, -0.00040914131858},
    {0.308370395049, -0.0440874511783, -0.366299602116},
    {-0.01493625828150.00446126933178, -0.000938738496254},
    {0.184354359182, -0.0904720145049, -0.0866392911745},
    {0.193741093433, -0.0876960948411, -0.113986496103},
    {-0.0249647325112, -0.005942802957460.01038246304},
    {0.0850977285604, -0.1155158919770.0909139518915},
    {0.260905844821, -0.0841269913801, -0.317866350456},
    {-0.00097223996393, -0.0046818354073, -0.00443646653402},
    {-0.003641754549290.0139558811565, -0.00771410003344},
    {-0.00216841359756, -0.00545245263308, -0.00386304728375},
    {-8.70602913003e-050.01114317405640.0145401735664},
    {-0.00963447070917, -0.007782269608090.00101368004201},
    {0.2506791106410.0187397414502, -0.326182991553},
    {-0.01398419460770.007116482017950.0103306514814},
    {0.18164313447, -0.133722739697, -0.00864408506204}
};

const ap_fixed<91, AP_TRN_ZERO, AP_SAT> af2_weight[100][3] = {
    {-0.003906250.0, -0.00390625},
    {-0.003906250.0, -0.00390625},
    {0.00.00.00390625},
    {0.0, -0.0078125, -0.0078125},
    {-0.01171875, -0.0078125, -0.01171875},
    {0.00.003906250.00390625},
    {0.0156250.003906250.0},
    {-0.00390625, -0.00781250.0},
    {-0.00781250.00781250.00390625},
    {-0.14843750.00781250.203125},
    {-0.06250.08984375, -0.109375},
    {0.003906250.00781250.0078125},
    {-0.003906250.0, -0.01171875},
    {-0.09765625, -0.06250.16796875},
    {-0.42968750.121093750.11328125},
    {-0.183593750.11718750.0},
    {-0.2031250.128906250.00390625},
    {0.003906250.109375, -0.1953125},
    {0.019531250.0, -0.015625},
    {0.00781250.003906250.0078125},
    {0.00390625, -0.00781250.0234375},
    {0.003906250.00.0078125},
    {0.03125, -0.113281250.10546875},
    {0.28125, -0.046875, -0.33203125},
    {0.003906250.003906250.0078125},
    {0.0, -0.003906250.01171875},
    {-0.1484375, -0.0156250.17578125},
    {0.0, -0.003906250.0},
    {-0.00781250.003906250.00390625},
    {-0.00390625, -0.011718750.015625},
    {0.011718750.00390625, -0.00390625},
    {0.2734375, -0.4375, -0.04296875},
    {0.00.00.0},
    {-0.0078125, -0.00390625, -0.0078125},
    {0.00390625, -0.015625, -0.00390625},
    {0.12890625, -0.1250.0234375},
    {0.00.011718750.0078125},
    {-0.003906250.0, -0.00390625},
    {0.00781250.00.00390625},
    {-0.0078125, -0.00781250.0078125},
    {0.003906250.00.0},
    {0.01171875, -0.093750.13671875},
    {0.06640625, -0.113281250.1015625},
    {0.27734375, -0.05859375, -0.40234375},
    {-0.156250.12109375, -0.02734375},
    {0.011718750.00781250.0078125},
    {0.0156250.0156250.0078125},
    {0.28125, -0.0859375, -0.234375},
    {-0.18750.144531250.0078125},
    {-0.02734375, -0.0781250.13671875},
    {0.00.00781250.01171875},
    {0.003906250.011718750.0078125},
    {-0.230468750.1250.0546875},
    {0.0078125, -0.011718750.02734375},
    {-0.53906250.128906250.15625},
    {-0.003906250.00.01953125},
    {0.06640625, -0.105468750.109375},
    {-0.02343750.109375, -0.1171875},
    {-0.0156250.0156250.015625},
    {0.003906250.003906250.01171875},
    {0.296875, -0.05078125, -0.53515625},
    {0.00.011718750.0078125},
    {0.00.00.0},
    {0.0, -0.011718750.01171875},
    {0.011718750.003906250.01171875},
    {-0.191406250.113281250.00390625},
    {0.003906250.003906250.0},
    {-0.02343750.109375, -0.125},
    {-0.003906250.0156250.01171875},
    {-0.00781250.0, -0.00390625},
    {0.390625, -0.48828125, -0.109375},
    {-0.156250.00.171875},
    {0.003906250.011718750.01171875},
    {0.00.00.0},
    {0.1015625, -0.105468750.0625},
    {0.0, -0.003906250.0},
    {0.00781250.003906250.00390625},
    {0.277343750.015625, -0.3203125},
    {0.003906250.00781250.00390625},
    {-0.0156250.00781250.0},
    {0.00781250.0, -0.0078125},
    {0.04296875, -0.105468750.13671875},
    {0.0078125, -0.00781250.00390625},
    {0.003906250.011718750.01171875},
    {0.00781250.00.0},
    {0.30859375, -0.0390625, -0.36328125},
    {-0.011718750.003906250.0},
    {0.18359375, -0.0859375, -0.08203125},
    {0.1953125, -0.08203125, -0.109375},
    {-0.01953125, -0.003906250.01171875},
    {0.0859375, -0.113281250.08984375},
    {0.26171875, -0.08203125, -0.3125},
    {0.00.00.0},
    {0.00.015625, -0.00390625},
    {0.00.00.0},
    {0.00.011718750.015625},
    {-0.00390625, -0.003906250.0},
    {0.250.01953125, -0.32421875},
    {-0.011718750.00781250.01171875},
    {0.18359375, -0.12890625, -0.00390625}
};


af2_bias.h を貼っておく。

// af2_bias.h
// 2017/08/24 20:29:35 by marsee

const float af2_fbias[3] = {
    -0.0999304880919, -0.02879082868040.121076044953
};

const ap_fixed<91, AP_TRN_ZERO, AP_SAT> af2_bias[3] = {
    -0.09765625, -0.02343750.12109375
};


残念ながら、 af1_weight.h が長すぎて貼れなかった。。。
  1. 2017年08月25日 04:31 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

白線追従走行用畳み込みニューラルネットワークの製作14(固定小数点用に量子化)

白線追従走行用畳み込みニューラルネットワークの製作13(9075枚のトレーニング用画像データで学習)”の続き。

前回は、9075 個のトレーニング用画像データと4125 個のテスト用画像データを使用して学習を行った。その結果、CONV数が 2 の畳み込みニューラルネットワークで、93.1 % の精度を得ることができた。今回は、その畳み込みニューラルネットワークを固定小数点用に量子化し、Vivado HLS に使用する重みやバイアスのヘッダファイルを生成しよう。

最初に、今まで使ってきたDLFS_Chap7_integer.ipynb のPython コードで量子化を行った。
wlt_cnn_75_170825.png

wlt_cnn_78_170825.png

固定小数点用に量子化したときの精度は約 91.9 % だった。浮動小数点数演算の場合は 93.1 % だったので、1.2 % 精度が落ちている。
この時の量子化ビット数は、MNISTの手書き数字認識の時よりも、畳み込みの精度を変えている。最大10.3 位の値が出るので、符号も併せて整数部(COV_OUT_INT)を 5 ビット、小数部(COV_OUT_MAG)を 4 ビットとした。
wlt_cnn_76_170825.png

この時のデバックモードの出力の一部を示す。

(100, 1, 10, 56)
Conv col.shape = (31200, 25)
Conv col_W.shape = (25, 2)
Conv np.max(x) = 0.9686274528503418
Conv np.min(x) = 0.29411765933036804
(2, 1, 5, 5)
Conv np.max(self.W_int) = 0.54296875
Conv np.min(self.W_int) = -0.01171875
(2,)
Conv np.max(self.b_int) = 0.0
Conv np.min(self.b_int) = -0.46484375
Conv out.shape = (31200, 2)
Conv np.max(out) = 10.408639731584117
Conv np.min(out) = 0.00032169173937290907
Conv np.max(out2) = 10.4375
Conv np.min(out2) = 0.0
Conv out.reshape = (100, 2, 6, 52)
Pooling x.shape = (100, 2, 6, 52)
Pooling out.shape = (100, 2, 3, 26)
x shape =(100, 2, 3, 26)
np.max(self.W) = 0.3530595475749049
np.max(self.W) = 0.3530595475749049
np.max(self.b) = 0.16036682979180678
x reshape =(100, 156)
np.max(x) = 10.4375
np.min(x) = 0.0
(156, 100)
np.max(self.W_int) = 0.3515625
np.min(self.W_int) = -0.3046875
(100,)
np.max(self.b_int) = 0.16015625
np.min(self.b_int) = -0.1484375
(100, 100)
np.max(out) = 8.645263671875
np.min(out) = -4.50537109375
np.max(out2) = 8.65625
np.min(out2) = -4.46875
x shape =(100, 100)
np.max(self.W) = 0.38870702647190525
np.max(self.W) = 0.38870702647190525
np.max(self.b) = 0.12107604495322784
x reshape =(100, 100)
np.max(x) = 8.65625
np.min(x) = 0.0
(100, 3)
np.max(self.W_int) = 0.390625
np.min(self.W_int) = -0.5390625
(3,)
np.max(self.b_int) = 0.12109375
np.min(self.b_int) = -0.09765625
(100, 3)
np.max(out) = 7.540771484375
np.min(out) = -8.2576904296875
np.max(out2) = 7.53125
np.min(out2) = -8.21875


大体良いと思うので、Vivado HLS に使用する重みやバイアスのヘッダファイルを生成した。これはMNISTの手書き数字認識と同じPython コードを使用している。これについては、”「ゼロから作るDeep Learning」の畳み込みニューラルネットワークのハードウェア化3”を参照してほしい。

畳み込み層の重みのファイル名は、conv1_weight.h、バイアスのファイル名は conv1_bias.h、1層目の全結合層のファイル名は af1_weight.h、バイアスのファイル名は af1_bias.h、2層目の全結合層の重みファイル名は af2_weight.h、バイアスのファイル名は af2_bias.h となっている。これらのファイルを生成することができた。
wlt_cnn_77_170825.png
  1. 2017年08月25日 03:57 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

白線追従走行用畳み込みニューラルネットワークの製作13(9075枚のトレーニング用画像データで学習)

白線追従走行用畳み込みニューラルネットワークの製作12(テスト用画像ファイルとラベル・ファイルの作成)”の続き。

前回で、4125 個のテスト用画像データを作ることができた。9075 個のトレーニング用画像データを使用して、今回は学習をしてみようと思う。

まずは、C:\Users\Masaaki\Google ドライブ\Python\deep-learning-from-scratch\dataset_straight に9075 個のトレーニング用画像データのtrain_straight_run_image と train_straight_run_label 、4125 個のテスト用画像データの test_straight_run_image と test_straight_run_label をコピー&ペーストした。
wlt_cnn_69_170823.png

同じフォルダの straight_dataset.py を修正した。
wlt_cnn_70_170823.png

C:\Users\Masaaki\Google ドライブ\Python\deep-learning-from-scratch\ch07_straight フォルダのDLFS_Chap7_integer.ipynb を jupyuter Notebook で開いて、train_convnet.py を実行して学習を行った。
ニューラルネットワークの階層は畳み込み層 - ReLU - プーリング - 全結合層 - ReLU - 全結合層 - softmax だ。
wlt_cnn_71_170823.png

畳み込みフィルタ数(CONV数) 30 個で、max_epochs = 10 の学習結果の精度は約 92.0 % だった。画像を増やす前は七十パーセント台だったので、だいぶ精度が良くなった。
wlt_cnn_72_170823.png

いろいろとCONV数と max_epochs を変えて精度を調べたデータを示す。ただし、複数回学習すると同じパラメータでも精度が 10 % 程度変動することがある。今回のデータは平均したデータではなく、1回やってみて出たデータである。

直線走行CONV_NNのCONV数とmax_epochsによる精度の違い
トレーニング画像数9075、テスト画像数4125

CONV=30, max_epochs = 10
pool_output_size =2340
test acc:0.854545454545

CONV=30, max_epochs = 20
test acc:0.888

CONV=30, max_epochs = 40
test acc:0.875636363636

CONV=30, max_epochs = 60
test acc:0.843636363636

CONV=30, max_epochs = 80
test acc:0.877575757576


CONV=10, max_epochs = 10
pool_output_size =780
test acc:0.941333333333

CONV=10, max_epochs = 20
test acc:0.931878787879

CONV=10, max_epochs = 40
test acc:0.900121212121

CONV=10, max_epochs = 60
test acc:0.868848484848

CONV=10, max_epochs = 80
test acc:0.881454545455


CONV=8, max_epochs = 10
pool_output_size =624
test acc:0.900363636364

CONV=8, max_epochs = 20
test acc:0.908606060606

CONV=8, max_epochs = 40
test acc:0.919515151515


CONV=6, max_epochs = 10
pool_output_size =468
test acc:0.882666666667

CONV=6, max_epochs = 20
test acc:0.923151515152

CONV=6, max_epochs = 40
test acc:0.901818181818


CONV=12, max_epochs = 10
pool_output_size =936
test acc:0.938424242424

CONV=14, max_epochs = 10
pool_output_size =1092
test acc:0.900848484848

CONV=16, max_epochs = 10
pool_output_size =1248
test acc:0.955151515152

CONV=18, max_epochs = 10
pool_output_size =1404
test acc:0.930666666667

CONV=20, max_epochs = 10
pool_output_size =1560
test acc:0.935272727273

CONV=22, max_epochs = 10
pool_output_size =1716
test acc:0.928

CONV=24, max_epochs = 10
pool_output_size =1872
test acc:0.843393939394

CONV=26, max_epochs = 10
pool_output_size =2028
test acc:0.922181818182

CONV=28, max_epochs = 10
pool_output_size =2184
test acc:0.914666666667


CONV=4, max_epochs = 10
pool_output_size =312
test acc:0.889696969697

CONV=4, max_epochs = 20
test acc:0.933575757576

CONV=4, max_epochs = 40
test acc:0.908363636364


CONV=3, max_epochs = 10
pool_output_size =234
test acc:0.837090909091

CONV=3, max_epochs = 20
test acc:0.918545454545

CONV=3, max_epochs = 40
test acc:0.879515151515


CONV=2, max_epochs = 10
pool_output_size =156
test acc:0.922181818182

CONV=2, max_epochs = 20
test acc:0.947878787879

CONV=2, max_epochs = 40
test acc:0.895272727273


max_epochs = 10 の時のCONV数における精度のグラフを書いてみた。
wlt_cnn_73_170824.png
先ほど書いたように値には変動があるが、傾向は見られると思う。案外、CONV数 2 でも精度が出ている。これだったらPYNQ ボードでなくても ZYBO に畳み込みニューラルネットワークが入るかもしれない?

CONV数 2 、max_epochs = 20 でやってみたところ、精度は約 93.1 % だったので、使えそうだ。
wlt_cnn_74_170824.png
  1. 2017年08月24日 05:04 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

白線追従走行用畳み込みニューラルネットワークの製作12(テスト用画像ファイルとラベル・ファイルの作成)

白線追従走行用畳み込みニューラルネットワークの製作11(トレーニング用画像ファイルとラベル・ファイルの作成)”の続き。

前回は、画像ファイルを増やして、トレーニング用画像ファイルとラベル・ファイルの作成を行った。今回は、テスト用の画像を増やして、MNISTデータ形式のテスト用画像ファイルとテスト用ラベル・ファイルの作成を行った。

まずは、~/Vivado_HLS/PYNQ ディレクトリにVivado HLS 2016.4 の straight_test_dataset3 プロジェクトを作った。
その下に、test_images_170804 ディレクトリをコピーした。ここにはテスト用の画像が直進、左旋回、右旋回それぞれ5枚ずつ、計15枚入っている。これを55枚ずつに増やす。
test_images_170804 ディレクトリに increase_images_test をコピーした。
increase_images_test を下に貼っておく。

#!/bin/bash
# increase_image_test
# for test

max=5

# contrast
for ((i=0; i < $max; i++)); do
    convert left_turn_test$i.bmp -contrast left_turn_test$(expr $i + $max).bmp
    convert right_turn_test$i.bmp -contrast right_turn_test$(expr $i + $max).bmp
    convert straight_test$i.bmp -contrast straight_test$(expr $i + $max).bmp
done

for ((i=0; i < $max; i++)); do
    convert left_turn_test$i.bmp -contrast -contrast left_turn_test$(expr $i + $max \* 2).bmp
    convert right_turn_test$i.bmp -contrast -contrast right_turn_test$(expr $i + $max \* 2).bmp
    convert straight_test$i.bmp -contrast -contrast straight_test$(expr $i + $max \* 2).bmp
done

for ((i=0; i < $max; i++)); do
    convert left_turn_test$i.bmp -contrast -contrast -contrast left_turn_test$(expr $i + $max \* 3).bmp
    convert right_turn_test$i.bmp -contrast -contrast -contrast right_turn_test$(expr $i + $max \* 3).bmp
    convert straight_test$i.bmp -contrast -contrast -contrast straight_test$(expr $i + $max \* 3).bmp
done

for ((i=0; i < $max; i++)); do
    convert left_turn_test$i.bmp +contrast left_turn_test$(expr $i + $max \* 4).bmp
    convert right_turn_test$i.bmp +contrast right_turn_test$(expr $i + $max \* 4).bmp
    convert straight_test$i.bmp +contrast straight_test$(expr $i + $max \* 4).bmp
done

for ((i=0; i < $max; i++)); do
    convert left_turn_test$i.bmp +contrast +contrast left_turn_test$(expr $i + $max \* 5).bmp
    convert right_turn_test$i.bmp +contrast +contrast right_turn_test$(expr $i + $max \* 5).bmp
    convert straight_test$i.bmp +contrast +contrast straight_test$(expr $i + $max \* 5).bmp
done

for ((i=0; i < $max; i++)); do
    convert left_turn_test$i.bmp +contrast +contrast +contrast left_turn_test$(expr $i + $max \* 6).bmp
    convert right_turn_test$i.bmp +contrast +contrast +contrast right_turn_test$(expr $i + $max \* 6).bmp
    convert straight_test$i.bmp +contrast +contrast +contrast straight_test$(expr $i + $max \* 6).bmp
done

# blur
for ((i=0; i < $max; i++)); do
    convert left_turn_test$i.bmp -blur 10x1.5 left_turn_test$(expr $i + $max \* 7).bmp
    convert right_turn_test$i.bmp -blur 10x1.5 right_turn_test$(expr $i + $max \* 7).bmp
    convert straight_test$i.bmp -blur 10x1.5 straight_test$(expr $i + $max \* 7).bmp
done

for ((i=0; i < $max; i++)); do
    convert left_turn_test$i.bmp -blur 10x2 left_turn_test$(expr $i + $max \* 8).bmp
    convert right_turn_test$i.bmp -blur 10x2 right_turn_test$(expr $i + $max \* 8).bmp
    convert straight_test$i.bmp -blur 10x2 straight_test$(expr $i + $max \* 8).bmp
done

#gamma
for ((i=0; i < $max; i++)); do
    convert left_turn_test$i.bmp -gamma 1.5 left_turn_test$(expr $i + $max \* 9).bmp
    convert right_turn_test$i.bmp -gamma 1.5 right_turn_test$(expr $i + $max \* 9).bmp
    convert straight_test$i.bmp -gamma 1.5 straight_test$(expr $i + $max \* 9).bmp
done

for ((i=0; i < $max; i++)); do
    convert left_turn_test$i.bmp -gamma 0.75 left_turn_test$(expr $i + $max \* 10).bmp
    convert right_turn_test$i.bmp -gamma 0.75 right_turn_test$(expr $i + $max \* 10).bmp
    convert straight_test$i.bmp -gamma 0.75 straight_test$(expr $i + $max \* 10).bmp
done


./increase_images_test で実行した。
wlt_cnn_63_170823.png

テスト用の画像が直進、左旋回、右旋回それぞれ55 枚ずつに増えた。

straight_test_data.h と straight_test_data.cpp を用意した。これは、前回のC ソースコードの処理するファイル名を変更しただけだ。
wlt_cnn_64_170823.png

wlt_cnn_65_170823.png

C シミュレーションを行った。
wlt_cnn_66_170823.png

~/Vivado_HLS/PYNQ/straight_test_dataset3/solution1/csim/build に test_straight_run_image と test_straight_run_label が生成された。
wlt_cnn_67_170823.png

test_straight_run_image の内容に一部を示す。
wlt_cnn_68_170823.png

101d は 4125 を示し、テスト用画像が 4125 個あることを示す。
  1. 2017年08月23日 05:07 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

白線追従走行用畳み込みニューラルネットワークの製作11(トレーニング用画像ファイルとラベル・ファイルの作成)

白線追従走行用畳み込みニューラルネットワークの製作10(画像を増やす)”の続き。

前回は、imagemagic を使用して、トレーニング画像を33枚から 363 枚に増やした。今回は、それをMNISTデータの形にしてからトレーニング用画像ファイル train_straight_run_image とトレーニング用ラベル・ファイル train_straight_run_label を作成した。

まずは、前回作ってあって、そのディレクトリの下で作業をしていたのだが、Vivado HLS 2016.4 のプロジェクト straight_dataset_bmp3 プロジェクトを作ってあった。それに straigh_dataset_bmp_nowr.cpp と straigh_dataset_bmp.h を追加した。
wlt_cnn_57_170822.png

wlt_cnn_58_170822.png

straigh_dataset_bmp.h は、STRAIGHT_NUM_OF_IMAGE、LEFT_TRUN_NUM_OF_IMAGE、RIGHT_TRUNNUM_OF_IMAGEをそれぞれ、121 に設定した。
straigh_dataset_bmp_nowr.cpp は、BMPファイルを書かないようにしたC ソースコードで、この下に貼っておく。

// straight_dataset_bmp_nowr.cpp
// 2017/07/24 by marsee
//
// 2017/08/21 : no write bmp files
//

#include <iostream>
#include "hls_opencv.h"
#include "straight_dataset_bmp.h"
#include <arpa/inet.h>

const char IMAGE_DIR[] = "train_data_170808";

int main(){
    char straight_fn[256] = "straight";
    char left_turn_fn[256] = "left_turn";
    char right_turn_fn[256] = "right_turn";
    char bmp_file[256];
    FILE *ftin, *ftln;
    char train_image_name[256] = "train_straight_run_image";
    char train_label_name[256] = "train_straight_run_label";
    uint32_t buf[5];
    uint8_t bufchar[100];


    if ((ftin = fopen(train_image_name, "wb")) == NULL){
        fprintf(stderr, "Can't open %s\n", train_image_name);
        exit(1);
    }
    if ((ftln = fopen(train_label_name, "wb")) == NULL){
        fprintf(stderr, "Can't open %s\n", train_label_name);
        exit(1);
    }

    // Writed header
    buf[0] = htonl(0x803); // magic number
    buf[1] = htonl((STRAIGHT_NUM_OF_IMAGE+LEFT_TRUN_NUM_OF_IMAGE+RIGHT_TRUNNUM_OF_IMAGE)*25); // number of image
    buf[2] = htonl(10); // number of rows (10)
    buf[3] = htonl(56); // number of columns (56)
    fwrite(buf, sizeof(uint32_t), 4, ftin);

    buf[0] = htonl(0x801); // magic number
    buf[1] = htonl((STRAIGHT_NUM_OF_IMAGE+LEFT_TRUN_NUM_OF_IMAGE+RIGHT_TRUNNUM_OF_IMAGE)*25); // number of image
    fwrite(buf, sizeof(uint32_t), 2, ftln);

    // refereed to http://opencv.jp/cookbook/opencv_img.html
    // straight
    for(int i=0; i<STRAIGHT_NUM_OF_IMAGE; i++){
        sprintf(bmp_file, "%s/%s%d.bmp", IMAGE_DIR, straight_fn, i);
        cv::Mat straight_img = cv::imread(bmp_file,1);
        if(straight_img.empty())
            return(-1);
        cv::Mat reduct_img(straight_img.rows*0.075, straight_img.cols*0.075, straight_img.type());
        cv::resize(straight_img, reduct_img, reduct_img.size(), cv::INTER_LINEAR);
        cv::Mat gray_img;
        cv::cvtColor(reduct_img, gray_img, CV_BGR2GRAY);

        //sprintf(bmp_file, "%s_RED%d.bmp", straight_fn, i);
        //cv::imwrite(bmp_file, gray_img);

        for(int y=0; y<5; y++){
            for(int x=0; x<5; x++){
                cv::Rect rect_center(x, 30+y, 5610);
                cv::Mat img_rect(gray_img, rect_center);
                //sprintf(bmp_file, "%s_RED_rect%d_%d%d.bmp", straight_fn, i, y, x);
                //cv::imwrite(bmp_file, img_rect);

                for(int iy=0; iy<img_rect.rows; iy++){
                    for(int ix=0; ix<img_rect.cols; ix++){
                        bufchar[ix] = img_rect.at<uchar>(iy, ix);
                    }
                    fwrite(bufchar, sizeof(uint8_t), img_rect.cols, ftin); // image write
                }
                bufchar[0] = 0x1;
                fwrite(bufchar, sizeof(uint8_t), 1, ftln); // label write
            }
        }
    }

    // left turn
    for(int i=0; i<LEFT_TRUN_NUM_OF_IMAGE; i++){
        sprintf(bmp_file, "%s/%s%d.bmp", IMAGE_DIR, left_turn_fn, i);
        cv::Mat left_trun_img = cv::imread(bmp_file,1);
        if(left_trun_img.empty())
            return(-1);
        cv::Mat reduct_img(left_trun_img.rows*0.075, left_trun_img.cols*0.075, left_trun_img.type());
        cv::resize(left_trun_img, reduct_img, reduct_img.size(), cv::INTER_LINEAR);
        cv::Mat gray_img;
        cv::cvtColor(reduct_img, gray_img, CV_BGR2GRAY);

        //sprintf(bmp_file, "%s_RED%d.bmp", left_turn_fn, i);
        //cv::imwrite(bmp_file, gray_img);

        for(int y=0; y<5; y++){
            for(int x=0; x<5; x++){
                cv::Rect rect_center(x, 30+y, 5610);
                cv::Mat img_rect(gray_img, rect_center);
                //sprintf(bmp_file, "%s_RED_rect%d_%d%d.bmp", left_turn_fn, i, y, x);
                //cv::imwrite(bmp_file, img_rect);

                for(int iy=0; iy<img_rect.rows; iy++){
                    for(int ix=0; ix<img_rect.cols; ix++){
                        bufchar[ix] = img_rect.at<uchar>(iy, ix);
                    }
                    fwrite(bufchar, sizeof(uint8_t), img_rect.cols, ftin); // image write
                }
                bufchar[0] = 0x0;
                fwrite(bufchar, sizeof(uint8_t), 1, ftln); // label write
            }
        }
    }

    // right turn
    for(int i=0; i<STRAIGHT_NUM_OF_IMAGE; i++){
        sprintf(bmp_file, "%s/%s%d.bmp", IMAGE_DIR, right_turn_fn, i);
        cv::Mat right_trun_img = cv::imread(bmp_file,1);
        if(right_trun_img.empty())
            return(-1);
        cv::Mat reduct_img(right_trun_img.rows*0.075, right_trun_img.cols*0.075, right_trun_img.type());
        cv::resize(right_trun_img, reduct_img, reduct_img.size(), cv::INTER_LINEAR);
        cv::Mat gray_img;
        cv::cvtColor(reduct_img, gray_img, CV_BGR2GRAY);

        //sprintf(bmp_file, "%s_RED%d.bmp", right_turn_fn, i);
        //cv::imwrite(bmp_file, gray_img);

        for(int y=0; y<5; y++){
            for(int x=0; x<5; x++){
                cv::Rect rect_center(x, 30+y, 5610);
                cv::Mat img_rect(gray_img, rect_center);
                //sprintf(bmp_file, "%s_RED_rect%d_%d%d.bmp", right_turn_fn, i, y, x);
                //cv::imwrite(bmp_file, img_rect);

                for(int iy=0; iy<img_rect.rows; iy++){
                    for(int ix=0; ix<img_rect.cols; ix++){
                        bufchar[ix] = img_rect.at<uchar>(iy, ix);
                    }
                    fwrite(bufchar, sizeof(uint8_t), img_rect.cols, ftin); // image write
                }
                bufchar[0] = 0x2;
                fwrite(bufchar, sizeof(uint8_t), 1, ftln); // label write
            }
        }
    }

    fclose(ftin);
    fclose(ftln);

    return(0);
}


C シミュレーションを行ったが、最初うまく行かなかった。”Ubuntu 16.04 上のVivado HLS 2017.2 でOpenCV を使用したプロジェクトでエラー発生”の解決策の
sudo apt-get install libjpeg62-dev
を実行したら、コンパイルできるようになった。
C シミュレーションの結果を示す。成功した。
wlt_cnn_59_170822.png

~/Vivado_HLS/PYNQ/straight_dataset_bmp3/solution1/csim/build に train_straight_run_image と train_straight_run_label が生成された。
wlt_cnn_60_170822.png

train_straight_run_image の内容の一部を示す。2373 は 10 進数で 9075 となる。
wlt_cnn_61_170823.png
  1. 2017年08月23日 04:41 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

白線追従走行用畳み込みニューラルネットワークの製作10(画像を増やす)

白線追従走行用畳み込みニューラルネットワークの製作9(再度、学習)”の続き。

前回、精度が上がらなかったので、画像を増やしてトレーニングしてみようということになった。今回はimagemagic を使って画像を増やしてみよう。

imagemagic はツィッターで ame_feb4 さんに教えてもらった。ありがとうございました。
imagemagic の使い方がここにある。これを参照してスクリプトを作った。

まず画像の増やし方は、”機械学習のデータセット画像枚数を増やす方法”を参考にした。

画像のコントラストを増やす方向で3セット、画像のコントラストを減らす方向で3セット、ぼかしで2セット、ガンマ値で2セットの画像を作ることにした。

スクリプトのincrease_images を示す。

#!/bin/bash
# increase_image

max=11

# contrast
for ((i=0; i < $max; i++)); do
    convert left_turn$i.bmp -contrast left_turn$(expr $i + $max).bmp
    convert right_turn$i.bmp -contrast right_turn$(expr $i + $max).bmp
    convert straight$i.bmp -contrast straight$(expr $i + $max).bmp
done

for ((i=0; i < $max; i++)); do
    convert left_turn$i.bmp -contrast -contrast left_turn$(expr $i + $max \* 2).bmp
    convert right_turn$i.bmp -contrast -contrast right_turn$(expr $i + $max \* 2).bmp
    convert straight$i.bmp -contrast -contrast straight$(expr $i + $max \* 2).bmp
done

for ((i=0; i < $max; i++)); do
    convert left_turn$i.bmp -contrast -contrast -contrast left_turn$(expr $i + $max \* 3).bmp
    convert right_turn$i.bmp -contrast -contrast -contrast right_turn$(expr $i + $max \* 3).bmp
    convert straight$i.bmp -contrast -contrast -contrast straight$(expr $i + $max \* 3).bmp
done

for ((i=0; i < $max; i++)); do
    convert left_turn$i.bmp +contrast left_turn$(expr $i + $max \* 4).bmp
    convert right_turn$i.bmp +contrast right_turn$(expr $i + $max \* 4).bmp
    convert straight$i.bmp +contrast straight$(expr $i + $max \* 4).bmp
done

for ((i=0; i < $max; i++)); do
    convert left_turn$i.bmp +contrast +contrast left_turn$(expr $i + $max \* 5).bmp
    convert right_turn$i.bmp +contrast +contrast right_turn$(expr $i + $max \* 5).bmp
    convert straight$i.bmp +contrast +contrast straight$(expr $i + $max \* 5).bmp
done

for ((i=0; i < $max; i++)); do
    convert left_turn$i.bmp +contrast +contrast +contrast left_turn$(expr $i + $max \* 6).bmp
    convert right_turn$i.bmp +contrast +contrast +contrast right_turn$(expr $i + $max \* 6).bmp
    convert straight$i.bmp +contrast +contrast +contrast straight$(expr $i + $max \* 6).bmp
done

# blur
for ((i=0; i < $max; i++)); do
    convert left_turn$i.bmp -blur 10x1.5 left_turn$(expr $i + $max \* 7).bmp
    convert right_turn$i.bmp -blur 10x1.5 right_turn$(expr $i + $max \* 7).bmp
    convert straight$i.bmp -blur 10x1.5 straight$(expr $i + $max \* 7).bmp
done

for ((i=0; i < $max; i++)); do
    convert left_turn$i.bmp -blur 10x2 left_turn$(expr $i + $max \* 8).bmp
    convert right_turn$i.bmp -blur 10x2 right_turn$(expr $i + $max \* 8).bmp
    convert straight$i.bmp -blur 10x2 straight$(expr $i + $max \* 8).bmp
done

#gamma
for ((i=0; i < $max; i++)); do
    convert left_turn$i.bmp -gamma 1.5 left_turn$(expr $i + $max \* 9).bmp
    convert right_turn$i.bmp -gamma 1.5 right_turn$(expr $i + $max \* 9).bmp
    convert straight$i.bmp -gamma 1.5 straight$(expr $i + $max \* 9).bmp
done

for ((i=0; i < $max; i++)); do
    convert left_turn$i.bmp -gamma 0.75 left_turn$(expr $i + $max \* 10).bmp
    convert right_turn$i.bmp -gamma 0.75 right_turn$(expr $i + $max \* 10).bmp
    convert straight$i.bmp -gamma 0.75 straight$(expr $i + $max \* 10).bmp
done


これで、11枚 x 3 の画像が 121枚 x 3 の画像になる。

それではやってみよう。”白線追従走行用畳み込みニューラルネットワークの製作9(再度、学習)”で使ったトレーニングデータの tran_data_170808 に increase_images を入れた。
wlt_cnn_51_170821.png

まず、sudo apt install imagemagick でインストールすると、すでに入っていた。
wlt_cnn_52_170821.png

./increase_images で実行した。
wlt_cnn_53_170821.png

画像が増えた。
wlt_cnn_54_170821.png

nautilus で見たときの最初
wlt_cnn_55_170821.png

nautilus で見たときの最後
wlt_cnn_56_170821.png

これで、33枚が 363 枚に増えた。これが 25 倍に増えるので、最終的には、 363 x 25 = 9075 枚になる。
  1. 2017年08月22日 05:37 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

白線追従走行用畳み込みニューラルネットワークの製作9(再度、学習)

白線追従走行用畳み込みニューラルネットワークの製作8(再度トレーニング、ラベル・ファイルの作成)”の続き。

前回、白線追従走行の直進走行用の画像データを取り直して、トレーニング・ファイルとラベル・ファイルを作成した。そのトレーニング・ファイルとラベル・ファイルを使用して、学習してみよう。
なお、前回の学習のブログは、
白線追従走行用畳み込みニューラルネットワークの製作6(学習1)
白線追従走行用畳み込みニューラルネットワークの製作7(学習2)
だ。

まずは、前回生成したトレーニング・ファイル(train_straight_run_image)とラベル・ファイル(train_straight_run_label)を deep-learning-from-scratch\dataset_straight にコピー&ペーストした。以前のトレーニング・ファイルとラベル・ファイルは後ろに _750 を付けて保存しておいた。今回のデータファイルの要素数は 825 だ。
wlt_cnn_47_170821.png

mnist.pkl はトレーニング・データのキャッシュなので、これを削除する。

次に、同じフォルダのstraight_dataset.py の train_num を 750 から 825 に修正した。
wlt_cnn_48_170821.png

jupyter notebook を立ち上げて、DLFS_Chap7_integer.ipynb を起動した。
wlt_cnn_49_170821.png

train_convnet.py を実行して学習を行った。結果を示す。

pool_output_size =2340
train loss:1.09597077527
=== epoch:1, train acc:0.0, test acc:0.0 ===
train loss:1.09763818641
train loss:1.09825520224
train loss:1.09830713311
train loss:1.09483577203
train loss:1.09673085529
train loss:1.09591664135
train loss:1.09249280974
train loss:1.08987641387
train loss:1.08545885042
train loss:1.08117723144
train loss:1.08097061845
train loss:1.06785401247
train loss:1.06847091152
train loss:1.07555744076
train loss:1.04351469112
train loss:1.04435821276
train loss:1.03649227153
train loss:1.02536538003
train loss:1.00731901572
train loss:0.994094999178
train loss:0.973141656596
train loss:0.970560099646
train loss:0.925359858257
train loss:0.922232065606
train loss:0.890463657306
train loss:0.857971776813
train loss:0.808963625972
train loss:0.810114333796
train loss:0.790134792491
train loss:0.75177290901
train loss:0.719148569532
train loss:0.703947163294
train loss:0.733538828557
=== epoch:2, train acc:1.0, test acc:0.97 ===
train loss:0.626812813265
train loss:0.691149885713
train loss:0.652269563466
train loss:0.551628036238
train loss:0.573457780284
train loss:0.555262535477
train loss:0.569233568195
train loss:0.608432180822
train loss:0.576392359819
train loss:0.553962266041
train loss:0.631553098995
train loss:0.541951265715
train loss:0.59235235809
train loss:0.570984798898
train loss:0.618629636193
train loss:0.519372445675
train loss:0.528735330839
train loss:0.484056856152
train loss:0.536815249815
train loss:0.561484523189
train loss:0.623591206274
train loss:0.442553097887
train loss:0.631538407003
train loss:0.543256943224
train loss:0.571884326854
train loss:0.59330093491
train loss:0.543568052814
train loss:0.625170917522
train loss:0.609623989829
train loss:0.626034861444
train loss:0.53018319314
train loss:0.478202730277
train loss:0.519885098008
=== epoch:3, train acc:1.0, test acc:0.79 ===
train loss:0.547483270221
train loss:0.645673557139
train loss:0.522337685379
train loss:0.536177468441
train loss:0.468486580763
train loss:0.515871224274
train loss:0.457075387848
train loss:0.398502113575
train loss:0.547250552889
train loss:0.47266059459
train loss:0.58253528562
train loss:0.563849158638
train loss:0.584245273642
train loss:0.490038949342
train loss:0.575957945909
train loss:0.53032895386
train loss:0.598642706188
train loss:0.51896606919
train loss:0.447935727928
train loss:0.523748197354
train loss:0.630220932465
train loss:0.475171119124
train loss:0.552545002799
train loss:0.418398639435
train loss:0.54651784985
train loss:0.54795133755
train loss:0.484632026785
train loss:0.486523131145
train loss:0.608954877859
train loss:0.52597657247
train loss:0.550768419421
train loss:0.510231459765
train loss:0.514870472085
=== epoch:4, train acc:1.0, test acc:0.86 ===
train loss:0.554327599733
train loss:0.476852300198
train loss:0.528736145907
train loss:0.431610455794
train loss:0.492618692268
train loss:0.523164350434
train loss:0.583515316911
train loss:0.456262940166
train loss:0.385874800448
train loss:0.391292082306
train loss:0.493916291898
train loss:0.469376182458
train loss:0.511861331662
train loss:0.555790656279
train loss:0.552997199476
train loss:0.491419451075
train loss:0.427534856105
train loss:0.462498766512
train loss:0.671785632209
train loss:0.674157815366
train loss:0.508518571047
train loss:0.454157308456
train loss:0.588429704378
train loss:0.539304639676
train loss:0.461259212557
train loss:0.439467592743
train loss:0.486391964423
train loss:0.541361700557
train loss:0.765172284665
train loss:0.557673416383
train loss:0.472034860108
train loss:0.467462631341
train loss:0.473195698334
=== epoch:5, train acc:0.94, test acc:0.63 ===
train loss:0.621301963466
train loss:0.519214259086
train loss:0.592548430631
train loss:0.44266943545
train loss:0.418137479978
train loss:0.458057503538
train loss:0.487746201447
train loss:0.542828607541
train loss:0.412820783943
train loss:0.387734335894
train loss:0.504347603465
train loss:0.372213430157
train loss:0.566137812809
train loss:0.511320738505
train loss:0.372290661458
train loss:0.43099129379
train loss:0.446050407765
train loss:0.580177285636
train loss:0.521574375012
train loss:0.470257839398
train loss:0.358914879585
train loss:0.429000331704
train loss:0.532481848172
train loss:0.487614622413
train loss:0.512510956562
train loss:0.443207619531
train loss:0.453973643453
train loss:0.527084108842
train loss:0.411040275113
train loss:0.514922929244
train loss:0.440648980547
train loss:0.521523873667
=============== Final Test Accuracy ===============
test acc:0.701333333333
Saved Network Parameters!
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-1-2cecdfeafa8d> in <module>()
     39 markers = {'train': 'o', 'test': 's'}
     40 x = np.arange(max_epochs)
---> 41 plt.plot(x, trainer.train_acc_list, marker='o', label='train', markevery=2)
     42 plt.plot(x, trainer.test_acc_list, marker='s', label='test', markevery=2)
     43 plt.xlabel("epochs")

C:\Users\Masaaki\Anaconda3\lib\site-packages\matplotlib\pyplot.py in plot(*args, **kwargs)
   3316                       mplDeprecation)
   3317     try:
-> 3318         ret = ax.plot(*args, **kwargs)
   3319     finally:
   3320         ax._hold = washold

C:\Users\Masaaki\Anaconda3\lib\site-packages\matplotlib\__init__.py in inner(ax, *args, **kwargs)
   1889                     warnings.warn(msg % (label_namer, func.__name__),
   1890                                   RuntimeWarning, stacklevel=2)
-> 1891             return func(ax, *args, **kwargs)
   1892         pre_doc = inner.__doc__
   1893         if pre_doc is None:

C:\Users\Masaaki\Anaconda3\lib\site-packages\matplotlib\axes\_axes.py in plot(self, *args, **kwargs)
   1404         kwargs = cbook.normalize_kwargs(kwargs, _alias_map)
   1405 
-> 1406         for line in self._get_lines(*args, **kwargs):
   1407             self.add_line(line)
   1408             lines.append(line)

C:\Users\Masaaki\Anaconda3\lib\site-packages\matplotlib\axes\_base.py in _grab_next_args(self, *args, **kwargs)
    405                 return
    406             if len(remaining) <= 3:
--> 407                 for seg in self._plot_args(remaining, kwargs):
    408                     yield seg
    409                 return

C:\Users\Masaaki\Anaconda3\lib\site-packages\matplotlib\axes\_base.py in _plot_args(self, tup, kwargs)
    383             x, y = index_of(tup[-1])
    384 
--> 385         x, y = self._xy_from_xy(x, y)
    386 
    387         if self.command == 'plot':

C:\Users\Masaaki\Anaconda3\lib\site-packages\matplotlib\axes\_base.py in _xy_from_xy(self, x, y)
    242         if x.shape[0] != y.shape[0]:
    243             raise ValueError("x and y must have same first dimension, but "
--> 244                              "have shapes {} and {}".format(x.shape, y.shape))
    245         if x.ndim > 2 or y.ndim > 2:
    246             raise ValueError("x and y can be no greater than 2-D, but have "

ValueError: x and y must have same first dimension, but have shapes (20,) and (5,)

In [ ]:


テストデータの精度は70 % で以前のトレーニング・データの時と変化はない。なお、7 回くらい実行して良い結果を取っている。
次は、トレーニング・データやテスト・データを増やしてみようと思う。
  1. 2017年08月21日 05:22 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

白線追従走行用畳み込みニューラルネットワークの製作8(再度トレーニング、ラベル・ファイルの作成)

白線追従走行用畳み込みニューラルネットワークの製作7(学習2)”の続き。

白線追従走行用畳み込みニューラルネットワークの製作7(学習2)”で、精度が 71 % だったので、もう一度、白線追従直進走行用の画像データをもう一度取得して、再度トレーニング・ファイルとラベル・ファイルを作成することにした。(前回のトレーニング・ファイルとラベル・ファイルを作成は、”白線追従走行用畳み込みニューラルネットワークの製作3(トレーニング、ラベル・ファイルの作成)”を参照のこと)

画像データを取得したときの条件を示す。

ストレート(straight)
0: 角度 0 度、白線真ん中
1: 角度 0 度、左白線の内側エッジに左車輪の真ん中がくるように置いた
2: 角度 0 度、右白線の内側エッジにに右車輪の真ん中がくるように置いた
3: 角度 -5度、白線真ん中
4: 角度 +5 度、白線真ん中
5: 角度 -2 度、白線真ん中
6: 角度 +2 度、白線真ん中
7: 角度 -2 度、左白線の内側エッジにに左車輪の真ん中がくるように置いた
8: 角度 +2 度、右白線の内側エッジにに右車輪の真ん中がくるように置いた
9: 角度 0 度、左白線の真ん中に左車輪の真ん中を置いた
10: 角度 0 度、右白線の真ん中に右車輪の真ん中を置いた

左ターン(left_turn)
0: 角度 0 度、右白線外側のエッジに右車輪の真ん中がくるように置いた
1: 角度 0 度、右車輪逸脱車体1/4
2: 角度 +5 度、右車輪逸脱車体1/4
3: 角度 +10 度、右車輪逸脱車体1/4
4: 角度 0 度、右車輪逸脱車体1/2
5: 角度 +5 度、右車輪逸脱車体1/2
6: 角度 +10 度、白線真ん中
7: 角度 +15 度、白線真ん中
8: 角度 +20 度、白線真ん中
9: 角度 +5 度、右白線の内側エッジにに右車輪の真ん中がくるように置いた
10: 角度 +10 度、右白線の内側エッジにに右車輪の真ん中がくるように置いた

右ターン(right_turn)
0: 角度 0 度、左白線外側のエッジに左車輪の真ん中がくるように置いた
1: 角度 0 度、左車輪逸脱車体1/4
2: 角度 -5 度、左車輪逸脱車体1/4
3: 角度 -10 度、左車輪逸脱車体1/4
4: 角度 0 度、左車輪逸脱車体1/2
5: 角度 -5 度、左車輪逸脱車体1/2
6: 角度 -10 度、白線真ん中
7: 角度 -15 度、白線真ん中
8: 角度 -20 度、白線真ん中
9: 角度 -5 度、左白線の内側エッジにに左車輪の真ん中がくるように置いた
10: 角度 -10 度、左白線の内側エッジにに左車輪の真ん中がくるように置いた

これで取得した画像データを示す。
wlt_cnn_43_170820.png

VirtualBox 上のUbuntu 16.04 でVivado HLS 2016.4 を立ち上げて、~/Vivado_HLS/PYNQ/straigh_dataset_bmp2 に straigh_dataset_bmp2 プロジェクトを作成して、straight_dataset_bmp.cpp と straight_dataset_bmp.h をコピー&ペーストした。今回、撮影した白線の画像データもコピー&ペーストして、プロジェクトのテストベンチに入れた。
wlt_cnn_44_170820.png

C シミュレーションを行った。ファイルがいろいろと作成された。
wlt_cnn_45_170820.png

~/Vivado_HLS/PYNQ/straigh_dataset_bmp2/solution1/csim/build ディレクトリに train_straight_run_image と train_straight_run_label
が生成された。
wlt_cnn_46_170820.png

今回、トレーニング・ファイルとラベル・ファイルの画像データが増えたので、straight_dataset_bmp.cpp と straight_dataset_bmp.h を変更した。
straight_dataset_bmp.h を示す。

// straight_dataset_bmp.h
// 2017/07/24 by marsee
//

#ifndef __STRAIGHT_DATASET_BMP_H__
#define __STRAIGHT_DATASET_BMP_H__

#include "hls_video.h"

#define BMP_HEIGHT    600
#define BMP_WIDTH    800

#define REDUCTION_RATIO    0.075    // 1/13.3333... 60x45

#define DATASET_HEIGHT    10
#define DATASET_WIDTH    56

#define STRAIGHT_BMP_FILE_NAME        straight
#define LEFT_TRUN_BMP_FILE_NAME        left_turn
#define RIGHT_TRUN_BMP_FILE_NAME    right_turn
#define STRAIGHT_NUM_OF_IMAGE        11
#define LEFT_TRUN_NUM_OF_IMAGE        11
#define    RIGHT_TRUNNUM_OF_IMAGE        11

typedef hls::Scalar<3unsigned char> RGB_PIXEL;
typedef hls::Mat<BMP_HEIGHT, BMP_WIDTH, HLS_8UC3> RGB_IMAGE;
typedef hls::Mat<BMP_HEIGHT, BMP_WIDTH, HLS_8UC1> GRAY_IMAGE;

#endif


straight_dataset_bmp.cpp を示す。

// straight_dataset_bmp.cpp
// 2017/07/24 by marsee
//

#include <iostream>
#include "hls_opencv.h"
#include "straight_dataset_bmp.h"
#include <arpa/inet.h>

int main(){
    char straight_fn[256] = "straight";
    char left_turn_fn[256] = "left_turn";
    char right_turn_fn[256] = "right_turn";
    char bmp_file[256];
    FILE *ftin, *ftln;
    char train_image_name[256] = "train_straight_run_image";
    char train_label_name[256] = "train_straight_run_label";
    uint32_t buf[5];
    uint8_t bufchar[100];


    if ((ftin = fopen(train_image_name, "wb")) == NULL){
        fprintf(stderr, "Can't open %s\n", train_image_name);
        exit(1);
    }
    if ((ftln = fopen(train_label_name, "wb")) == NULL){
        fprintf(stderr, "Can't open %s\n", train_label_name);
        exit(1);
    }

    // Writed header
    buf[0] = htonl(0x803); // magic number
    buf[1] = htonl(5*5*(STRAIGHT_NUM_OF_IMAGE+LEFT_TRUN_NUM_OF_IMAGE+RIGHT_TRUNNUM_OF_IMAGE));
     // number of image
    buf[2] = htonl(10); // number of rows (10)
    buf[3] = htonl(56); // number of columns (56)
    fwrite(buf, sizeof(uint32_t), 4, ftin);

    buf[0] = htonl(0x801); // magic number
    buf[1] = htonl(5*5*(STRAIGHT_NUM_OF_IMAGE+LEFT_TRUN_NUM_OF_IMAGE+RIGHT_TRUNNUM_OF_IMAGE));
     // number of image
    fwrite(buf, sizeof(uint32_t), 2, ftln);

    // refereed to http://opencv.jp/cookbook/opencv_img.html
    // straight
    for(int i=0; i<STRAIGHT_NUM_OF_IMAGE; i++){
        sprintf(bmp_file, "%s%d.bmp", straight_fn, i);
        cv::Mat straight_img = cv::imread(bmp_file,1);
        if(straight_img.empty())
            return(-1);
        cv::Mat reduct_img(straight_img.rows*0.075, straight_img.cols*0.075, straight_img.type());
        cv::resize(straight_img, reduct_img, reduct_img.size(), cv::INTER_LINEAR);
        cv::Mat gray_img;
        cv::cvtColor(reduct_img, gray_img, CV_BGR2GRAY);

        sprintf(bmp_file, "%s_RED%d.bmp", straight_fn, i);
        cv::imwrite(bmp_file, gray_img);

        for(int y=0; y<5; y++){
            for(int x=0; x<5; x++){
                cv::Rect rect_center(x, 30+y, 5610);
                cv::Mat img_rect(gray_img, rect_center);
                sprintf(bmp_file, "%s_RED_rect%d_%d%d.bmp", straight_fn, i, y, x);
                cv::imwrite(bmp_file, img_rect);

                for(int iy=0; iy<img_rect.rows; iy++){
                    for(int ix=0; ix<img_rect.cols; ix++){
                        bufchar[ix] = img_rect.at<uchar>(iy, ix);
                    }
                    fwrite(bufchar, sizeof(uint8_t), img_rect.cols, ftin); // image write
                }
                bufchar[0] = 0x1;
                fwrite(bufchar, sizeof(uint8_t), 1, ftln); // label write
            }
        }
    }

    // left turn
    for(int i=0; i<LEFT_TRUN_NUM_OF_IMAGE; i++){
        sprintf(bmp_file, "%s%d.bmp", left_turn_fn, i);
        cv::Mat left_trun_img = cv::imread(bmp_file,1);
        if(left_trun_img.empty())
            return(-1);
        cv::Mat reduct_img(left_trun_img.rows*0.075, left_trun_img.cols*0.075, left_trun_img.type());
        cv::resize(left_trun_img, reduct_img, reduct_img.size(), cv::INTER_LINEAR);
        cv::Mat gray_img;
        cv::cvtColor(reduct_img, gray_img, CV_BGR2GRAY);

        sprintf(bmp_file, "%s_RED%d.bmp", left_turn_fn, i);
        cv::imwrite(bmp_file, gray_img);

        for(int y=0; y<5; y++){
            for(int x=0; x<5; x++){
                cv::Rect rect_center(x, 30+y, 5610);
                cv::Mat img_rect(gray_img, rect_center);
                sprintf(bmp_file, "%s_RED_rect%d_%d%d.bmp", left_turn_fn, i, y, x);
                cv::imwrite(bmp_file, img_rect);

                for(int iy=0; iy<img_rect.rows; iy++){
                    for(int ix=0; ix<img_rect.cols; ix++){
                        bufchar[ix] = img_rect.at<uchar>(iy, ix);
                    }
                    fwrite(bufchar, sizeof(uint8_t), img_rect.cols, ftin); // image write
                }
                bufchar[0] = 0x0;
                fwrite(bufchar, sizeof(uint8_t), 1, ftln); // label write
            }
        }
    }

    // right turn
    for(int i=0; i<STRAIGHT_NUM_OF_IMAGE; i++){
        sprintf(bmp_file, "%s%d.bmp", right_turn_fn, i);
        cv::Mat right_trun_img = cv::imread(bmp_file,1);
        if(right_trun_img.empty())
            return(-1);
        cv::Mat reduct_img(right_trun_img.rows*0.075, right_trun_img.cols*0.075, right_trun_img.type());
        cv::resize(right_trun_img, reduct_img, reduct_img.size(), cv::INTER_LINEAR);
        cv::Mat gray_img;
        cv::cvtColor(reduct_img, gray_img, CV_BGR2GRAY);

        sprintf(bmp_file, "%s_RED%d.bmp", right_turn_fn, i);
        cv::imwrite(bmp_file, gray_img);

        for(int y=0; y<5; y++){
            for(int x=0; x<5; x++){
                cv::Rect rect_center(x, 30+y, 5610);
                cv::Mat img_rect(gray_img, rect_center);
                sprintf(bmp_file, "%s_RED_rect%d_%d%d.bmp", right_turn_fn, i, y, x);
                cv::imwrite(bmp_file, img_rect);

                for(int iy=0; iy<img_rect.rows; iy++){
                    for(int ix=0; ix<img_rect.cols; ix++){
                        bufchar[ix] = img_rect.at<uchar>(iy, ix);
                    }
                    fwrite(bufchar, sizeof(uint8_t), img_rect.cols, ftin); // image write
                }
                bufchar[0] = 0x2;
                fwrite(bufchar, sizeof(uint8_t), 1, ftln); // label write
            }
        }
    }

    fclose(ftin);
    fclose(ftln);

    return(0);
}

  1. 2017年08月20日 06:51 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

ソニーのNeural Network Console をやってみた2

ソニーのNeural Network Console をやってみた1”の続き。

前回は、ソニーのNeural Network Console をインストールして、サンプルプロジェクトをやってみた。今回は更にサンプルプロジェクトをやってみることした。

まずは、binary_cnn。やはり、4 と 9 から 9 を選択する。
Neural_Network_Console_14_170818.png

ネットワークは、Input - 畳み込み - マックス・プーリング - Tanh - 畳み込み - マックス・プーリング - Tanh - 全結合 - Tanh - 全結合 - シグモイド - 交差エントロピー誤差だった。
Neural_Network_Console_15_170818.png

学習結果を示す。
Neural_Network_Console_16_170818.png

評価。
Neural_Network_Console_17_170818.png

Accuracy は 0.988 だった。”ソニーのNeural Network Console をやってみた1”のネットワークよりも精度が良い。
Neural_Network_Console_18_170818.png

次に、auto_encoder をやってみる。
Neural_Network_Console_19_170818.png

ネットワークは、Input - ドロップアウト - 全結合 - シグモイド - 全結合 - シグモイド - 2乗誤差 だった。
Neural_Network_Console_20_170818.png

学習の結果を示す。
Neural_Network_Console_21_170818.png

次は、deep_mlp を試してみた。
Neural_Network_Console_22_170818.png

ネットワークは Input - 全結合 - Tanh - 全結合 - Tanh - 全結合 - Tanh - 全結合 - Tanh - 全結合 - シグモイド - 交差エントロピー誤差だった。全結合が5層だ。
Neural_Network_Console_23_170818.png

学習結果を示す。
Neural_Network_Console_24_170818.png

精度は、0.966 だった。binary_cnn よりも精度が落ちている。
Neural_Network_Console_25_170818.png

residual_learning をやってみた。今回は、4 と 9 から 9 を推定ではなく、MNISTの 0 から 9 の手書き数字をすべて推定する。
Neural_Network_Console_26_170818.png

ネットワークはとっても長い。
Neural_Network_Console_27_170818.png
Neural_Network_Console_28_170818.png
Neural_Network_Console_29_170818.png
Neural_Network_Console_30_170818.png
Neural_Network_Console_31_170818.png

学習には、10時間程度かかった。
Neural_Network_Console_32_170819.png

さすがに精度は0.9913 で、今までで一番良い。というか、MNISTの数字の推定の結果だけれども。。。
Neural_Network_Console_33_170819.png
  1. 2017年08月19日 05:45 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

ソニーのNeural Network Console をやってみた1

Neural Network Console」という学習・評価だけでなく、ニューラルネットワークの設計までも可能なディープラーニング・ツールをソニーが無償提供したので、やってみることにした。

Neural Network Console」のページからNeural Network Console_V1.0.0 for Windows 8.1/10_64bit をダウンロードするリンクをメールアドレスを登録して送ってもらうことができる。
メールのリンクをクリックすると、neural_network_console_100.zip というファイルをダウンロードすることができた。中を見てみるとインストーラーは無いので、ファイルの中身をコピーした。
Neural_Network_Console_1_170818.png

Neural Network Console ドキュメントセットアップによると2バイト文字が含まれたパスにはインストールしないようにということだった。

フォルダを作成して、ZIP を解凍したファイルをコピーした。
Neural_Network_Console_2_170818.png

neural_network_console.exe をダブルクリックして、起動した。
すると、WindowsによってPC が保護されましたダイアログが出てきた。実行ボタンをクリックして、起動した。
Neural_Network_Console_3_170818.png

起動したところ、Microsoft Visual C++ 2015 Redistributable Package をインストールして、CUDAを最新にしろとのダイアログが出た。
Neural_Network_Console_4_170818.png

Microsoft Visual C++ 2015 Redistributable Update 3 RC のEnglish バージョンをダウンロード、インストールした。
NVIDIA のグラフィック・ドライバはバージョン: 385.28 があったので、インストールした。

もう一度、neural_network_console.exe を起動したが、やはり同じダイアログが出てきたので、Microsoft Visual C++ 2015 Redistributable Package をインストールして合ってもダイアログが出てしまうようだ。

チュートリアル:サンプルプロジェクトを用いた学習を参照して、最初のサンプル・プロジェクトの 01_logistic_regression.sdcproj をやってみた。

neural_network_console.exe の起動画面で 01_logistic_regression.sdcproj をクリックした。このプロジェクトはMNISTの4 と 9 の手書き数字から 9 を選ぶネットワークを学習するプロジェクトの様だ。
Neural_Network_Console_5_170818.png

MNISTデータをダウンロードしているようだ。
Neural_Network_Console_6_170818.png

入力 - 全結合ニューラルネットワーク - シグモイド関数 - バイナリ・交差エントロピー誤差 のネットワークのようだ。
Neural_Network_Console_7_170818.png

DATASET をクリックすると、データセットが見えた。4 が 0 で 9 が 1 という評価だ。
Neural_Network_Console_8_170818.png

EDIT をクリックすると、ネットワークの表示に戻る。Training のRun training ボタンをクリックして学習を始めた。
Neural_Network_Console_9_170818.png

すると、Learning Curveが表れて、どんどん学習が進んでいく様子が分かる。
Neural_Network_Console_10_170818.png

Evaluation の Run evaluation をクリックして、評価を行う。
Neural_Network_Console_11_170818.png

Evaluate ボタンが選択されて、評価結果が表示された。
Neural_Network_Console_12_170818.png

Confusion Matrix ラジオボタンをクリックした。
Accuracy が 0.,95 になっている。
Neural_Network_Console_13_170818.png
  1. 2017年08月18日 07:12 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

Vivado シミュレータでDPI-C を使用してZynq VIPを使う3

Vivado シミュレータでDPI-C を使用してZynq VIPを使う2”の続き。

前回は、コンパイルとエラボレートを行った。今回はいよいよxsim を走らせて、シミュレーション波形を出してみよう。

最初に、simulate.sh を開いて編集する。xsim のコマンドラインに -g を追加した。GUI を上げるためのオプションだ。
DPI_examples_26_170813.png

tb.tcl を開いて編集した。 run 1000 ns を run all に変更した。
DPI_examples_27_170813.png

.simulate.sh を実行した。
DPI_examples_34_170813.png

xsim のGUI が上がって、波形が表示された。
DPI_examples_28_170813.png

拡大した波形を示す。うまく行っているようだ。
DPI_examples_32_170813.png

シミュレーションを実行中の ~/Vivado/zynq_base_ex_172/zynq_base_ex_172.sim/sim_1/behav ディレクトリの内容を示す。
DPI_examples_33_170813.png

シミュレーションのログを貼っておく。

start_gui
source xsim.dir/tb_behav/xsim_script.tcl
# load_feature core
# current_fileset
INFO: [IP_Flow 19-234] Refreshing IP repositories
INFO: [IP_Flow 19-1704] No user IP repositories specified
INFO: [IP_Flow 19-2313] Loaded Vivado IP repository '/opt/Xilinx/Vivado/2017.2/data/ip'.
# xsim {tb_behav} -autoloadwcfg -tclbatch {tb.tcl} -key {Behavioral:sim_1:Functional:tb}
Vivado Simulator 2017.2
Time resolution is 1 ps
open_wave_config /home/masaaki/Vivado/zynq_base_ex_172/zynq_base_ex_172.sim/sim_1/behav/tb_behav.wcfg
source tb.tcl
## set curr_wave [current_wave_config]
## if { [string length $curr_wave] == 0 } {
## if { [llength [get_objects]] > 0} {
## add_wave /
## set_property needs_save false [current_wave_config]
## } else {
## send_msg_id Add_Wave-1 WARNING "No top level signals found. Simulator will start without a wave window. If you want to open a wave window go to 'File->New Waveform Configuration' or type 'create_wave_config' in the TCL console."
## }
## }
## run all
Block Memory Generator module tb.zynq_sys.base_zynq_i.blk_mem_gen_0.inst.native_mem_mapped_module.blk_mem_gen_v8_3_6_inst is using a behavioral model for simulation which will not precisely model memory collision behavior.
XilinxAXIVIP: Found at Path: tb.zynq_sys.base_zynq_i.processing_system7_0.inst.M_AXI_GP0.master
[0] : *ZYNQ_BFM_INFO : M_AXI_GP0 : Port is ENABLED.
XilinxAXIVIP: Found at Path: tb.zynq_sys.base_zynq_i.processing_system7_0.inst.M_AXI_GP1.master
[0] : *ZYNQ_BFM_INFO : M_AXI_GP1 : Port is DISABLED.
XilinxAXIVIP: Found at Path: tb.zynq_sys.base_zynq_i.processing_system7_0.inst.S_AXI_GP0.slave
[0] : *ZYNQ_BFM_INFO : S_AXI_GP0 : Port is DISABLED.
XilinxAXIVIP: Found at Path: tb.zynq_sys.base_zynq_i.processing_system7_0.inst.S_AXI_GP1.slave
[0] : *ZYNQ_BFM_INFO : S_AXI_GP1 : Port is DISABLED.
XilinxAXIVIP: Found at Path: tb.zynq_sys.base_zynq_i.processing_system7_0.inst.S_AXI_HP0.slave
[0] : *ZYNQ_BFM_INFO : S_AXI_HP0 : Port is DISABLED.
XilinxAXIVIP: Found at Path: tb.zynq_sys.base_zynq_i.processing_system7_0.inst.S_AXI_HP1.slave
[0] : *ZYNQ_BFM_INFO : S_AXI_HP1 : Port is DISABLED.
XilinxAXIVIP: Found at Path: tb.zynq_sys.base_zynq_i.processing_system7_0.inst.S_AXI_HP2.slave
[0] : *ZYNQ_BFM_INFO : S_AXI_HP2 : Port is DISABLED.
XilinxAXIVIP: Found at Path: tb.zynq_sys.base_zynq_i.processing_system7_0.inst.S_AXI_HP3.slave
[0] : *ZYNQ_BFM_INFO : S_AXI_HP3 : Port is DISABLED.
XilinxAXIVIP: Found at Path: tb.zynq_sys.base_zynq_i.processing_system7_0.inst.S_AXI_ACP.slave
[0] : *ZYNQ_BFM_INFO : S_AXI_ACP : Port is DISABLED.
running the tb
[150] : *ZYNQ_BFM_INFO : FPGA Soft Reset called for 0x1
[150] : *ZYNQ_BFM_INFO : FPGA Soft Reset called for 0x0
[150] : M_AXI_GP0 : *ZYNQ_BFM_INFO : Starting Address(0x41200000) -> AXI Write -> 4 bytes
[1490] : M_AXI_GP0 : *ZYNQ_BFM_INFO : Done AXI Write for Starting Address(0x41200000) with Response 'OKAY'
LEDs are toggled, observe the waveform
[1490] : M_AXI_GP0 : *ZYNQ_BFM_INFO : Starting Address(0x40000000) -> AXI Write -> 4 bytes
[1790] : M_AXI_GP0 : *ZYNQ_BFM_INFO : Done AXI Write for Starting Address(0x40000000) with Response 'OKAY'
[1790] : M_AXI_GP0 : *ZYNQ_BFM_INFO : Starting Address(0x40000000) -> AXI Read -> 4 bytes
[1950] : M_AXI_GP0 : *ZYNQ_BFM_INFO : Done AXI Read for Starting Address(0x40000000) with Response 'OKAY'
1950000, running the testbench, data read from BRAM was 32'hdeadbeef
AXI VIP Test PASSED
Simulation completed


次に、2番目のWrite と Read のアドレスを 0x4000004 にしてみよう。更に、Write の delay を 500 にしてみる。
DPI_examples_39_170816.png

これで、compile.sh , elaborate.sh , simulate.sh を再実行した。波形を示す。
DPI_examples_37_170816.png

AWADDR を見ると 40000004 になっているのが分かる。更に、前のWrite のBVALID がアサートされ、ディアサートされた後から、今回のWrite のAWVALID がアサートされるまでの時間は、500.001 ns だった。正しく delay が効いているようだ。

Write の delay を 500 から 0 にしたときをもう一度、確かめてみよう。
DPI_examples_38_170816.png

前のWrite のBVALID がアサートされ、ディアサートされた後から、今回のWrite のAWVALID がアサートされるまでの時間は、20.001 ns だった。

Zynq VIP のレジスタWrite は完全にBVALID 、BRADY がアサートされたら終了なのかもしれない?複数のトランザクションを重ねることはできるのだろうか?
  1. 2017年08月16日 04:45 |
  2. シミュレーション
  3. | トラックバック:0
  4. | コメント:0

Vivado シミュレータでDPI-C を使用してZynq VIPを使う2

Vivado シミュレータでDPI-C を使用してZynq VIPを使う1”の続き。

前回は、Vivado 2017.2 で Base Zynq サンプル・プロジェクトを作成して、一度シミュレーションを実行し、テストベンチをSystemVerilog ファイルに変更し、シミュレーション用のディレクトリにDPI-C を実行するC ファイルを追加した。今回は、コンパイル、エラボレートを行う。

~/Vivado/zynq_base_ex_172/zynq_base_ex_172.sim/sim_1/behav には、compile.sh ができていた。
DPI_examples_14_170813.png

compile.sh を zynq_dpi.c をコンパイルするように変更する。
DPI_examples_17_170813.png

最後に xsc zynq_dpi.c を追加した。これで、zynq_dpi.c をコンパイルする。
次に、tb_vlog.prj にコンパイルするファイルやオプションが書いてあるので、zynq_tb.sv をコンパイルするように書き換えた。
DPI_examples_18_170813.png

./compile.sh を実行してコンパイルを行った。
DPI_examples_19_170813.png
DPI_examples_20_170813.png

コンパイルのログを貼っておく。

masaaki@masaaki-VirtualBox2:~/Vivado/zynq_base_ex_172/zynq_base_ex_172.sim/sim_1/behav$ ./compile.sh
xvlog -m64 --relax -L smartconnect_v1_0 -L axi_protocol_checker_v1_1_14 -L xil_common_vip_v1_0_0 -L axi_vip_v1_0_2 -L axi_vip_v1_0_1 -prj tb_vlog.prj
INFO: [VRFC 10-2263] Analyzing Verilog file "/home/masaaki/Vivado/zynq_base_ex_172/zynq_base_ex_172.ip_user_files/bd/base_zynq/ip/base_zynq_processing_system7_0_0/sim/base_zynq_processing_system7_0_0.v" into library xil_defaultlib
INFO: [VRFC 10-311] analyzing module base_zynq_processing_system7_0_0
INFO: [VRFC 10-2263] Analyzing Verilog file "/home/masaaki/Vivado/zynq_base_ex_172/zynq_base_ex_172.ip_user_files/bd/base_zynq/ip/base_zynq_blk_mem_gen_0_0/sim/base_zynq_blk_mem_gen_0_0.v" into library xil_defaultlib
INFO: [VRFC 10-311] analyzing module base_zynq_blk_mem_gen_0_0
INFO: [VRFC 10-2263] Analyzing Verilog file "/home/masaaki/Vivado/zynq_base_ex_172/zynq_base_ex_172.ip_user_files/bd/base_zynq/ip/base_zynq_xbar_0/sim/base_zynq_xbar_0.v" into library xil_defaultlib
INFO: [VRFC 10-311] analyzing module base_zynq_xbar_0
INFO: [VRFC 10-2263] Analyzing Verilog file "/home/masaaki/Vivado/zynq_base_ex_172/zynq_base_ex_172.ip_user_files/bd/base_zynq/ip/base_zynq_auto_pc_0/sim/base_zynq_auto_pc_0.v" into library xil_defaultlib
INFO: [VRFC 10-311] analyzing module base_zynq_auto_pc_0
INFO: [VRFC 10-2263] Analyzing Verilog file "/home/masaaki/Vivado/zynq_base_ex_172/zynq_base_ex_172.ip_user_files/bd/base_zynq/ip/base_zynq_auto_pc_1/sim/base_zynq_auto_pc_1.v" into library xil_defaultlib
INFO: [VRFC 10-311] analyzing module base_zynq_auto_pc_1
INFO: [VRFC 10-2263] Analyzing SystemVerilog file "/home/masaaki/Vivado/zynq_base_ex_172/zynq_base_ex_172.srcs/sim_1/imports/base_zynq/zynq_tb.sv" into library xil_defaultlib
INFO: [VRFC 10-311] analyzing module tb
INFO: [VRFC 10-2263] Analyzing Verilog file "/home/masaaki/Vivado/zynq_base_ex_172/zynq_base_ex_172.sim/sim_1/behav/glbl.v" into library xil_defaultlib
INFO: [VRFC 10-311] analyzing module glbl
xvhdl -m64 --relax -prj tb_vhdl.prj
INFO: [VRFC 10-163] Analyzing VHDL file "/home/masaaki/Vivado/zynq_base_ex_172/zynq_base_ex_172.ip_user_files/bd/base_zynq/ip/base_zynq_axi_gpio_0_0/sim/base_zynq_axi_gpio_0_0.vhd" into library xil_defaultlib
INFO: [VRFC 10-307] analyzing entity base_zynq_axi_gpio_0_0
INFO: [VRFC 10-163] Analyzing VHDL file "/home/masaaki/Vivado/zynq_base_ex_172/zynq_base_ex_172.ip_user_files/bd/base_zynq/ip/base_zynq_axi_bram_ctrl_0_0/sim/base_zynq_axi_bram_ctrl_0_0.vhd" into library xil_defaultlib
INFO: [VRFC 10-307] analyzing entity base_zynq_axi_bram_ctrl_0_0
INFO: [VRFC 10-163] Analyzing VHDL file "/home/masaaki/Vivado/zynq_base_ex_172/zynq_base_ex_172.ip_user_files/bd/base_zynq/ip/base_zynq_rst_ps7_0_50M_0/sim/base_zynq_rst_ps7_0_50M_0.vhd" into library xil_defaultlib
INFO: [VRFC 10-307] analyzing entity base_zynq_rst_ps7_0_50M_0
INFO: [VRFC 10-163] Analyzing VHDL file "/home/masaaki/Vivado/zynq_base_ex_172/zynq_base_ex_172.ip_user_files/bd/base_zynq/hdl/base_zynq.vhd" into library xil_defaultlib
INFO: [VRFC 10-307] analyzing entity m00_couplers_imp_QHT96L
INFO: [VRFC 10-307] analyzing entity m01_couplers_imp_11WP2HX
INFO: [VRFC 10-307] analyzing entity s00_couplers_imp_1JB4A1T
INFO: [VRFC 10-307] analyzing entity base_zynq_ps7_0_axi_periph_0
INFO: [VRFC 10-307] analyzing entity base_zynq
INFO: [VRFC 10-163] Analyzing VHDL file "/home/masaaki/Vivado/zynq_base_ex_172/zynq_base_ex_172.srcs/sources_1/bd/base_zynq/hdl/base_zynq_wrapper.vhd" into library xil_defaultlib
INFO: [VRFC 10-307] analyzing entity base_zynq_wrapper
Running compilation flow
Done compilation
Done linking: "/home/masaaki/Vivado/zynq_base_ex_172/zynq_base_ex_172.sim/sim_1/behav/xsim.dir/xsc/dpi.so"
masaaki@masaaki-VirtualBox2:~/Vivado/zynq_base_ex_172/zynq_base_ex_172.sim/sim_1/behav$


~/Vivado/zynq_base_ex_172/zynq_base_ex_172.sim/sim_1/behav/xsim.dir/xsc にdpi.so と zynq_dpi.lnx64.o ができていた。
DPI_examples_21_170813.png

~/Vivado/zynq_base_ex_172/zynq_base_ex_172.sim/sim_1/behav ディレクトリを示す。
DPI_examples_22_170813.png

さて、次にエラボレートを行う。
elaborate.sh を開いて、-sv_lib dpi を追加した。
DPI_examples_23_170813.png

./elaborate.sh を実行した。
DPI_examples_24_170813.png
DPI_examples_25_170813.png

エラボレートのログを貼っておく。ただし、Xilinx 社のIPのワーニングは長すぎるので削除した。

masaaki@masaaki-VirtualBox2:~/Vivado/zynq_base_ex_172/zynq_base_ex_172.sim/sim_1/behav$ ./elaborate.sh
Vivado Simulator 2017.2
Copyright 1986-1999, 2001-2016 Xilinx, Inc. All Rights Reserved.
Running: /opt/Xilinx/Vivado/2017.2/bin/unwrapped/lnx64.o/xelab -wto 429c07435a554e888bf42dfaf10910cc --debug typical --relax --mt 8 -L axi_infrastructure_v1_1_0 -L xil_common_vip_v1_0_0 -L smartconnect_v1_0 -L axi_protocol_checker_v1_1_14 -L axi_vip_v1_0_2 -L axi_vip_v1_0_1 -L xil_defaultlib -L axi_lite_ipif_v3_0_4 -L lib_cdc_v1_0_2 -L interrupt_control_v3_1_4 -L axi_gpio_v2_0_15 -L blk_mem_gen_v8_3_6 -L axi_bram_ctrl_v4_0_11 -L proc_sys_reset_v5_0_11 -L generic_baseblocks_v2_1_0 -L axi_register_slice_v2_1_13 -L fifo_generator_v13_1_4 -L axi_data_fifo_v2_1_12 -L axi_crossbar_v2_1_14 -L axi_protocol_converter_v2_1_13 -L unisims_ver -L unimacro_ver -L secureip -L xpm --snapshot tb_behav xil_defaultlib.tb xil_defaultlib.glbl -log elaborate.log -cc gcc -sv_lib dpi
Using 8 slave threads.
Starting static elaboration

Starting simulation data flow analysis
Completed simulation data flow analysis
Time Resolution for simulation is 1ps
WARNING: [XSIM 43-3447] Restricting number of parallel compilation jobs to 4 to avoid system resource limitations.
Compiling package std.standard
Compiling package std.textio
Compiling package ieee.std_logic_1164
Compiling package unisim.vcomponents
Compiling package ieee.numeric_std
Compiling package ieee.std_logic_arith
Compiling package axi_bram_ctrl_v4_0_11.axi_bram_ctrl_funcs
Compiling package ieee.vital_timing
Compiling package ieee.vital_primitives
Compiling package unisim.vpkg
Compiling package ieee.std_logic_unsigned
Compiling package synopsys.attributes
Compiling package ieee.std_logic_misc
Compiling package axi_lite_ipif_v3_0_4.ipif_pkg
Compiling architecture implementation of entity axi_bram_ctrl_v4_0_11.sng_port_arb [\sng_port_arb(c_s_axi_addr_width...]
Compiling architecture implementation of entity axi_bram_ctrl_v4_0_11.wrap_brst [\wrap_brst(c_axi_addr_width=13,c...]
Compiling architecture muxcy_v of entity unisim.MUXCY [muxcy_default]
Compiling architecture muxcy_l_v of entity unisim.MUXCY_L [muxcy_l_default]
Compiling architecture xorcy_v of entity unisim.XORCY [xorcy_default]
Compiling architecture srl16e_v of entity unisim.SRL16E [\SRL16E(0,15)\]
Compiling architecture fdre_v of entity unisim.FDRE [fdre_default]
Compiling architecture fdr_v of entity unisim.FDR [fdr_default]
Compiling architecture imp of entity axi_bram_ctrl_v4_0_11.SRL_FIFO [\SRL_FIFO(c_data_bits=12,c_depth...]
Compiling architecture implementation of entity axi_bram_ctrl_v4_0_11.wr_chnl [\wr_chnl(c_axi_addr_width=13,c_a...]
Compiling architecture implementation of entity axi_bram_ctrl_v4_0_11.rd_chnl [\rd_chnl(c_axi_addr_width=13,c_a...]
Compiling architecture implementation of entity axi_bram_ctrl_v4_0_11.full_axi [\full_axi(c_s_axi_addr_width=13,...]
Compiling architecture implementation of entity axi_bram_ctrl_v4_0_11.axi_bram_ctrl_top [\axi_bram_ctrl_top(c_bram_addr_w...]
Compiling architecture implementation of entity axi_bram_ctrl_v4_0_11.axi_bram_ctrl [\axi_bram_ctrl(c_memory_depth=20...]
Compiling architecture base_zynq_axi_bram_ctrl_0_0_arch of entity xil_defaultlib.base_zynq_axi_bram_ctrl_0_0 [base_zynq_axi_bram_ctrl_0_0_defa...]
Compiling architecture imp of entity axi_lite_ipif_v3_0_4.pselect_f [\pselect_f(c_ab=2,c_aw=2,c_bar="...]
Compiling architecture imp of entity axi_lite_ipif_v3_0_4.pselect_f [\pselect_f(c_ab=2,c_aw=2,c_bar="...]
Compiling architecture imp of entity axi_lite_ipif_v3_0_4.pselect_f [\pselect_f(c_ab=2,c_aw=2,c_bar="...]
Compiling architecture imp of entity axi_lite_ipif_v3_0_4.pselect_f [\pselect_f(c_ab=2,c_aw=2,c_bar="...]
Compiling architecture imp of entity axi_lite_ipif_v3_0_4.address_decoder [\address_decoder(c_bus_awidth=9,...]
Compiling architecture imp of entity axi_lite_ipif_v3_0_4.slave_attachment [\slave_attachment(c_ard_addr_ran...]
Compiling architecture imp of entity axi_lite_ipif_v3_0_4.axi_lite_ipif [\axi_lite_ipif(c_s_axi_addr_widt...]
Compiling architecture implementation of entity lib_cdc_v1_0_2.cdc_sync [\cdc_sync(c_single_bit=0,c_vecto...]
Compiling architecture imp of entity axi_gpio_v2_0_15.GPIO_Core [\GPIO_Core(c_aw=9,c_gpio_width=4...]
Compiling architecture imp of entity axi_gpio_v2_0_15.axi_gpio [\axi_gpio(c_family="zynq",c_gpio...]
Compiling architecture base_zynq_axi_gpio_0_0_arch of entity xil_defaultlib.base_zynq_axi_gpio_0_0 [base_zynq_axi_gpio_0_0_default]
Compiling module blk_mem_gen_v8_3_6.blk_mem_gen_v8_3_6_output_stage(...
Compiling module blk_mem_gen_v8_3_6.blk_mem_gen_v8_3_6_output_stage(...
Compiling module blk_mem_gen_v8_3_6.blk_mem_gen_v8_3_6_softecc_outpu...
Compiling module blk_mem_gen_v8_3_6.blk_mem_gen_v8_3_6_mem_module(C_...
Compiling module blk_mem_gen_v8_3_6.blk_mem_gen_v8_3_6(C_FAMILY="zyn...
Compiling module xil_defaultlib.base_zynq_blk_mem_gen_0_0
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_ge...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_ge...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_ar...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_ar...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_fm...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_ar...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_ar...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_ar...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_ar...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_ss...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_in...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_sp...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_dd...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_oc...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_oc...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_re...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_re...
Compiling module axi_vip_v1_0_2.axi_vip_v1_0_2_if(C_AXI_PROTOCOL...
Compiling module smartconnect_v1_0.sc_util_v1_0_2_onehot_to_binary(...
Compiling module smartconnect_v1_0.sc_util_v1_0_2_srl_rtl(C_A_WIDTH...
Compiling module smartconnect_v1_0.sc_util_v1_0_2_axic_reg_srl_fifo...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_thr...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_syn...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_axi...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_syn...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_syn...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_cor...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_rep...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_top...
Compiling module axi_vip_v1_0_2.axi_vip_v1_0_2_top(C_AXI_PROTOCO...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_ax...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_ax...
Compiling module axi_vip_v1_0_2.axi_vip_v1_0_2_if(C_AXI_PROTOCOL...
Compiling module smartconnect_v1_0.sc_util_v1_0_2_onehot_to_binary(...
Compiling module smartconnect_v1_0.sc_util_v1_0_2_srl_rtl(C_A_WIDTH...
Compiling module smartconnect_v1_0.sc_util_v1_0_2_axic_reg_srl_fifo...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_thr...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_axi...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_syn...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_cor...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_rep...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_top...
Compiling module axi_vip_v1_0_2.axi_vip_v1_0_2_top(C_AXI_PROTOCO...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_ax...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_ax...
Compiling module axi_vip_v1_0_2.axi_vip_v1_0_2_if(C_AXI_PROTOCOL...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_axi...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_syn...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_cor...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_rep...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_top...
Compiling module axi_vip_v1_0_2.axi_vip_v1_0_2_top(C_AXI_PROTOCO...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_in...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_in...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_af...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_in...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_af...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_in...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_af...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_in...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_af...
Compiling module axi_vip_v1_0_2.axi_vip_v1_0_2_if(C_AXI_PROTOCOL...
Compiling module smartconnect_v1_0.sc_util_v1_0_2_onehot_to_binary(...
Compiling module smartconnect_v1_0.sc_util_v1_0_2_srl_rtl(C_A_WIDTH...
Compiling module smartconnect_v1_0.sc_util_v1_0_2_axic_reg_srl_fifo...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_thr...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_axi...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_cor...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_rep...
Compiling module axi_protocol_checker_v1_1_14.axi_protocol_checker_v1_1_14_top...
Compiling module axi_vip_v1_0_2.axi_vip_v1_0_2_top(C_AXI_PROTOCO...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1_ax...
Compiling module axi_vip_v1_0_1.processing_system7_vip_v1_0_1(C_...
Compiling module xil_defaultlib.base_zynq_processing_system7_0_0
Compiling module axi_infrastructure_v1_1_0.axi_infrastructure_v1_1_0_axi2ve...
Compiling module axi_register_slice_v2_1_13.axi_register_slice_v2_1_13_axic_...
Compiling module axi_register_slice_v2_1_13.axi_register_slice_v2_1_13_axic_...
Compiling module axi_register_slice_v2_1_13.axi_register_slice_v2_1_13_axic_...
Compiling module axi_register_slice_v2_1_13.axi_register_slice_v2_1_13_axic_...
Compiling module axi_infrastructure_v1_1_0.axi_infrastructure_v1_1_0_vector...
Compiling module axi_register_slice_v2_1_13.axi_register_slice_v2_1_13_axi_r...
Compiling module axi_protocol_converter_v2_1_13.axi_protocol_converter_v2_1_13_b...
Compiling module axi_protocol_converter_v2_1_13.axi_protocol_converter_v2_1_13_b...
Compiling module axi_protocol_converter_v2_1_13.axi_protocol_converter_v2_1_13_b...
Compiling module axi_protocol_converter_v2_1_13.axi_protocol_converter_v2_1_13_b...
Compiling module axi_protocol_converter_v2_1_13.axi_protocol_converter_v2_1_13_b...
Compiling module axi_protocol_converter_v2_1_13.axi_protocol_converter_v2_1_13_b...
Compiling module axi_protocol_converter_v2_1_13.axi_protocol_converter_v2_1_13_b...
Compiling module axi_protocol_converter_v2_1_13.axi_protocol_converter_v2_1_13_b...
Compiling module axi_protocol_converter_v2_1_13.axi_protocol_converter_v2_1_13_b...
Compiling module axi_protocol_converter_v2_1_13.axi_protocol_converter_v2_1_13_b...
Compiling module axi_protocol_converter_v2_1_13.axi_protocol_converter_v2_1_13_b...
Compiling module axi_protocol_converter_v2_1_13.axi_protocol_converter_v2_1_13_b...
Compiling module axi_protocol_converter_v2_1_13.axi_protocol_converter_v2_1_13_b...
Compiling module axi_infrastructure_v1_1_0.axi_infrastructure_v1_1_0_axi2ve...
Compiling module axi_register_slice_v2_1_13.axi_register_slice_v2_1_13_axic_...
Compiling module axi_register_slice_v2_1_13.axi_register_slice_v2_1_13_axic_...
Compiling module axi_register_slice_v2_1_13.axi_register_slice_v2_1_13_axic_...
Compiling module axi_register_slice_v2_1_13.axi_register_slice_v2_1_13_axic_...
Compiling module axi_infrastructure_v1_1_0.axi_infrastructure_v1_1_0_vector...
Compiling module axi_register_slice_v2_1_13.axi_register_slice_v2_1_13_axi_r...
Compiling module axi_protocol_converter_v2_1_13.axi_protocol_converter_v2_1_13_b...
Compiling module axi_protocol_converter_v2_1_13.axi_protocol_converter_v2_1_13_a...
Compiling module xil_defaultlib.base_zynq_auto_pc_0
Compiling architecture structure of entity xil_defaultlib.m00_couplers_imp_QHT96L [m00_couplers_imp_qht96l_default]
Compiling architecture structure of entity xil_defaultlib.m01_couplers_imp_11WP2HX [m01_couplers_imp_11wp2hx_default]
Compiling module axi_protocol_converter_v2_1_13.axi_protocol_converter_v2_1_13_a...
Compiling module xil_defaultlib.base_zynq_auto_pc_1
Compiling architecture structure of entity xil_defaultlib.s00_couplers_imp_1JB4A1T [s00_couplers_imp_1jb4a1t_default]
Compiling module generic_baseblocks_v2_1_0.generic_baseblocks_v2_1_0_carry_...
Compiling module generic_baseblocks_v2_1_0.generic_baseblocks_v2_1_0_compar...
Compiling module generic_baseblocks_v2_1_0.generic_baseblocks_v2_1_0_compar...
Compiling module axi_crossbar_v2_1_14.axi_crossbar_v2_1_14_addr_decode...
Compiling module generic_baseblocks_v2_1_0.generic_baseblocks_v2_1_0_mux_en...
Compiling module unisims_ver.SRLC32E_default_1
Compiling module axi_data_fifo_v2_1_12.axi_data_fifo_v2_1_12_ndeep_srl(...
Compiling module axi_data_fifo_v2_1_12.axi_data_fifo_v2_1_12_axic_srl_f...
Compiling module axi_crossbar_v2_1_14.axi_crossbar_v2_1_14_si_transact...
Compiling module generic_baseblocks_v2_1_0.generic_baseblocks_v2_1_0_mux_en...
Compiling module axi_crossbar_v2_1_14.axi_crossbar_v2_1_14_si_transact...
Compiling module axi_crossbar_v2_1_14.axi_crossbar_v2_1_14_splitter
Compiling module unisims_ver.SRLC32E_default
Compiling module axi_data_fifo_v2_1_12.axi_data_fifo_v2_1_12_ndeep_srl(...
Compiling module axi_data_fifo_v2_1_12.axi_data_fifo_v2_1_12_axic_reg_s...
Compiling module axi_crossbar_v2_1_14.axi_crossbar_v2_1_14_wdata_route...
Compiling module axi_crossbar_v2_1_14.axi_crossbar_v2_1_14_wdata_mux(C...
Compiling module axi_data_fifo_v2_1_12.axi_data_fifo_v2_1_12_axic_srl_f...
Compiling module axi_infrastructure_v1_1_0.axi_infrastructure_v1_1_0_axi2ve...
Compiling module axi_register_slice_v2_1_13.axi_register_slice_v2_1_13_axic_...
Compiling module axi_register_slice_v2_1_13.axi_register_slice_v2_1_13_axic_...
Compiling module axi_register_slice_v2_1_13.axi_register_slice_v2_1_13_axic_...
Compiling module axi_register_slice_v2_1_13.axi_register_slice_v2_1_13_axic_...
Compiling module axi_infrastructure_v1_1_0.axi_infrastructure_v1_1_0_vector...
Compiling module axi_register_slice_v2_1_13.axi_register_slice_v2_1_13_axi_r...
Compiling module axi_crossbar_v2_1_14.axi_crossbar_v2_1_14_wdata_mux(C...
Compiling module axi_data_fifo_v2_1_12.axi_data_fifo_v2_1_12_ndeep_srl(...
Compiling module axi_data_fifo_v2_1_12.axi_data_fifo_v2_1_12_axic_srl_f...
Compiling module axi_crossbar_v2_1_14.axi_crossbar_v2_1_14_addr_arbite...
Compiling module axi_crossbar_v2_1_14.axi_crossbar_v2_1_14_decerr_slav...
Compiling module axi_crossbar_v2_1_14.axi_crossbar_v2_1_14_crossbar(C_...
Compiling module axi_crossbar_v2_1_14.axi_crossbar_v2_1_14_axi_crossba...
Compiling module xil_defaultlib.base_zynq_xbar_0
Compiling architecture structure of entity xil_defaultlib.base_zynq_ps7_0_axi_periph_0 [base_zynq_ps7_0_axi_periph_0_def...]
Compiling architecture implementation of entity lib_cdc_v1_0_2.cdc_sync [\cdc_sync(c_vector_width=2,c_mtb...]
Compiling architecture srl16e_v of entity unisim.SRL16E [\SRL16E(init="1111111111111111")...]
Compiling architecture srl16_v of entity unisim.SRL16 [\SRL16(init="1111111111111111")(...]
Compiling architecture imp of entity proc_sys_reset_v5_0_11.lpf [\lpf(c_ext_rst_width=4,c_aux_rst...]
Compiling architecture imp of entity proc_sys_reset_v5_0_11.upcnt_n [\upcnt_n(c_size=6)\]
Compiling architecture imp of entity proc_sys_reset_v5_0_11.sequence_psr [sequence_psr_default]
Compiling architecture imp of entity proc_sys_reset_v5_0_11.proc_sys_reset [\proc_sys_reset(c_family="zynq",...]
Compiling architecture base_zynq_rst_ps7_0_50m_0_arch of entity xil_defaultlib.base_zynq_rst_ps7_0_50M_0 [base_zynq_rst_ps7_0_50m_0_defaul...]
Compiling architecture structure of entity xil_defaultlib.base_zynq [base_zynq_default]
Compiling architecture structure of entity xil_defaultlib.base_zynq_wrapper [base_zynq_wrapper_default]
Compiling module xil_defaultlib.tb
Compiling module xil_defaultlib.glbl
Compiling package axi_vip_v1_0_2.axi_vip_v1_0_2_pkg
Compiling package xil_common_vip_v1_0_0.xil_common_vip_v1_0_0_pkg
Compiling package std.std
Compiling package smartconnect_v1_0.sc_util_v1_0_2_pkg
Waiting for 4 sub-compilation(s) to finish...
0 sub-compilation(s) remaining...
Built simulation snapshot tb_behav
masaaki@masaaki-VirtualBox2:~/Vivado/zynq_base_ex_172/zynq_base_ex_172.sim/sim_1/behav$


Vivado シミュレータでDPI-C を使用してZynq VIPを使う3”に続く。
  1. 2017年08月15日 06:00 |
  2. シミュレーション
  3. | トラックバック:0
  4. | コメント:0

Vivado シミュレータでDPI-C を使用してZynq VIPを使う1

Vivado シミュレータのDPI-C その1”と”Vivado シミュレータのDPI-C その2”でVivado シミュレータでDPI-C を実行する方法をXilinx者のサンプルで見てきた。
それでは、Zynq VIP を使用するときにDPI-C を使用することができるかどうか?をやってみた。

今回使用するのは、”Vivado 2017.1 の新機能8(Zynq-7000 VIP)”で使用したBase Zynq サンプル・プロジェクトだ。

最初に使用したのはVirtualBox 上のUbuntu 16.04 にインストールしたVivado 2017.2 だ。
さて、Vivado 2017.2 でサンプル・プロジェクトをオープンして、Templates からBase Zynq を選択して、プロジェクトを生成する。
DPI_examples_12_170813.png

一度、Flow Navigator からSIMULATION -> Run Simulation -> Run Behavioral Simulation を選択して、論理シミュレーションを行っておく。
DPI_examples_13_170813.png

その時に、Scope の tb -> zynq_sys -> base_zynq_i を右クリックし、Add to Wave Window を選択して、wave window にAXI バスの信号線を追加しておこう。そして、wave window の tb_behav.wcfg をセーブしておく。

~/Vivado/zynq_base_ex_172/zynq_base_ex_172.sim/sim_1/behav を見た。
DPI_examples_14_170813.png

シミュレーション用のファイルがいろいろと生成されていた。
ここに zynq_dpi.c を追加した。
DPI_examples_15_170813.png

zynq_dpi.c を示す。

// zynq_dpi.c
// 2017/08/12 by marsee
//

#include "svdpi.h"

#define AXI_TRANS_CS_LIMIT 10
#define READ_STATE    1

const struct axi_trans_scenario {
    int r_w;
    int delay;
    int addr;
    int trans_bytes;
    int    data;
} axi_trans_sc[AXI_TRANS_CS_LIMIT] =
    {{000x4120000040xFFFFFFFF},
    {000x4000000040xDEADBEEF},
    {100x4000000040}, {00000}, {00000}, {00000}, 
    {00000}, {00000}, {00000}, {00000}};

static int i=0;
                
int write_axit(int * const delay, int * const addr, 
    int * const trans_bytes, int * const data){
    int r_w;
    
    r_w = axi_trans_sc[i].r_w;
    *delay = axi_trans_sc[i].delay;
    *addr = axi_trans_sc[i].addr;
    *trans_bytes = axi_trans_sc[i].trans_bytes;
    *data = axi_trans_sc[i].data;
    
    if(axi_trans_sc[i].trans_bytes != 0 && i<AXI_TRANS_CS_LIMIT){
        if(r_w == 0){
            i++;
            return(0);
        }else
            return(1);
    }else
        return(2);
}

int read_axit(int * const delay, int * const addr, 
    int * const trans_bytes){
    int r_w;
    
    r_w = axi_trans_sc[i].r_w;
    *delay = axi_trans_sc[i].delay;
    *addr = axi_trans_sc[i].addr;
    *trans_bytes = axi_trans_sc[i].trans_bytes;
    
    if(axi_trans_sc[i].trans_bytes != 0 && i<AXI_TRANS_CS_LIMIT){
        if(r_w == 1){
            i++;
            return(0);
        }else
            return(1);
    }else
        return(2);
}


ソースコードを見てお分かりの様に、zynq_dpi.c はアドレスや書き込みデータをSV テストベンチに渡す。

次に、~/Vivado/zynq_base_ex_172/zynq_base_ex_172.srcs/sim_1/imports/base_zynq ディレクトリに行くと、zynq_tb.v がある。それをコピー&ペーストして、zynq_tb_sv に名前を変更した。
zynq_tb_sv にコードを追加した。なお、zynq_tb_v はXilinx 社のコードなので、一部を貼っておくだけとする。
まずはwire や reg の宣言部分にDPI-C の宣言を記述して、DPI-C で使用する変数を宣言した。
DPI_examples_35_170813.png

    integer delay, trans_bytes, addr;
    integer    data;
    
    integer i;
    
    import "DPI-C" function int write_axit(
        output int delay,
        output int addr,
        output int trans_bytes,
        output int data);

    import "DPI-C" function int read_axit(
        output int delay,
        output int addr,
        output int trans_bytes);


write_axit() と read_axit() を使用するようにSystemVerilog ファイルを変更した。task も使用していないが実証コードということで。。。
DPI_examples_36_170813.png

        //This drives the LEDs on the GPIO output
        if(write_axit(delay, addr, trans_bytes, data) == 0) begin
            for(i=0; i<delay; i++) begin
                #1;
            end
            tb.zynq_sys.base_zynq_i.processing_system7_0.inst.write_data(addr,trans_bytes, data, resp);
        end
        $display ("LEDs are toggled, observe the waveform");
        
        //Write into the BRAM through GP0 and read back
        if(write_axit(delay, addr, trans_bytes, data) == 0) begin
            for(i=0; i<delay; i++) begin
                #1;
            end
            tb.zynq_sys.base_zynq_i.processing_system7_0.inst.write_data(addr,trans_bytes, data, resp);
        end

        if(read_axit(delay, addr, trans_bytes) == 0) begin
            for(i=0; i<delay; i++) begin
                #1;
            end
            tb.zynq_sys.base_zynq_i.processing_system7_0.inst.read_data(addr, trans_bytes, read_data, resp);
        end


Vivado シミュレータでDPI-C を使用してZynq VIPを使う2”に続く。
  1. 2017年08月14日 04:48 |
  2. シミュレーション
  3. | トラックバック:0
  4. | コメント:0

Vivado シミュレータのDPI-C その2

Vivado シミュレータのDPI-C その1”の続き。

前回は、DPI のexample の simple_import をやってみた。今回は、simple_export をやってみよう。

今回も、aster_ismの工作室さんの”Vivado SimulatorによるDPI-Cシミュレーション”を参考にさせて頂く。

VirtualBox 上のUbuntu 16.04 の /opt/Xilinx/Vivado/2016.4/examples/xsim/systemverilog/dpi/simple_export ディレクトリがある。
DPI_examples_1_170809.png

やはり、README と file.sv, function.c, run.csh があった。
README を引用する。

Steps
-----
1. Run the setup for Xilinx executables.
2. Check if the executables "xsc" and "xelab" are in your PATH.
3. Invoke run.csh

This example shows a simple DPI-C export usage. The System Verilog code (file.sv)
calls a function "cFunc" defined in function.c that in turn calls a function "svFunc" which is
defined on the SV side in the file file.sv.
1. First the xvlog/xelab combination is run to generate the header dpi.h that is included
in the function.c
2. Then the C code is compiled using xsc to create a dll in directory xsim.dir/xsc/dpi.so.
3. This dll is then linked into when using "xelab" to compile the file.sv

The return value is checked by the System Verilog code triggering a "PASSED" output for a valid run.


function.c を引用する。


#include "dpi.h"

int cFunc(int x)
{
  return svFunc(x) ;
}

// XSIP watermark, do not delete 67d7842dbbe25473c3c32b93c0da8047785f30d78e8a024de1b57352245f9689


file.sv を引用する。


module TOP();

  export "DPI-C" function svFunc ; 

  int svValue ;

  function int svFunc(input int x) ;
    svValue = x + 1 ;
    return svValue + 3 ;
  endfunction

  import "DPI-C" function int cFunc(input int x) ;

  int result ;
  
  initial
  begin
    svValue = 15 ;
    result = cFunc(3) ;
    if (svValue != 4)
    begin
      $display("FAILED") ;
      $finish ;
    end
    if (result == 7)
      $display("PASSED") ;
    else
      $display("FAILED") ;
  end

endmodule


前回の simple_import では、C の関数を呼び出して、その値を使用するだけだったのだが、simple_export では、呼び出したC の関数からSystemVerilog の関数を呼び出している。

run.csh を引用する。

#!/bin/csh -xvf
xvlog -sv file.sv
xelab TOP -dpiheader dpi.h
xsc function.c
xelab TOP -sv_lib dpi -R


Ubuntu 16.04 上で、/opt/Xilinx/Vivado/2016.4/examples/xsim/systemverilog/dpi/simple_export ディレクトリを ~/DPI_examples ディレクトリにコピー&ペーストして、そのディレクトリの中の./run.csh を起動した。
DPI_examples_3_170809.png
DPI_examples_4_170809.png
DPI_examples_5_170809.png

PASSED が表示されたので成功だ。

~/DPI_examples/simple_export ディレクトリには、やはり、いろいろなファイルが生成されている。
DPI_examples_2_170809.png
  1. 2017年08月11日 05:21 |
  2. シミュレーション
  3. | トラックバック:0
  4. | コメント:0

Vivado シミュレータのDPI-C その1

Vivado シミュレータでDPI (Direct Programming Interface)をやってみることにした。

参考にするのは、aster_ismの工作室さんの”Vivado SimulatorによるDPI-Cシミュレーション”だ。
Vivado SimulatorによるDPI-Cシミュレーション”によるとVivado シミュレータのDPI のサンプルが /opt/Xilinx/Vivado/バージョン番号/examples/xsim/systemverilog/dpi/ にあるそうだ。

VirtualBox 上のUbuntu 16.04 の /opt/Xilinx/Vivado/2016.4/examples/xsim/systemverilog/dpi/ に行ってみると、simple_import と simple_export の2つのディレクトリがあった。
DPI_examples_11_170809.png

そのうちの simple_import ディレクトリの中に入ってみた。
DPI_examples_6_170809.png

README と file.sv, function.c, run.csh があった。
README を引用する。

Steps
-----
1. Run the setup for Xilinx executables.
2. Check if the executables "xsc" and "xelab" are in your PATH.
3. Invoke run.csh

This example shows a simple DPI-C import usage. The System Verilog code (file.sv)
calls a function "myFunction" that is defined on the C side in the file function.c.
The C code is compiled using xsc to create a dll in directory xsim.dir/xsc/dpi.so.
This dll is then linked into when using "xelab" to compile the file.sv
You could use your own compiler (gcc) for compiling and creating a dll.
myFunction() call into the C code returns an C integer value of 5 which is then checked
by the System Verilog code triggering a "PASSED" output for a valid run.


function.c を引用する。


#include "svdpi.h"

DPI_DLLESPEC
int myFunction()
{
    return 5;
}


// XSIP watermark, do not delete 67d7842dbbe25473c3c32b93c0da8047785f30d78e8a024de1b57352245f9689


file.sv を引用する。


module m();

import "DPI-C" pure function int myFunction ();

int i;

initial
begin
#1;
  i = myFunction();
  if( i == 5)
    $display("PASSED");
  else
    $display("FAILED");
  $finish();
end


endmodule


最後に run.csh を引用する。

#!/bin/csh -xvf
xsc function.c
xvlog -svlog file.sv
xelab work.m -sv_lib dpi -R


run.csh のコマンドについては、”Vivado Design Suite ユーザー ガイド ロジック シ ミ ュレーシ ョ ン UG900 (v2017.1) 2017 年 4 月 5 日”の 171 ページの”付録 D Vivado シミュレータのダイレクト プログラミング インターフェイス (DPI)”に書いてある。
そこから引用する。

xsc コ ンパイ ラ を使用する と、 1 つまたは複数の C フ ァ イルから共有ラ イブラ リ (Windows の場合は .a、 Linux の場合は .so) を作成でき ます。


xvlog はSystemVerilog を解析するパーサーのようだ。
xelab はシミュレータ・コンパイラで、HDL モデルがスナップショットにコンパイルされるそうだ。

さて、Ubuntu 16.04 上で、/opt/Xilinx/Vivado/2016.4/examples/xsim/systemverilog/dpi/simple_import ディレクトリを ~/DPI_examples ディレクトリにコピー&ペーストして、そのディレクトリの中の./run.csh を起動してみた。
最初に csh がインストールされていなかったので、sudo apt-get install csh でインストールした。
DPI_examples_8_170809.png
DPI_examples_9_170809.png
DPI_examples_10_170809.png

PASSED が表示された。成功だ。

なお、 ~/DPI_examples/simple_import ディレクトリはいろいろなファイルが生成されている。
DPI_examples_7_170809.png
  1. 2017年08月10日 04:33 |
  2. シミュレーション
  3. | トラックバック:0
  4. | コメント:0

映画『ジョジョの奇妙な冒険 ダイヤモンドは砕けない 第一章』を見てました

今日は8月11日に大学説明会で出勤するので、振替休日だった。なので、映画『ジョジョの奇妙な冒険 ダイヤモンドは砕けない 第一章』(音注意)を見てきた。
少し怖かったが(ジョジョの奇妙な冒険は漫画でも怖かったので、よく読んでいない)面白かった。
  1. 2017年08月09日 17:18 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0

白線追従走行用畳み込みニューラルネットワークの製作7(学習2)

白線追従走行用畳み込みニューラルネットワークの製作6(学習1)”の続き。

前回は、白線追従走行の直線走行用のトレーニング・データとテスト・データを用意し、それらのデータセットを使用するためのPython コードのstraight_dataset.py を用意した。今回は、浮動小数点数を使用して畳み込みニューラルネットワーク(CNN)をトレーニングするためにPython コードを修正する。
今回使用するフォルダは前回コピー&ペーストした ch07_straight フォルダだ。その内容を示す。
wlt_cnn_40_170808.png

このうちの、simple_convnet.py を変更した。このCNNを記述するPython コードはn x n の画像に対応しているコードだった。今回は 10 x 56 で行と列の数が違っているので、対応することができないのだ。そこで、input_size の代わりにinput_size_x とinput_size_y をconv_output_size の代わりにconv_output_size_x とconv_output_size_y を作った。

        input_size_y = input_dim[1]
        input_size_x = input_dim[2]
        conv_output_size_y = (input_size_y - filter_size + 2*filter_pad) / filter_stride + 1
        conv_output_size_x = (input_size_x - filter_size + 2*filter_pad) / filter_stride + 1
        pool_output_size = int(filter_num * (conv_output_size_y/2) * (conv_output_size_x/2))


simple_convnet.py の全文を貼っておく。

# simple_convnet.py
# 2017/08/08 白線追従走行用CNNに変更 by marsee
# 元になったコードは、https://github.com/oreilly-japan/deep-learning-from-scratch にあります。
# 改変したコードもMITライセンスとします。 2017/08/08 by marsee

# coding: utf-8
import sys, os
sys.path.append(os.pardir)  # 親ディレクトリのファイルをインポートするための設定
import pickle
import numpy as np
from collections import OrderedDict
from common.layers import *
from common.gradient import numerical_gradient


class SimpleConvNet:
    """単純なConvNet

    conv - relu - pool - affine - relu - affine - softmax
    
    Parameters
    ----------
    input_size : 入力サイズ(MNISTの場合は784)
    hidden_size_list : 隠れ層のニューロンの数のリスト(e.g. [100, 100, 100])
    output_size : 出力サイズ(MNISTの場合は10)
    activation : 'relu' or 'sigmoid'
    weight_init_std : 重みの標準偏差を指定(e.g. 0.01)
        'relu'または'he'を指定した場合は「Heの初期値」を設定
        'sigmoid'または'xavier'を指定した場合は「Xavierの初期値」を設定
    """
    def __init__(self, input_dim=(1, 10, 56), 
                 conv_param={'filter_num':30, 'filter_size':5, 'pad':0, 'stride':1},
                 hidden_size=100, output_size=10, weight_init_std=0.01):
        filter_num = conv_param['filter_num']
        filter_size = conv_param['filter_size']
        filter_pad = conv_param['pad']
        filter_stride = conv_param['stride']
        input_size_y = input_dim[1]
        input_size_x = input_dim[2]
        conv_output_size_y = (input_size_y - filter_size + 2*filter_pad) / filter_stride + 1
        conv_output_size_x = (input_size_x - filter_size + 2*filter_pad) / filter_stride + 1
        pool_output_size = int(filter_num * (conv_output_size_y/2) * (conv_output_size_x/2))
        print("pool_output_size ={0}".format(pool_output_size))

        # 重みの初期化
        self.params = {}
        self.params['W1'] = weight_init_std * \
                            np.random.randn(filter_num, input_dim[0], filter_size, filter_size)
        self.params['b1'] = np.zeros(filter_num)
        self.params['W2'] = weight_init_std * \
                            np.random.randn(pool_output_size, hidden_size)
        self.params['b2'] = np.zeros(hidden_size)
        self.params['W3'] = weight_init_std * \
                            np.random.randn(hidden_size, output_size)
        self.params['b3'] = np.zeros(output_size)

        # レイヤの生成
        self.layers = OrderedDict()
        self.layers['Conv1'] = Convolution(self.params['W1'], self.params['b1'],
                                           conv_param['stride'], conv_param['pad'])
        self.layers['Relu1'] = Relu()
        self.layers['Pool1'] = Pooling(pool_h=2, pool_w=2, stride=2)
        self.layers['Affine1'] = Affine(self.params['W2'], self.params['b2'])
        self.layers['Relu2'] = Relu()
        self.layers['Affine2'] = Affine(self.params['W3'], self.params['b3'])

        self.last_layer = SoftmaxWithLoss()

    def predict(self, x):
        for layer in self.layers.values():
            x = layer.forward(x)

        return x

    def loss(self, x, t):
        """損失関数を求める
        引数のxは入力データ、tは教師ラベル
        """
        y = self.predict(x)
        return self.last_layer.forward(y, t)

    def accuracy(self, x, t, batch_size=100):
        if t.ndim != 1 : t = np.argmax(t, axis=1)
        
        acc = 0.0
        
        for i in range(int(x.shape[0] / batch_size)):
            tx = x[i*batch_size:(i+1)*batch_size]
            tt = t[i*batch_size:(i+1)*batch_size]
            y = self.predict(tx)
            y = np.argmax(y, axis=1)
            acc += np.sum(y == tt) 
        
        return acc / x.shape[0]

    def numerical_gradient(self, x, t):
        """勾配を求める(数値微分)

        Parameters
        ----------
        x : 入力データ
        t : 教師ラベル

        Returns
        -------
        各層の勾配を持ったディクショナリ変数
            grads['W1']、grads['W2']、...は各層の重み
            grads['b1']、grads['b2']、...は各層のバイアス
        """
        loss_w = lambda w: self.loss(x, t)

        grads = {}
        for idx in (1, 2, 3):
            grads['W' + str(idx)] = numerical_gradient(loss_w, self.params['W' + str(idx)])
            grads['b' + str(idx)] = numerical_gradient(loss_w, self.params['b' + str(idx)])

        return grads

    def gradient(self, x, t):
        """勾配を求める(誤差逆伝搬法)

        Parameters
        ----------
        x : 入力データ
        t : 教師ラベル

        Returns
        -------
        各層の勾配を持ったディクショナリ変数
            grads['W1']、grads['W2']、...は各層の重み
            grads['b1']、grads['b2']、...は各層のバイアス
        """
        # forward
        self.loss(x, t)

        # backward
        dout = 1
        dout = self.last_layer.backward(dout)

        layers = list(self.layers.values())
        layers.reverse()
        for layer in layers:
            dout = layer.backward(dout)

        # 設定
        grads = {}
        grads['W1'], grads['b1'] = self.layers['Conv1'].dW, self.layers['Conv1'].db
        grads['W2'], grads['b2'] = self.layers['Affine1'].dW, self.layers['Affine1'].db
        grads['W3'], grads['b3'] = self.layers['Affine2'].dW, self.layers['Affine2'].db

        return grads
        
    def save_params(self, file_name="params.pkl"):
        params = {}
        for key, val in self.params.items():
            params[key] = val
        with open(file_name, 'wb') as f:
            pickle.dump(params, f)

    def load_params(self, file_name="params.pkl"):
        with open(file_name, 'rb') as f:
            params = pickle.load(f)
        for key, val in params.items():
            self.params[key] = val

        for i, key in enumerate(['Conv1', 'Affine1', 'Affine2']):
            self.layers[key].W = self.params['W' + str(i+1)]
            self.layers[key].b = self.params['b' + str(i+1)]


次に、Jupyter Notebook を立ち上げて、DLFS_Chap7.ipynb を起動した。
wlt_cnn_41_170808.png

train_convnet.py のdataset_straight.straight_dataset を読むように変更し、また、input_dim=(1,10,56) に変更した。
wlt_cnn_42_170808.png

train_convnet.py を貼っておく。

# train_convnet.py
# 2017/08/08 白線追従走行用CNNに変更 by marsee
# 元になったコードは、https://github.com/oreilly-japan/deep-learning-from-scratch にあります。
# 改変したコードもMITライセンスとします。 2017/08/08 by marsee

# coding: utf-8
import sys, os
sys.path.append(os.pardir)  # 親ディレクトリのファイルをインポートするための設定
import numpy as np
import matplotlib.pyplot as plt
from dataset_straight.straight_dataset import load_mnist
from simple_convnet import SimpleConvNet
from common.trainer import Trainer

# データの読み込み
(x_train, t_train), (x_test, t_test) = load_mnist(flatten=False)

# 処理に時間のかかる場合はデータを削減 
#x_train, t_train = x_train[:5000], t_train[:5000]
#x_test, t_test = x_test[:1000], t_test[:1000]

max_epochs = 20

network = SimpleConvNet(input_dim=(1,10,56), 
                        conv_param = {'filter_num': 30, 'filter_size': 5, 'pad': 0, 'stride': 1},
                        hidden_size=100, output_size=3, weight_init_std=0.01)
                        
trainer = Trainer(network, x_train, t_train, x_test, t_test,
                  epochs=max_epochs, mini_batch_size=100,
                  optimizer='Adam', optimizer_param={'lr': 0.001},
                  evaluate_sample_num_per_epoch=100)
trainer.train()

# パラメータの保存
network.save_params("params.pkl")
print("Saved Network Parameters!")

# グラフの描画
markers = {'train': 'o', 'test': 's'}
x = np.arange(max_epochs)
plt.plot(x, trainer.train_acc_list, marker='o', label='train', markevery=2)
plt.plot(x, trainer.test_acc_list, marker='s', label='test', markevery=2)
plt.xlabel("epochs")
plt.ylabel("accuracy")
plt.ylim(0, 1.0)
plt.legend(loc='lower right')
plt.show()


train_convnet.py を実行した結果を貼っておく。

pool_output_size =2340
train loss:1.09740103666
=== epoch:1, train acc:0.0, test acc:0.0 ===
train loss:1.09619339353
train loss:1.09805550027
train loss:1.09687513729
train loss:1.0943589982
train loss:1.09043641309
train loss:1.08765370932
train loss:1.08988835762
train loss:1.08589893222
train loss:1.08082757519
train loss:1.07091805021
train loss:1.06677488283
train loss:1.07590794106
train loss:1.07036316486
train loss:1.0564093902
train loss:1.04913884878
=== epoch:2, train acc:1.0, test acc:1.0 ===
train loss:1.05282141475
train loss:1.02463171511
train loss:1.03238803274
train loss:1.01808300652
train loss:1.00418097479
train loss:0.994927691467
train loss:0.971943720127
train loss:0.938959564805
train loss:0.959999566898
train loss:0.964902849483
train loss:0.930027599907
train loss:0.910958350671
train loss:0.912115741252
train loss:0.877372771453
train loss:0.881933637438
=== epoch:3, train acc:1.0, test acc:1.0 ===
train loss:0.82203361721
train loss:0.875176827014
train loss:0.799964071175
train loss:0.801881639351
train loss:0.815978625085
train loss:0.779677387859
train loss:0.808213315743
train loss:0.779122522377
train loss:0.67732259731
train loss:0.664630569144
train loss:0.696595385714
train loss:0.804241795734
train loss:0.665426441902
train loss:0.672940861823
train loss:0.65431805427
=== epoch:4, train acc:1.0, test acc:1.0 ===
train loss:0.733642727716
train loss:0.724044016753
train loss:0.728747015891
train loss:0.645574644162
train loss:0.563772565951
train loss:0.650969893624
train loss:0.71471792151
train loss:0.562708504548
train loss:0.603808048409
train loss:0.599713674484
train loss:0.627750549668
train loss:0.554349357064
train loss:0.615028866599
train loss:0.581826815111
train loss:0.614025507529
=== epoch:5, train acc:0.98, test acc:0.98 ===
train loss:0.536548177427
train loss:0.616438072707
train loss:0.545175491413
train loss:0.59173160996
train loss:0.593612159015
train loss:0.599846111758
train loss:0.602536956687
train loss:0.526653021569
train loss:0.493542164942
train loss:0.652987814042
train loss:0.593193099959
train loss:0.651098995425
train loss:0.583797795175
train loss:0.497425254547
train loss:0.50022478405
=== epoch:6, train acc:1.0, test acc:0.99 ===
train loss:0.546986740154
train loss:0.632857452048
train loss:0.596720193602
train loss:0.628242539831
train loss:0.516102642255
train loss:0.584049938495
train loss:0.643520590658
train loss:0.433788079879
train loss:0.464739965862
train loss:0.517770447956
train loss:0.565927389082
train loss:0.574423786278
train loss:0.487440270503
train loss:0.460763808238
train loss:0.50437176485
=== epoch:7, train acc:0.91, test acc:0.8 ===
train loss:0.539680492517
train loss:0.43184783555
train loss:0.463142994517
train loss:0.40834945717
train loss:0.502730258745
train loss:0.530335381027
train loss:0.483509730618
train loss:0.419754214749
train loss:0.542743643599
train loss:0.545018581985
train loss:0.527738479101
train loss:0.552609220918
train loss:0.511188282627
train loss:0.439410114208
train loss:0.547204230479
=== epoch:8, train acc:0.87, test acc:0.74 ===
train loss:0.42177291798
train loss:0.37878361722
train loss:0.553163684557
train loss:0.573063758222
train loss:0.39186244896
train loss:0.445078706415
train loss:0.462594294123
train loss:0.438555772242
train loss:0.385638041553
train loss:0.415701287503
train loss:0.391015150038
train loss:0.468615281475
train loss:0.504983134551
train loss:0.377033870421
train loss:0.39501268333
=== epoch:9, train acc:0.95, test acc:0.89 ===
train loss:0.387747127634
train loss:0.385348791912
train loss:0.482271444765
train loss:0.397431981912
train loss:0.38837660175
train loss:0.456368766821
train loss:0.381980621014
train loss:0.320979196606
train loss:0.374925172354
train loss:0.424100142739
train loss:0.339776275437
train loss:0.379021958425
train loss:0.415783734932
train loss:0.312515924983
train loss:0.493949450648
=== epoch:10, train acc:0.99, test acc:0.9 ===
train loss:0.443524574076
train loss:0.357979512064
train loss:0.415673465881
train loss:0.362790259715
train loss:0.25231192493
train loss:0.405671943517
train loss:0.35069212333
train loss:0.372544883284
train loss:0.409110864872
train loss:0.343560294381
train loss:0.31804787133
train loss:0.403356537286
train loss:0.268652788357
train loss:0.394903753068
=============== Final Test Accuracy ===============
test acc:0.714666666667
Saved Network Parameters!
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-3-d6e09c53f736> in <module>()
     36 markers = {'train': 'o', 'test': 's'}
     37 x = np.arange(max_epochs)
---> 38 plt.plot(x, trainer.train_acc_list, marker='o', label='train', markevery=2)
     39 plt.plot(x, trainer.test_acc_list, marker='s', label='test', markevery=2)
     40 plt.xlabel("epochs")

C:\Users\Masaaki\Anaconda3\lib\site-packages\matplotlib\pyplot.py in plot(*args, **kwargs)
   3316                       mplDeprecation)
   3317     try:
-> 3318         ret = ax.plot(*args, **kwargs)
   3319     finally:
   3320         ax._hold = washold

C:\Users\Masaaki\Anaconda3\lib\site-packages\matplotlib\__init__.py in inner(ax, *args, **kwargs)
   1889                     warnings.warn(msg % (label_namer, func.__name__),
   1890                                   RuntimeWarning, stacklevel=2)
-> 1891             return func(ax, *args, **kwargs)
   1892         pre_doc = inner.__doc__
   1893         if pre_doc is None:

C:\Users\Masaaki\Anaconda3\lib\site-packages\matplotlib\axes\_axes.py in plot(self, *args, **kwargs)
   1404         kwargs = cbook.normalize_kwargs(kwargs, _alias_map)
   1405 
-> 1406         for line in self._get_lines(*args, **kwargs):
   1407             self.add_line(line)
   1408             lines.append(line)

C:\Users\Masaaki\Anaconda3\lib\site-packages\matplotlib\axes\_base.py in _grab_next_args(self, *args, **kwargs)
    405                 return
    406             if len(remaining) <= 3:
--> 407                 for seg in self._plot_args(remaining, kwargs):
    408                     yield seg
    409                 return

C:\Users\Masaaki\Anaconda3\lib\site-packages\matplotlib\axes\_base.py in _plot_args(self, tup, kwargs)
    383             x, y = index_of(tup[-1])
    384 
--> 385         x, y = self._xy_from_xy(x, y)
    386 
    387         if self.command == 'plot':

C:\Users\Masaaki\Anaconda3\lib\site-packages\matplotlib\axes\_base.py in _xy_from_xy(self, x, y)
    242         if x.shape[0] != y.shape[0]:
    243             raise ValueError("x and y must have same first dimension, but "
--> 244                              "have shapes {} and {}".format(x.shape, y.shape))
    245         if x.ndim > 2 or y.ndim > 2:
    246             raise ValueError("x and y can be no greater than 2-D, but have "

ValueError: x and y must have same first dimension, but have shapes (20,) and (10,)

In [21]:

print(network.params['W1'].shape)


plot がなぜか?エラーになってしまう。

テストデータの正解率が 71 % になってしまうのは低すぎないだろうか?
もう一度、トレーニング・データを取り直してみようか?
  1. 2017年08月09日 03:34 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

白線追従走行用畳み込みニューラルネットワークの製作6(学習1)

白線追従走行用畳み込みニューラルネットワークの製作5(テストデータの作成)”の続き。

前回はテストデータを測定しファイルにまとめた。今回はトレーニング・ファイルとテスト・ファイルがそろったので、Pythonコードを使用したのCNNの学習を行う。

「ゼロから作るDeep Learning」の畳み込みニューラルネットワークのハードウェア化1”からのブログ記事を参考にMNISTから白線追従データセット用に変更する。

まずは、dataset_straight フォルダを作成し、ch07 フォルダをコピー&ペーストして ch07_straight フォルダを作成した。
wlt_cnn_39_170808.png

dataset_straight フォルダに”白線追従走行用畳み込みニューラルネットワークの製作3(トレーニング、ラベル・ファイルの作成)”で作成したトレーニングの画像ファイルの train_straight_run_image とラベル・ファイル train_straight_run_label をコピー&ペーストした。更に、”白線追従走行用畳み込みニューラルネットワークの製作5(テストデータの作成)”で作成したテスト用の画像ファイルtest_straight_run_image とテスト用のラベル・ファイル test_straight_run_label をコピー&ペーストした。
次に、mnist.py をベースに straight_dataset.py を作成した。なお、多くのPython コードで load_mnist() が使用されているので、それは変更していない。straight_dataset.py を示す。

# straight_dataset.py
# 2017/08/08 白線追従走行用CNNに変更 by marsee
# 元になったコードは、https://github.com/oreilly-japan/deep-learning-from-scratch の mnist.py です
# 改変したコードもMITライセンスとします。 2017/08/08 by marsee

# coding: utf-8
try:
    import urllib.request
except ImportError:
    raise ImportError('You should use Python 3.x')
import os.path
import gzip
import pickle
import os
import numpy as np


key_file = {
    'train_img':'train_straight_run_image',
    'train_label':'train_straight_run_label',
    'test_img':'test_straight_run_image',
    'test_label':'test_straight_run_label'
}

dataset_dir = os.path.dirname(os.path.abspath(__file__))
save_file = dataset_dir + "/mnist.pkl"

train_num = 750
test_num = 375
img_dim = (1, 10, 56)
img_size = 560


def _load_label(file_name):
    file_path = dataset_dir + "/" + file_name
    
    print("Converting " + file_name + " to NumPy Array ...")
    with open(file_path, 'rb') as f:
            labels = np.frombuffer(f.read(), np.uint8, offset=8)
    print("Done")
    
    return labels

def _load_img(file_name):
    file_path = dataset_dir + "/" + file_name
    
    print("Converting " + file_name + " to NumPy Array ...")    
    with open(file_path, 'rb') as f:
            data = np.frombuffer(f.read(), np.uint8, offset=16)
    data = data.reshape(-1, img_size)
    print("Done")
    
    return data
    
def _convert_numpy():
    dataset = {}
    dataset['train_img'] =  _load_img(key_file['train_img'])
    dataset['train_label'] = _load_label(key_file['train_label'])    
    dataset['test_img'] = _load_img(key_file['test_img'])
    dataset['test_label'] = _load_label(key_file['test_label'])
    
    return dataset

def init_mnist():
    dataset = _convert_numpy()
    print("Creating pickle file ...")
    with open(save_file, 'wb') as f:
        pickle.dump(dataset, f, -1)
    print("Done!")

def _change_one_hot_label(X):
    T = np.zeros((X.size, 3))
    for idx, row in enumerate(T):
        row[X[idx]] = 1
        
    return T
    

def load_mnist(normalize=True, flatten=True, one_hot_label=False):
    """MNISTデータセットの読み込み
    
    Parameters
    ----------
    normalize : 画像のピクセル値を0.0~1.0に正規化する
    one_hot_label : 
        one_hot_labelがTrueの場合、ラベルはone-hot配列として返す
        one-hot配列とは、たとえば[0,0,1,0,0,0,0,0,0,0]のような配列
    flatten : 画像を一次元配列に平にするかどうか 
    
    Returns
    -------
    (訓練画像, 訓練ラベル), (テスト画像, テストラベル)
    """
    if not os.path.exists(save_file):
        init_mnist()
        
    with open(save_file, 'rb') as f:
        dataset = pickle.load(f)
    
    if normalize:
        for key in ('train_img', 'test_img'):
            dataset[key] = dataset[key].astype(np.float32)
            dataset[key] /= 255.0
            
    if one_hot_label:
        dataset['train_label'] = _change_one_hot_label(dataset['train_label'])
        dataset['test_label'] = _change_one_hot_label(dataset['test_label'])
    
    if not flatten:
         for key in ('train_img', 'test_img'):
            dataset[key] = dataset[key].reshape(-1, 1, 10, 56)

    return (dataset['train_img'], dataset['train_label']), (dataset['test_img'], dataset['test_label']) 


if __name__ == '__main__':
    init_mnist()


いろいろと元の mnist.py そのままだが、とりあえず、これで動くようだ。

dataset_straight フォルダを示す。
wlt_cnn_38_170808.png

今日は寝坊してしまったので、ここまで。明日に続きます。
  1. 2017年08月08日 07:34 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

MFT2017 に行って来ました

近頃久しく出展してないですが、昨日MFT2017 に見学に行ってきました。
MFT2017_1_170807.jpg

会場の様子です。
MFT2017_2_170807.jpg

朝から、にぎわっていました。

筑波大学の学生さんのSigboost もありました。ケースの中にZYBO が入っていました。

FabLab Kannai の作品です。木をレーザー加工機で加工した板を組み合わせて丸い形にしていました。とっても良い感じでしたね。
MFT2017_3_170807.jpg

MFT2017_4_170807.jpg

Make Network の方のワークベンチです。作りは荒かったですが、どこでも移動して広げて作業するというコンセプトが良かったです。
MFT2017_5_170807.jpg

千葉大学平沢研究室の木工用5軸加工機で加工した木材の数々。でもこの加工機では完全な加工はできないような?ノミも使っているのかもしれません?
MFT2017_6_170807.jpg

MFT2017_7_170807.jpg

木工用5軸加工機。
MFT2017_8_170807.jpg

加工の様子。音がうるさいので注意です。


HotDog というIchgoJam 向けのロボットカーが走っていました。私の作っているミニ・ロボットカーの土台にいいかな?と思って資料もらってきました。

MachiKania というPIC32 が搭載されたカラーテレビゲームシステムがありました。ビデオ信号をPIC32 のソフトウェアで作っているそうです。同期の時にゲームの処理をしているそうです。凄いです。大変そう。。。お値段はPIC32 だけで済むので、安いそうです。

そうそう、R2D2たちもいました。著作権は大丈夫なのかな?ピンぼけ写真ですみません。。。
MFT2017_9_170807.jpg

MFT2017_10_170807.jpg

スイッチサイエンスやRS コンポーネンツなども来ていました。

私も持っているHAKKO のはんだごてのFX-600 に数量限定ではありますが、ピンクとゴールド、シルバーの新色が登場したそうです。凄いです。女性が喜ぶからなんですかね?

29,800円の 3D プリンタ BS CUBE がありました。でも、スライスソフトは自分で用意するとのことです。大丈夫かな?
アマゾンでも売っています。なかなか良かったです。

マンホールのふたの写真を集めているアプリの宣伝がありました。面白いです。ご当地マンホール蓋。つくば市にもスペースシャトルのマンホール蓋があります。見ました。

ラズベリーパイカメラに取り付けて魚眼レンズにするというのがありました。Entaniya ラズベリーパイ VR 220 改造キット

4096個だったかな?を使用したLED の3次元ディスプレイです。LEDの数に圧倒されました。
MFT2017_11_170807.jpg

面白そうなものとしては、空飛ぶスーパーカブがありました。ターボプロップ・エンジンしょって飛ぶのは大丈夫でしょうか?飛べれば面白いですが。。。ネタにしかならない気もします。

写真はホバークラフトです。飛んでいるところはなかったです。残念。。。
MFT2017_12_170807.jpg

最後につくば科学株式会社のテスラコイルです。放電で音楽を流していましたが、凄い音量です。イベントで使えそうですね。。。
MFT2017_13_170807.jpg

あと、DNNを使ったものがちらほらと。。。きゅうりの選別は有名ですが、鳥箱に入った鳥をYOROを使ったDNNで判別というのもありました。Jetson 使っているそうです。ディスプレイに写した鳥を判別していました。

以上独断と偏見のMFT2017 レポートでした。
  1. 2017年08月07日 05:21 |
  2. Make出展
  3. | トラックバック:0
  4. | コメント:0

白線追従走行用畳み込みニューラルネットワークの製作5(テストデータの作成)

白線追従走行用畳み込みニューラルネットワークの製作4(トレーニング・ファイルのチェック)”の続き。

前回は、トレーニング・ファイルをチェックして、画像が取り出せることが分かった。今回は、テストデータを作成してみよう。

トレーニング・ファイルは結構いい加減にデータを取ってしまったが、テストデータはデータのとり方を記録に残しておくことにする。

白線追従テストデータ測定方法

<直進>
ミニロボットカーが真っ直ぐの時の角度 111度
左、右 ±7度
左右車輪が白線の真ん中、姿勢は真っ直ぐ

<左ターン>
白線内 +15度
白線内 +20度
右車輪白線逸脱車体1/4
右車輪白線逸脱車体1/4 + +10度
右車輪白線逸脱車体1/2

<右ターン>
白線内 -15度
白線内 -20度
左車輪白線逸脱車体1/4
左車輪白線逸脱車体1/4 + -10度
左車輪白線逸脱車体1/2


なお、角度はデジタルコンパスで測定した。まずはまっすぐで、白線のちょうど真ん中の時。(直進)
wlt_cnn_33_170805.jpg

左車輪が白線の真ん中、姿勢は真っ直ぐ(直進)。
wlt_cnn_34_170805.jpg

白線内 +15度(左ターン)。
wlt_cnn_35_170805.jpg

右車輪白線逸脱車体1/4(左ターン)。
wlt_cnn_36_170805.jpg

右車輪白線逸脱車体1/4 + +10度(左ターン)。
wlt_cnn_37_170805.jpg

なお、撮影したBMPファイルは直進(straight_test?.bmp)と左ターン(left_turn_test?.bmp)と右ターン(right_turn_test?.bmp)がそれぞれ5枚ずつとなった。よって、3 x 5 x 25 = 375 枚となった。

Vivado HLS 2016.4 で straight_test_dataset を作成した。
straight_test_dataset ディレクトリにBMPファイルと straight_dataset_bmp.cpp と straight_dataset_bmp.h をコピー&ペーストした。
straight_dataset_bmp.h をテストデータ用に記述を変更した。
wlt_cnn_26_170805.png

straight_dataset_bmp.cpp をテストデータ用に記述を変更した。
wlt_cnn_27_170805.png

C シミュレーションを行った。
wlt_cnn_28_170805.png

test_straight_run_image と test_straight_run_label ができた。
wlt_cnn_28_170805.png

solution1/csim/build ディレクトリを示す。
wlt_cnn_29_170805.png

wlt_cnn_30_170805.png

test_straight_run_image の内容を示す。
wlt_cnn_31_170805.png

test_straight_run_label の内容を示す。
wlt_cnn_32_170805.png

これでテストデータもできたので、いよいよ学習を始められるかな?
  1. 2017年08月05日 05:27 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

白線追従走行用畳み込みニューラルネットワークの製作4(トレーニング・ファイルのチェック)

白線追従走行用畳み込みニューラルネットワークの製作3(トレーニング、ラベル・ファイルの作成)”の続き。

前回は、straight_dataset_bmp.cpp を作成して、直進学習用の白線の画像のMNISTフォーマットのトレーニング・ファイルとラベル・ファイルを作成した。今回は、トレーニング・ファイルを本当に画像が格納されているかどうか?をチェックする。

トレーニング・ファイルは、train_straight_run_image という名前だ。
Vivado HLS 2016.4 の straight_dataset_check プロジェクトを作成し、train_straight_run_image と、新たに作成したstraight_dataset_check.cpp とstraight_dataset_bmp.h を straight_dataset_check プロジェクトのディレクトリにコピーした。
wlt_cnn_20_170804.png

straight_dataset_check.cpp を貼っておく。なお、このアプリケーションソフトは、train_straight_run_image からIMAGE_NUMBER 番目の画像を output.bmp に変換する。現在のIMAGE_NUMBER は 0 だ。つまり最初の画像を output.bmp に変換する。

// straight_dataset_check.cpp
// 2017/08/02 by marsee
//

#include <iostream>
#include "hls_opencv.h"
#include "straight_dataset_bmp.h"

#define IMAGE_NUMBER 4

int main(){
    FILE *ftin, *ftln;
    char train_image_name[256] = "train_straight_run_image";
    uint8_t buf[600];

    if ((ftin = fopen(train_image_name, "rb")) == NULL){
        fprintf(stderr, "Can't open %s\n", train_image_name);
        exit(1);
    }

    fread(buf, sizeof(uint32_t), 4, ftin); // header read

    for(int i=0; i<=IMAGE_NUMBER; i++){
        fread(buf, sizeof(uint8_t), DATASET_HEIGHT*DATASET_WIDTH, ftin);
    }

    cv::Mat wlt_img(cv::Size(5610), CV_8UC1);

    for (int y = 0; y < wlt_img.rows; y++) {
        for (int x = 0; x < wlt_img.cols; x++) {
            wlt_img.at<uchar>(y, x) = buf[y*DATASET_WIDTH+x];
        }
    }

    cv::imwrite("output.bmp", wlt_img);

    fclose(ftin);

    return(0);
}


straight_dataset_bmp.h は前回と同じファイルを使用している。

C シミュレーションを行った。
wlt_cnn_21_170804.png

output.bmp が生成されているのが分かる。
output.bmp を見てみよう。
wlt_cnn_22_170804.png

最初の画像が抽出されたのが分かった。

それでは、IMAGE_NUMBER を 4 に変更して、もう一度、C シミュレーションを行った。なお、5 番目の画像は、一番右側の画像になる。1つの白線の画像から 5 x 5 = 25 個のトレーニング用画像を生成している。最初に1ピクセルずつ段々と右にシフトしていくので
5 個目の画像が一番右側の画像となる。
wlt_cnn_23_170804.png

生成された output.bmp を示す。
wlt_cnn_24_170804.png

IMAGE_NUMBER が 0 の画像よりも右側の白線の画像だということが分かると思う。

これで、トレーニング・ファイルも問題なさそうだということが分かった。

OpenCV を使うとソースコードが短くなって書くのが楽でよい。
  1. 2017年08月04日 04:19 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

白線追従走行用畳み込みニューラルネットワークの製作3(トレーニング、ラベル・ファイルの作成)

白線追従走行用畳み込みニューラルネットワークの製作2(画像縮小、切り出し)”の続き。

前回は、800 x 600 ピクセルの元画像を 60 x 45 に縮小してから、白黒変換し、56 x 10 ピクセルの白線の画像を切り出した。今回は、本格的に56 x 10 ピクセルの白線の画像を切り出すとともに、MNISTデータセットと同じフォーマットでトレーニング・ファイルとラベル・ファイルを生成しよう。
なお、ソフトを作成する際に参考にしたサイトは、”OpenCV入門 2.画像の簡単操作”だ。このサイトには、Matからピクセル値を取り出す方法が書いてある。

まずは、straight_dataset_bmp.cpp を変更した。ここに貼っておく。なお、3つ続けて、同じコードを使用して、みっともないことをお詫びしておく。
buf[0] = htonl(0x803); の htonl() だが、uint32_t を fwrite() するとリトルエンディアンでファイルに書き込まれてしまう。つまり、0x00000803 だと 03 08 00 00 と書き込まれてしまう。これではまずいので、ビックエンディアンに変更した。リトルエンディアンをビックエンディアンに変更する関数が htonl() である。

// straight_dataset_bmp.cpp
// 2017/07/24 by marsee
//

#include <iostream>
#include "hls_opencv.h"
#include "straight_dataset_bmp.h"
#include <arpa/inet.h>

int main(){
    char straight_fn[256] = "straight";
    char left_turn_fn[256] = "left_turn";
    char right_turn_fn[256] = "right_turn";
    char bmp_file[256];
    FILE *ftin, *ftln;
    char train_image_name[256] = "train_straight_run_image";
    char train_label_name[256] = "train_straight_run_label";
    uint32_t buf[5];
    uint8_t bufchar[100];


    if ((ftin = fopen(train_image_name, "wb")) == NULL){
        fprintf(stderr, "Can't open %s\n", train_image_name);
        exit(1);
    }
    if ((ftln = fopen(train_label_name, "wb")) == NULL){
        fprintf(stderr, "Can't open %s\n", train_label_name);
        exit(1);
    }

    // Writed header
    buf[0] = htonl(0x803); // magic number
    buf[1] = htonl(750); // number of image (750)
    buf[2] = htonl(10); // number of rows (10)
    buf[3] = htonl(56); // number of columns (56)
    fwrite(buf, sizeof(uint32_t), 4, ftin);

    buf[0] = htonl(0x801); // magic number
    buf[1] = htonl(750); // number of image (750)
    fwrite(buf, sizeof(uint32_t), 2, ftln);

    // refereed to http://opencv.jp/cookbook/opencv_img.html
    // straight
    for(int i=0; i<STRAIGHT_NUM_OF_IMAGE; i++){
        sprintf(bmp_file, "%s%d.bmp", straight_fn, i);
        cv::Mat straight_img = cv::imread(bmp_file,1);
        if(straight_img.empty())
            return(-1);
        cv::Mat reduct_img(straight_img.rows*0.075, straight_img.cols*0.075, straight_img.type());
        cv::resize(straight_img, reduct_img, reduct_img.size(), cv::INTER_LINEAR);
        cv::Mat gray_img;
        cv::cvtColor(reduct_img, gray_img, CV_BGR2GRAY);

        sprintf(bmp_file, "%s_RED%d.bmp", straight_fn, i);
        cv::imwrite(bmp_file, gray_img);

        for(int y=0; y<5; y++){
            for(int x=0; x<5; x++){
                cv::Rect rect_center(x, 30+y, 5610);
                cv::Mat img_rect(gray_img, rect_center);
                sprintf(bmp_file, "%s_RED_rect%d_%d%d.bmp", straight_fn, i, y, x);
                cv::imwrite(bmp_file, img_rect);

                for(int iy=0; iy<img_rect.rows; iy++){
                    for(int ix=0; ix<img_rect.cols; ix++){
                        bufchar[ix] = img_rect.at<uchar>(iy, ix);
                    }
                    fwrite(bufchar, sizeof(uint8_t), img_rect.cols, ftin); // image write
                }
                bufchar[0] = 0x1;
                fwrite(bufchar, sizeof(uint8_t), 1, ftln); // label write
            }
        }
    }

    // left turn
    for(int i=0; i<LEFT_TRUN_NUM_OF_IMAGE; i++){
        sprintf(bmp_file, "%s%d.bmp", left_turn_fn, i);
        cv::Mat left_trun_img = cv::imread(bmp_file,1);
        if(left_trun_img.empty())
            return(-1);
        cv::Mat reduct_img(left_trun_img.rows*0.075, left_trun_img.cols*0.075, left_trun_img.type());
        cv::resize(left_trun_img, reduct_img, reduct_img.size(), cv::INTER_LINEAR);
        cv::Mat gray_img;
        cv::cvtColor(reduct_img, gray_img, CV_BGR2GRAY);

        sprintf(bmp_file, "%s_RED%d.bmp", left_turn_fn, i);
        cv::imwrite(bmp_file, gray_img);

        for(int y=0; y<5; y++){
            for(int x=0; x<5; x++){
                cv::Rect rect_center(x, 30+y, 5610);
                cv::Mat img_rect(gray_img, rect_center);
                sprintf(bmp_file, "%s_RED_rect%d_%d%d.bmp", left_turn_fn, i, y, x);
                cv::imwrite(bmp_file, img_rect);

                for(int iy=0; iy<img_rect.rows; iy++){
                    for(int ix=0; ix<img_rect.cols; ix++){
                        bufchar[ix] = img_rect.at<uchar>(iy, ix);
                    }
                    fwrite(bufchar, sizeof(uint8_t), img_rect.cols, ftin); // image write
                }
                bufchar[0] = 0x0;
                fwrite(bufchar, sizeof(uint8_t), 1, ftln); // label write
            }
        }
    }

    // right turn
    for(int i=0; i<STRAIGHT_NUM_OF_IMAGE; i++){
        sprintf(bmp_file, "%s%d.bmp", right_turn_fn, i);
        cv::Mat right_trun_img = cv::imread(bmp_file,1);
        if(right_trun_img.empty())
            return(-1);
        cv::Mat reduct_img(right_trun_img.rows*0.075, right_trun_img.cols*0.075, right_trun_img.type());
        cv::resize(right_trun_img, reduct_img, reduct_img.size(), cv::INTER_LINEAR);
        cv::Mat gray_img;
        cv::cvtColor(reduct_img, gray_img, CV_BGR2GRAY);

        sprintf(bmp_file, "%s_RED%d.bmp", right_turn_fn, i);
        cv::imwrite(bmp_file, gray_img);

        for(int y=0; y<5; y++){
            for(int x=0; x<5; x++){
                cv::Rect rect_center(x, 30+y, 5610);
                cv::Mat img_rect(gray_img, rect_center);
                sprintf(bmp_file, "%s_RED_rect%d_%d%d.bmp", right_turn_fn, i, y, x);
                cv::imwrite(bmp_file, img_rect);

                for(int iy=0; iy<img_rect.rows; iy++){
                    for(int ix=0; ix<img_rect.cols; ix++){
                        bufchar[ix] = img_rect.at<uchar>(iy, ix);
                    }
                    fwrite(bufchar, sizeof(uint8_t), img_rect.cols, ftin); // image write
                }
                bufchar[0] = 0x2;
                fwrite(bufchar, sizeof(uint8_t), 1, ftln); // label write
            }
        }
    }

    fclose(ftin);
    fclose(ftln);

    return(0);
}


次に、straight_dataset_bmp.h を貼っておく。これはバグをフィックスした。

// straight_dataset_bmp.h
// 2017/07/24 by marsee
//

#ifndef __STRAIGHT_DATASET_BMP_H__
#define __STRAIGHT_DATASET_BMP_H__

#include "hls_video.h"

#define BMP_HEIGHT    600
#define BMP_WIDTH    800

#define REDUCTION_RATIO    0.075    // 1/13.3333... 60x45

#define DATASET_HEIGHT    10
#define DATASET_WIDTH    56

#define STRAIGHT_BMP_FILE_NAME        straight
#define LEFT_TRUN_BMP_FILE_NAME        left_turn
#define RIGHT_TRUN_BMP_FILE_NAME    right_turn
#define STRAIGHT_NUM_OF_IMAGE        10
#define LEFT_TRUN_NUM_OF_IMAGE        10
#define RIGHT_TRUNNUM_OF_IMAGE        10

typedef hls::Scalar<3unsigned char> RGB_PIXEL;
typedef hls::Mat<BMP_HEIGHT, BMP_WIDTH, HLS_8UC3> RGB_IMAGE;
typedef hls::Mat<BMP_HEIGHT, BMP_WIDTH, HLS_8UC1> GRAY_IMAGE;

#endif


straight_dataset_bmp のVivado HLS プロジェクトを示す。
wlt_cnn_11_170803.png

C シミュレーションを行った。
wlt_cnn_12_170803.png

Straight_dataset_bmp/solution1/csim/build ディレクトリの内容を示す。ここにC シミュレーションの結果のファイルがある。
wlt_cnn_13_170803.png

wlt_cnn_19_170803.png

ピンクの四角枠で示した train_straight_run_image がトレーニング・ファイルで 56 x 10 ピクセルの 750 枚分の白線の画像が入っている。411KB だ。MNISTデータのフォーマットについては、”MNIST手書き数字のデータフォーマット”を参照のこと。
train_straight_run_label がラベル・ファイルだ。左旋回が 0 、直進が 1 、右旋回が 2 のラベルが入っている。1KB だ。

train_straight_run_label の内容を示す。
wlt_cnn_18_170803.png

train_straight_run_image の最初の部分を示す。
wlt_cnn_17_170803.png

ヘッダの次の値が 0x61, 0x5F なのに注目してほしい。
この値は、left_turn_RED_rect0_00.bmp ファイルの最初の行の最初の列からの2つのピクセル値のはずだ。
GIMP2 で見てみよう。スポイトを使用して、最初の行の最初の列(0, 0)の値を抜き出してみよう。
wlt_cnn_14_170803.png

(0, 0)のピクセル値は0x61 だった。
wlt_cnn_15_170803.png

(0, 1)のピクセル値は0x5F だった。
wlt_cnn_16_170803.png

これは、 train_straight_run_image の最初の 2 つのピクセル値と一致している。
これでトレーニング・ファイルとラベル・ファイルは大丈夫の様だが、一応、トレーニング・ファイルの値を読み込んで画像を復元するアプリケーションソフトを作成してみよう。
  1. 2017年08月03日 04:52 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

MNIST手書き数字のデータフォーマット

MNIST手書き数字のデータフォーマットを解析してみた。MNIST手書き数字のデータフォーマットに、今回、白線追従走行用のデータフォーマットを合わせた方が都合が良いのでやってみた。

日本語で参照したのは、”MNIST 手書き数字データを画像ファイルに変換する”。ここには、画像ファイルのフォーマットしか掲載されていなかったため、ラベルファイルのフォーマットも併せて、”MNIST handwritten digit database, Yann LeCun, Corinna Cortes and Chris Burges”を参照した。

MNIST handwritten digit database, Yann LeCun, Corinna Cortes and Chris Burges”から画像ファイルとラベルファイルのフォーマットを引用する。

TRAINING SET LABEL FILE (train-labels-idx1-ubyte):

[offset] [type]          [value]          [description] 
0000     32 bit integer  0x00000801(2049) magic number (MSB first) 
0004     32 bit integer  60000            number of items 
0008     unsigned byte   ??               label 
0009     unsigned byte   ??               label 
........ 
xxxx     unsigned byte   ??               label
The labels values are 0 to 9.

TRAINING SET IMAGE FILE (train-images-idx3-ubyte):

[offset] [type]          [value]          [description] 
0000     32 bit integer  0x00000803(2051) magic number 
0004     32 bit integer  60000            number of images 
0008     32 bit integer  28               number of rows 
0012     32 bit integer  28               number of columns 
0016     unsigned byte   ??               pixel 
0017     unsigned byte   ??               pixel 
........ 
xxxx     unsigned byte   ??               pixel
Pixels are organized row-wise. Pixel values are 0 to 255. 0 means background (white), 255 means foreground (black).

TEST SET LABEL FILE (t10k-labels-idx1-ubyte):

[offset] [type]          [value]          [description] 
0000     32 bit integer  0x00000801(2049) magic number (MSB first) 
0004     32 bit integer  10000            number of items 
0008     unsigned byte   ??               label 
0009     unsigned byte   ??               label 
........ 
xxxx     unsigned byte   ??               label
The labels values are 0 to 9.

TEST SET IMAGE FILE (t10k-images-idx3-ubyte):

[offset] [type]          [value]          [description] 
0000     32 bit integer  0x00000803(2051) magic number 
0004     32 bit integer  10000            number of images 
0008     32 bit integer  28               number of rows 
0012     32 bit integer  28               number of columns 
0016     unsigned byte   ??               pixel 
0017     unsigned byte   ??               pixel 
........ 
xxxx     unsigned byte   ??               pixel
Pixels are organized row-wise. Pixel values are 0 to 255. 0 means background (white), 255 means foreground (black). 


画像ファイルは 0 が白で 255 が黒だそうだ。そうか手書き数字は白地に黒だったのか。。。知らなかった。

実際のデータを見てみよう。トレーニングデータは大きいので、テストデータを見ていこう。
最初に画像ファイルの t10k-images-idx3-ubyte をバイナリエディタで見た。
MNIST_dataset_1_170801.png

最初の 0x0000 0803 が画像ファイルのマジック・ナンバーだ。その次の 0x0000 2710 は16進数なので、10進数に直すと10,000 となってデータの数を表す。0x0000 001c は10 進数にすると 28 だ。その次も同様。その後からは1バイトずつ、つまり、0 ~ 255 までのピクセル値を表す。

次にラベル・ファイルの t10k-labels-idx1-ubyte を見てみよう。
MNIST_dataset_2_170801.png

最初の 0x0000 0801 はラベル・ファイルのマジック・ナンバーだ。その次の 0x0000 2710 は16進数なので、10進数に直すと10,000 となってデータの数を表す。その次からはラベルが続いている。最初のラベルは0x07 で、つまり最初の数字は 7 であるということを表す。その次の数字は 2 だ。
  1. 2017年08月01日 12:37 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

白線追従走行用畳み込みニューラルネットワークの製作2(画像縮小、切り出し)

白線追従走行用畳み込みニューラルネットワークの製作1(概要)”の続き。

前回から間が空いてしまったが、前回集めた直線の白線画像をデータセットにする第1段階として、画像縮小と切り出しを行うソフトウェアを作成してみよう。
Vivado HLSでハードウェア化しやすく、短いコードで書けるようにOpenCVを使用することにする。もちろんVivado HLSを使用して、Vivado HLSのテストベンチとして、C++ ソースファイルを用意する。環境はネイティブUbuntu16.04 でVivado HLS 2017.2 を使用している。

これからの白線追従のためのニューラルネット学習のためのデータ・セット作成手順を書いておく。

1. 800x600の白線画像を1/13.333...(0.075)の60x45に縮める。
2. 60x45のうちの下から60x14を中間BMPファイルとしてセーブ
3. 60x14のうちの56x10を切り出してBMPファイルに。1つにつき5x5の25個できる。
4. 左右直進をやる。
直進10枚x25+左旋回10x25+右旋回10x25=750このデータセットをとりあえず、作ってみようか?
56x10=560なのでMNISTデータセットよりも小さくなる。


現在のソースコードを貼っておく。まずは、ヘッダファイルの straight_dataset_bmp.h から。
(2017/08/03 :修正 バグフィックス)


// straight_dataset_bmp.h
// 2017/07/24 by marsee
//

#ifndef __STRAIGHT_DATASET_BMP_H__
#define __STRAIGHT_DATASET_BMP_H__

#include "hls_video.h"

#define BMP_HEIGHT 600
#define BMP_WIDTH 800

#define REDUCTION_RATIO 0.075 // 1/13.3333... 60x45

#define DATASET_HEIGHT 10
#define DATASET_WIDTH 56

#define STRAIGHT_BMP_FILE_NAME straight
#define LEFT_TRUN_BMP_FILE_NAME left_turn
#define RIGHT_TRUN_BMP_FILE_NAME right_turn
#define STRAIGHT_NUM_OF_IMAGE 10
#define LEFT_TRUN_NUM_OF_IMAGE 10
#define RIGHT_TRUNNUM_OF_IMAGE 10

typedef hls::Scalar<3, unsigned char> RGB_PIXEL;
typedef hls::Mat<BMP_HEIGHT, BMP_WIDTH, HLS_8UC3> RGB_IMAGE;
typedef hls::Mat<BMP_HEIGHT, BMP_WIDTH, HLS_8UC1> GRAY_IMAGE;

#endif


次に、straight_dataset_bmp.cpp を貼っておく。まだ、直進の画像だけをしょりするコードだ。


// 2017/07/24 by marsee
//

#include <iostream>
#include "hls_opencv.h"
#include "straight_dataset_bmp.h"

int main(){
char straight_fn[256] = "straight";
char left_turn_fn[256] = "left_turn";
char right_turn_fn[256] = "right_turn";
char bmp_file[256];
cv::Rect rect_center(2, 33, 56, 10);

// refereed to http://opencv.jp/cookbook/opencv_img.html
// straight
for(int i=0; i<STRAIGHT_NUM_OF_IMAGE; i++){
sprintf(bmp_file, "%s%d.bmp", straight_fn, i);
cv::Mat straight_img = cv::imread(bmp_file,1);
if(straight_img.empty())
return(-1);
cv::Mat reduct_img(straight_img.rows*0.075, straight_img.cols*0.075, straight_img.type());
cv::resize(straight_img, reduct_img, reduct_img.size(), cv::INTER_LINEAR);
cv::Mat gray_img;
cv::cvtColor(reduct_img, gray_img, CV_BGR2GRAY);

sprintf(bmp_file, "%s_RED%d.bmp", straight_fn, i);
cv::imwrite(bmp_file, gray_img);

cv::Rect rect_center(2, 33, 56, 10);
cv::Mat img_rect(gray_img, rect_center);
sprintf(bmp_file, "%s_RED_rect%d.bmp", straight_fn, i);
cv::imwrite(bmp_file, img_rect);
}

return(0);
}


Vivado HLS 2017.2 の画面を示す。C シミュレーションが終了したところだ。
wlt_cnn_6_170801.png

60x45 に縮小した 0 番目の直進の画像を示す。
wlt_cnn_7_170801.png

60x45 に縮小した 9 番目の直進の画像を示す。
wlt_cnn_8_170801.png

60x45 の画像から白線の 60x14 の画像を切り出して、その真ん中の56x10 の画像を更に切り出した。これは 0 番目の画像から切り出した。
wlt_cnn_9_170801.png

60x45 の画像から白線の 60x14 の画像を切り出して、その真ん中の56x10 の画像を更に切り出した。これは 9 番目の画像から切り出した。
wlt_cnn_10_170801.png

大体うまく行っているかな?1 つの白線画像から 5x5 = 25 個のトレーニング用画像ができるはずだ。
  1. 2017年08月01日 05:09 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0