LoginSignup
35
38

More than 5 years have passed since last update.

FPGA上で動くニューラルネットワーク・ジェネレータを作った

Last updated at Posted at 2016-09-04

概要

FPGA上で動くNeuralNetworkジェネレータを作りました.

機能

  • FeedForwardニューラルネットワークが製作可能
  • 出力は0,1のみ
  • VerilogHDLで出力
  • 非同期回路(クロックに依存しない)
  • 任意bit幅の固定小数に対応
  • 活性化関数はシグマ関数
  • 推論のみ(学習はできない)

リポジトリはここ
https://github.com/kotauchisunsun/NN_FPGA

動作環境

  • Python 2.7以上3未満
  • Icarus Verilog

Python2.7はジェネレータに必須ですが,Icurus Verilogはシミュレーションしなければ必須ではありません.特にライブラリは必要とせず,Python標準ライブラリのみで動きます.

ライセンス

Affero GPL v3

使い方

NeuralNetworkの構造部分
基本文法は

$ python script/main.py width input_num structure output_num

width : 小数のbit幅
input_num : 入力信号の数
structure : ネットワーク構造を示す.カンマ区切りで多段構造を表現することができる(後述)
output_num : 出力信号の数

例)

$ python script/main.py 16 2 2 2
> NN_NL_016_0002_0002_NL_016_0002_0002
> saved to generate.v
> None

これにより,generate.vの中に16bitの小数で動くNN_NL_016_0002_0002_NL_016_0002_0002というニューラルネットが構築されます.
これは下の図のようなニューラルネットを表します.
image

それぞれの意味は
input* : 入力
output* : 出力
w* : 入力に対する重み係数
b* : ニューラルネットのバイアス

例えば左上のニューラルネットワークが発火する条件は

if input1 * w1 + input2 * w3 + b1 > 0:
    return 1
else:
    return 0

となっています.

また,NN_NL_016_0002_0002_NL_016_0002_0002に渡される引数の順番ですが,
1. input*
2. w*
3. b*
4. output*
の順番です.
したがって,この場合を全部書き下すと

input1,input2,w1,w2,w3,w4,w5,w6,w7,w8,b1,b2,b3,b4,ouput1,output2

となっています.
これによりニューラルネットワークが推論された結果が,output1,output2に入ります.

また,このmain.pyは多段のニューラルネットワークを構築することも可能で,

$ python main.py 16 32 64,32,48 16

とすると,16bit幅の小数を扱うことができる,

ニューラルネットのユニット数
入力層 32
隠れ層1 64
隠れ層2 32
隠れ層3 48
出力層 16

というニューラルネットワークを構成することができます.

小数表現

今回のニューラルネットワークは一般的に使われる浮動小数点に対応していません.
そのため,重み係数や,入力を代入するにはひと手間かかります.

小数の仕様は以下のようになっています.
width = 16の場合
1~8bit: 小数部 それぞれのbitが2^(-8+i-1)を表す.(C)
9~15bit: 整数部 それぞれのbitが2^(i-8-1)を表す.(N)
16bit: 負の数のフラグ.(F)

bit 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
意味 F N N N N N N N C C C C C C C C

となっています.width/2までのbitが小数部,トップのbitが負の数のフラグ,それ以外が整数部となっています.

これだけ聞くとややこしいので,スクリプトを用意しました.
`
$ python script/convert_number.py width number

width: 小数のbit幅
number: 変換したい値

例:

$ python script/convert_number.py 16 5.5
> 16b'0000010110000000
> ABS ERROR = 0.000000e+00

これにより,16bitの小数で5.5を表現したとき,16b'0000010110000000となることが分かります.
Verilogで構築する際にはこの値を入れれば大丈夫なことが分かります.
ここで,ABS ERRORは小数表現したときの誤差となります.10進数の小数を16bitの2進数で表したとき,どれくらい絶対誤差が生まれるかを10進法表現しています.

例:

$ python script/convert_number.py 16 -1.1
> 16b'1111111011100111
> ABS ERROR = 2.343750e-03

-1.1を16bitの固定小数で表した場合,ABS ERROR = 2.343750e-03となっているので,誤差があることが分かります.そこで,32bitの固定小数で表すと,

例:

$ python script/convert_number.py 32 -1.1
> 32b'11111111111111101110011001100111
> ABS ERROR = 9.155273e-06

ABS ERROR = 9.155273e-06となり,16bitで表現したときと比べ,誤差が減っていることが分かります.bit幅を大きくとると精度は上がりますが,回路規模が大きくなりFPGA上で動かなくなるので,バランスをとりながらチューニングしてください.

終わりに

VerilogHDLとFPGAを始めて4カ月の拙作です.バグや間違い,拡張の方針等ありましたらご助言いただけると幸いです.

35
38
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
35
38