誤差逆伝搬法を実装してMNISTの学習と認識プログラムをC言語でフルスクラッチで作る、その続き。
固定小数点化については、他社の作ったライブラリを使うほうが良い気がして来たので、調査をしていると以下のライブラリを見つけた。MITの作った固定小数点ライブラリらしい。
整数部16ビット、小数部16ビットとなっており、筋は良さそうなライブラリだ。
このライブラリのありがたいところは、三角関数などの実装に加えて、指数関数の実装もされているところだ。
特にニューラルネットワークにおいてsoftmax関数はexp演算を多用する。このため、固定小数点演算ライブラリにexpが入っているのは非常にありがたいのだ。
libfixmathを使ってMNISTプログラムを固定小数点化する
実装自体は非常に簡単だ。まずはlibfixmathライブラリをcloneしてビルドしておく。ライブラリとしてlibfixmath.a
が出来るので、自分のプログラムのリンク時にコチラを呼び出しておけばよい。
浮動小数点からlibfixmathへの置き換えだが、まず固定小数点の型としてfix16_t
が定義されている。こちらを活用することになる。
- 固定値の代入
float a = 1.0; fix16_t b = fix16_from_dbl(1.0); // fix16_from_floatもある
- fix16_tから浮動小数点への変換
float f = fix16_to_float (fx16); float d = fix16_to_dbl (fx16);
- 演算
fix16_t fx16_add = fix16_add (fx16_a, fx16_b); // add = a + b; fix16_t fx16_mul = fix16_mul (fx16_a, fx16_b); // mul = a * b; fix16_t fx16_exp = fix16_exp (fx16_a); // exp = exp (a) madd = fix16_add (madd, fix16_mul (fx16_a, fx16_b)); // madd = madd + (a * b);
など、大抵の演算が実行可能だ。
これを用いて、MNISTのプログラムの固定小数点化を行った。
MNISTの認識精度
doubleでの演算、floatでの演算、fix16_t での演算でのMNISTの認識精度の比較を行った。
- double : 90.53%
- float : 90.25%
- fix16_t : 90.42%
全くそん色ない精度だ。特に実装の問題はないと思われる。ただし、問題はその実行速度だ。何故かfix16_tを使うと非常に遅くなってしまった。
これは、今後解析を行っていくものとする。とりあえず、x86以外のマイコンやボードに、移植を行っていこうかな。