FC2カウンター FPGAの部屋 keras_compressor のモデルをVivado HLSで実装する5(model_raw.h5 の畳み込み層の重みをCヘッダに変換)
FC2ブログ

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

FPGAの部屋

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

keras_compressor のモデルをVivado HLSで実装する5(model_raw.h5 の畳み込み層の重みをCヘッダに変換)

keras_compressor のモデルをVivado HLSで実装する4(model_raw.h5 全結合層第2層目)”の続き。

前回は、keras compressor のMNIST サンプルの model_raw.h5 の全結合層の第2層目を解析した。今回はいよいよ畳み込み層の重みとバイアスをC のヘッダに変換してみよう。
畳み込み層の重みをCヘッダファイルに書き出す関数 fwrite_conv_weight() を定義する。

# 畳み込み層の重みをCヘッダファイルに書き出す
# 2018/05/31 by marsee

def fwrite_conv_weight(weight, wfile_name, float_wt_name, fixed_wt_name, MAGNIFICATION):
    import datetime
    import numpy as np
    
    f = open(wfile_name, 'w')
    todaytime = datetime.datetime.today()
    f.write('// '+wfile_name+'\n')
    strdtime = todaytime.strftime("%Y/%m/%d %H:%M:%S")
    f.write('// {0} by marsee\n'.format(strdtime))
    f.write("\n")
    
    f.write('const float '+float_wt_name+'['+str(weight.shape[0])+']['+str(weight.shape[1])+']['+str(weight.shape[2])+']['+str(weight.shape[3])+'] = \n{\n')
    for i in range(weight.shape[0]):
        f.write("\t{\n")
        for j in range(weight.shape[1]):
            f.write("\t\t{\n")
            for k in range(weight.shape[2]):
                f.write("\t\t\t{")
                for m in range(weight.shape[3]):
                    f.write(str(weight[i][j][k][m]))
                    if (m==weight.shape[3]-1):
                        f.write("}")
                    else:
                        f.write(",")
                
                if (k==weight.shape[2]-1):
                    f.write("\n\t\t}\n")
                else:
                    f.write(",\n")

            if (j==weight.shape[1]-1):
                f.write("\t}\n")
            else:
                f.write(",\n")
        
        
        if (i==weight.shape[0]-1):
            f.write("};\n")
        else:
            f.write("\t,\n")

    f.write("\n")
    f.write('const ap_fixed<'+str(int(np.log2(MAGNIFICATION))+1)+', 1, AP_TRN, AP_WRAP> '+fixed_wt_name+'['+str(weight.shape[0])+']['+str(weight.shape[1])+']['+str(weight.shape[2])+']['+str(weight.shape[3])+'] = \n{\n')
    for i in range(weight.shape[0]):
        f.write("\t{\n")
        for j in range(weight.shape[1]):
            f.write("\t\t{\n")
            for k in range(weight.shape[2]):
                f.write("\t\t\t{")
                for m in range(weight.shape[3]):
                    w_int = int(weight[i][j][k][m]*MAGNIFICATION+0.5)
                    if (w_int > MAGNIFICATION-1):
                        w_int = MAGNIFICATION-1
                    elif (w_int < -MAGNIFICATION):
                        w_int = -MAGNIFICATION
                    f.write(str(float(w_int)/float(MAGNIFICATION)))
                    if (m==weight.shape[3]-1):
                        f.write("}")
                    else:
                        f.write(",")
                
                if (k==weight.shape[2]-1):
                    f.write("\n\t\t}\n")
                else:
                     f.write(",\n")

            if (j==weight.shape[1]-1):
                f.write("\t}\n")
            else:
                f.write(",\n")
        
        
        if (i==weight.shape[0]-1):
            f.write("};\n")
        else:
            f.write("\t,\n")
 
    f.close()


この関数を使うためには配列の順番がKeras と異なるので、順番を入れ替える。
第1層目の畳み込み層の重みを出力した。重みのビット数は9ビットで整数部 1 ビット(つまり+とー)と小数部 8 ビットだ。

# 2018/06/05 修正 畳み込み層の重みの配列は(カーネルサイズh,カーネルサイズw, 入力チャネル, 出力チャネル)ということなので、Pythonコードを修正した。@NORA__0013 さんありがとうございました。
# 畳み込み層第1層目
MAGNIFICATION_CONV = 2 ** (9-1)
fwrite_conv_weight(conv_layer_weight.transpose(3,2,0,1), 'conv1_weight.h', 'conv1_fweight', 'conv1_weight', MAGNIFICATION_CONV)


conv1_weight.h を示す。
keras_compressor_56_190308.png

第2層目の畳み込み層の重みを出力した。

# 畳み込み層第2層目
MAGNIFICATION_CONV = 2 ** (9-1)
fwrite_conv_weight(conv_layer2_weight.transpose(3,2,0,1), 'conv2_weight.h', 'conv2_fweight', 'conv2_weight', MAGNIFICATION_CONV)



conv2_weight.h を示す。
keras_compressor_57_190308.png

次に、バイアスをC のヘッダとして出力する関数 fwrite_bias() を示す。

# 畳み込み層と全結合層のバイアスをCヘッダファイルに書き出す
# 2018/05/31 by marsee

def fwrite_bias(bias, wfile_name, float_b_name, fixed_wt_name, MAGNIFICATION):
    import datetime
    import numpy as np
    
    f = open(wfile_name, 'w')
    todaytime = datetime.datetime.today()
    f.write('// '+wfile_name+'\n')
    strdtime = todaytime.strftime("%Y/%m/%d %H:%M:%S")
    f.write('// {0} by marsee\n'.format(strdtime))
    f.write("\n")

    f.write('const float '+float_b_name+'['+str(bias.shape[0])+'] = {\n\t')
    for i in range(bias.shape[0]):
        f.write(str(bias[i]))
        if (i < bias.shape[0]-1):
            f.write(", ")
    f.write("\n};\n")

    f.write("\n")
    f.write('const ap_fixed<'+str(int(np.log2(MAGNIFICATION))+1)+', 1, AP_TRN, AP_WRAP> '+fixed_wt_name+'['+str(bias.shape[0])+'] = {\n\t')
    for i in range(bias.shape[0]):
        b_int = int(bias[i]*MAGNIFICATION+0.5)
        if (b_int > MAGNIFICATION-1):
            b_int = MAGNIFICATION-1
        elif (b_int < -MAGNIFICATION):
            b_int = -MAGNIFICATION
        f.write(str(float(b_int)/float(MAGNIFICATION)))
        if (i < bias.shape[0]-1):
            f.write(", ")
    f.write("\n};\n")

    f.close()


畳み込み層第1層目のバイアスを出力する。
バイアスの精度は、重みと同様にビット数は9ビットで整数部 1 ビット(つまり+とー)と小数部 8 ビットだ。

fwrite_bias(conv_layer_bias, 'conv1_bias.h', 'conv1_fbias', 'conv1_bias', MAGNIFICATION_CONV)


conv1_bias.h を示す。
keras_compressor_58_190308.png

畳み込み層第2層目のバイアスを出力する。

fwrite_bias(conv_layer2_bias, 'conv2_bias.h', 'conv2_fbias', 'conv2_bias', MAGNIFICATION_CONV)


conv2_bias.h を示す。
keras_compressor_59_190308.png

畳み込み層の重みをバイアスをC ヘッダに変換することができた。
  1. 2019年03月09日 16:35 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック URL
http://marsee101.blog.fc2.com/tb.php/4466-84521ae1
この記事にトラックバックする(FC2ブログユーザー)