============== C++ API ============== 概要 ============== 本章ではC++のAPIについて触れます。 現時点では細かなドキュメントが用意できておらず、ソースを読み人のために 概要を掴む為の情報を記載します。 なお BinaryBrain のコードは namespace に bb という名称を持ちます。 モデルクラス ============== 基本クラス --------------------- すべてのレイヤーはModelクラスからの派生で生成されます。 Model(抽象クラス) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 抽象クラスは直接生成できませんが、各レイヤーの基礎となっており、操作を定義します。 以下のようなメソッドを備えます。 SendCommand() 文字列によって汎用的に各レイヤーの属性変更などを行えます。 階層的にサブレイヤーに伝播させることを目的としておりますが、送信先クラス名を指定することで、 特定のレイヤにのみコマンドを送ることも出来ます。 現在の主な用途として "binary true" のようなコマンドで、バイナリ活性層を有効にしたり、 "host_only" コマンドで、部分的に動作をCPU版に切り替えたりできます。 将来的には、部分的に学習時のパラメータ学習を固定したりなど、いろいろな設定を追加していくことを考えています。 文字列なので、自作レイヤーに独自コマンドを追加することも簡単です。 GetClassName() クラス名を取得します。SendCommand() で、コマンド送付先をクラス名で指定することが出来ます。 SetName() クラス名とは別にインスタンス個別に自由に名前設定が出来ます。生成時に固有の名前をつけておけば、 後から SendCommand() で、個別に属性変更コマンドが送れます。 GetParameters() 内部パラメータの参照を取得します。重み係数などが取得対象です。 内部パラメータを持った自作レイヤーを作成する場合に実装が必要になります。 GetGradients() 内部パラメータの勾配への参照を取得します。Backward時に値が計算され、主に Optimizer が利用します。 内部パラメータを持った自作レイヤーを作成する場合に実装が必要になります。 SetInputShape() 入力のデータ形状を指定します。戻り値は出力のデータ形状となります。 階層的にサブレイヤーに伝播させることを目的としており、各レイヤーを連結後に呼びさすことで内部パラメータのサイズが決定され初期化されます。 自作レイヤーを作成する場合には必ず実装が必要になります。 Forward() 前方伝播を行います。階層的にサブレイヤーも実行することを想定しています。 自作レイヤーを作成する場合には必ず実装が必要になります。 Backward() 誤差逆伝播を行います。階層的にサブレイヤーも実行することを想定しています。 自作レイヤーを作成する場合には必ず実装が必要になります。 PrintInfo() レイヤーの情報を表示します。 自作レイヤーを作成する場合に実装しておけば独自の情報を出力できます。 活性化層 ------------------- Binarize クラス ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ バイナライズ層です。 Forward では、0を閾値に出力を0と1に二値化します。 Backward では hard-tanh として動作します。 バイナリネットワークの基礎となります。 ReLU クラス ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 普通のReLU です。 Binarize から派生しており、SendCommand() にて、"binary true" を送ることでBinarize層として動作します。 Sigmoid クラス ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 普通のSigmoid です。 Binarize から派生しており、SendCommand() にて、"binary true" を送ることでBinarize層として動作します。 演算層 ---------------------- StochasticLutN クラス ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LUT-Network の LUT に相当する部分をStochasticモデルに基づいて学習させるためのレイヤーです。 Stochastic計算に基づいてFPGAのLUTロジックを微分可能記述に直して、テーブル内容の逆伝搬学習を可能としています。 StochasticバイナリデータがStochastic性を持っている対象への学習に限定されますが、 DifferentiableLutN モデルよりも高速に学習させることが可能です。 このモデルは1層でXORパターンを含めたLUTで表現可能な空間すべてを学習可能です。 DifferentiableLutN クラス ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LUT-Network の LUT に相当する部分を独自のモデルで学習させるためのレイヤーです。 StochasticLutN クラスにさらに BatchNormalization と hard-tanh によるバイナリ化を 統合しています。 Stochastic性を持たない一般的なデータに対してバイナリネットワークとしての学習能力を持ちます。 このモデルも StochasticLutN 同様に1層でXORパターンを含めたLUTで表現可能な空間すべてを学習可能です。 一方で1つのノードの接続数がFPGA同様に6個などに限定されるため、疎結合網となり、ネットワークの構築には工夫が必要です。 MicroMlpAffine クラス ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ MicroMlp の構成要素で、入力数を6などに限定した疎結合、且つ、内部に隠れ層を備えた 小さなMLP(Multi Layer Perceptron)の集合体です。 入力数や隠れ層の数テンプレート引数で変更可能です。 MicroMlp クラス ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LUT-Network の LUT に相当する部分をパーセプトロンを用いて学習させるレイヤーです。 内部は MicroMlpAffine + BatchNormalization + 活性化層 の3層で構成されます。 活性化層 は デフォルトは ReLU ですが、テンプレート引数で変更可能です。 DenseAffine クラス ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ いわゆる普通の浮動小数点による全結合のニューラルネットです。 BatchNormalization クラス ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ BatchNormalization層です。 活性化層でバイナリ化を行う前段ほぼ必須となってくる層です。 MaxPooling クラス ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ MaxPooling層です。 LutLayer (抽象クラス) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LUT-Network を記述する基本モデルです。 現在 ver2 の直接学習機能はまだ ver3 には未実装です。 MicroMlp などで逆伝播で学習した内容をテーブル化して写し取ることを目的としています。 テーブル化取り込みに ImportLayer() メソッドを備えます。 BinaryLutN クラス ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 各ノードの入力数を1つに固定したLUTモデルです。一般的なFPGAに適合します。 入力数はテンプレート引数で指定でき、FPGAでは 4 か 6 のものが一般的と思われます。 入力数を固定することで演算を高速化できますが、ver3 への移植はまだ行えていません。 補助層 -------------- Sequential クラス ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 各種の層を直列に接続して1つの層として扱えるようにします。 Convolution2d クラス ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Lowering を行い畳こみ演算を行います。 ConvolutionIm2Col + 引数で渡したモデル + ConvolutionCol2Im DenseAffine を渡すと、通常のCNNになり、MicroMlp を用いたサブネットワークを渡すことで、 LUT-Network での畳込みが可能です。 ConvolutionIm2 クラス ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 畳み込みの為のLoweringを行います。通常、 Convolution2d クラス の中で利用されます。 Loweringされたデータに対して BatchNormalization するのも LUT-Network 学習時の特徴の一つかもしれません。 ConvolutionCol2Im クラス ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 畳み込みの為のLoweringの復元を行います。通常、 Convolution2d クラス の中で利用されます。 BinaryModulation クラス ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 内部でRealToBinary クラスとBinaryToRealクラスを組み合わせて、多値データをバイナリ化して学習するのに利用できます。 RealToBinary クラス ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 実数値をバイナライズします。 その際にframe方向に拡張して変調を掛ける(多重化)が可能です。 現在、PWM変調と、乱数での変調を実装しており、デフォルトでPWM変調となります(将来⊿Σなどの誤差蓄積機能も検討中です)。 変調を行うことで、入力値に対して確率的な0/1比率の値を生成できるため、出力も確率的なものとなります。 BinaryToReal クラス ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 多重化された確率的な0と1をカウンティングして実数値を生成します。 RealToBinary 対応しますが、こちらは時間方向だけでなく、空間方向のカウントも可能です。 オーバーサンプリングによる十分な多重化数が確保できれば、回路規模を増加させること無く回帰などの実数値へのフィッティング可能性が出てきます。 モデル以外のクラス ======================= 損失関数 ------------------------- LossSoftmaxCrossEntropy クラス ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 普通のSoftmax-CrossEntropyクラスです。 LossMeanSquaredError クラス ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 平均二乗誤差を損失とするクラスです。 評価関数 -------------- MetricsCategoricalAccuracy クラス ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Categorical Classification の精度を評価値とするクラスです。 MetricsMeanSquaredError クラス ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ MSE(平均二乗誤差)を評価値とするクラスです。 最適化(Optimizer) ----------------------- OptimizerSgd クラス ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 普通のSGDです。 OptimizerAdam クラス ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 普通のAdamです。 実行補助 ------------------ Runner クラス ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 構築したモデルのフィッティングや評価などの実行を補助します。 論よりRUN。 Runner のソースが各種の使い方で、参考になるはずです。 データ保持 ---------------------- Tensor クラス ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 多次元のデータを保持できるクラスで、演算も可能です。 名前に反してまだ Tensor演算は実装できていません。 Variables クラス ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 複数の Tensor を束ねる機能を持ったクラスです。 形状が同じなら Variables 間での演算も可能です。 主にOptimizerでの利用を想定しています。 FrameBuffer クラス ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1つの Tensor を 1 frame として、複数frame を保持できるクラスです。 ただし、内部では、NCHW や NHWC ではなく、CHWN 形式になるように並び替えてデータを保持しています。 これは Lowering されて frame数が十分増やされた疎行列に特化して性能を出すための配置で、BinaryBrainの特徴の一つです。 一方で、一般的な算術ライブラリに適合しない(並び替えが必要)ので注意が必要です。 各種関数 ============== FPGAへのエクスポート ------------------------- ExportVerilog_LutLayers 関数 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LutLayer を Verilog-RTL で出力します。 ExportVerilog_LutCnnLayersAxi4s 関数 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 畳み込み層を含む LutLayer を纏めて Verilog-RTL で出力します。 MaxPoolingなどの入出力でデータが不連続になる層は最後に1つだけ指定することができます。