数字認識ニューラル ネットワークの固定小数点への変換と C コードの生成
この例では、固定小数点ツールとルックアップ テーブル オプティマイザーを使用して Simulink™ のニューラル ネットワーク分類モデルを固定小数点に変換する方法を示します。変換後、Simulink Coder を使用して C コードを生成できます。
概要
固定小数点ツールを使用して、設計を浮動小数点から固定小数点へ変換できます。ルックアップ テーブル オプティマイザーを使用して、exp
や log2
などの境界がない関数に対してメモリ効率が高いルックアップ テーブル置換を生成します。この例では、これらのツールを使用して、学習済みの浮動小数点ニューラル ネットワークの分類モデルを変換し、組み込み効率の良い固定小数点データ型を使用します。
数字分類と MNIST データセット
MNIST の手書き数字データセットは、ニューラル ネットワークの分野でよく使用されるデータセットです。このデータセットを使用して 2 階層のニューラル ネットワークを簡単に作成する方法を示す例については、"Artificial Neural Networks for Beginners" を参照してください。
データとニューラル ネットワークの学習
"Artificial Neural Networks for Beginners" の指示に従って、MNIST の学習ファイルとテスト ファイルをダウンロードします。データを読み込み、ネットワークに学習させます。
%Load Data tr = csvread('train.csv', 1, 0); % read train.csv sub = csvread('test.csv', 1, 0); % read test.csv % Prepare Data n = size(tr, 1); % number of samples in the dataset targets = tr(:,1); % 1st column is |label| targets(targets == 0) = 10; % use '10' to present '0' targetsd = dummyvar(targets); % convert label into a dummy variable inputs = tr(:,2:end); % the rest of columns are predictors inputs = inputs'; % transpose input targets = targets'; % transpose target targetsd = targetsd'; % transpose dummy variable rng(1); % for reproducibility c = cvpartition(n,'Holdout',n/3); % hold out 1/3 of the dataset Xtrain = inputs(:, training(c)); % 2/3 of the input for training Ytrain = targetsd(:, training(c)); % 2/3 of the target for training Xtest = inputs(:, test(c)); % 1/3 of the input for testing Ytest = targets(test(c)); % 1/3 of the target for testing Ytestd = targetsd(:, test(c)); % 1/3 of the dummy variable for testing % Train Network hiddenLayerSize = 100; net = patternnet(hiddenLayerSize); [net, tr] = train(net, Xtrain, Ytrain); view(net); outputs = net(Xtest); errors = gsubtract(Ytest, outputs); performance = perform(net, Ytest, outputs); figure, plotperform(tr);
ネットワークのビューを閉じます。
nnet.guis.closeAllViews();
固定小数点の変換のためのモデルの準備
ネットワークに学習させた後、Deep Learning Toolbox™ から関数 gensim
を使用して Simulink モデルを生成します。
sys_name = gensim(net, 'Name', 'mTrainedNN');
関数 gensim
で生成されたモデルには、重みとバイアスを学習したニューラル ネットワークが含まれます。ネットワークの出力で信号のログを有効にし、入力スティミュラスと検証ブロックを追加して、学習したニューラル ネットワークを固定小数点に変換できるよう準備します。変更されたモデルは fxpdemo_mnist_classification
です。
モデルを開いて検証します。
model = 'fxpdemo_mnist_classification'; system_under_design = [model '/Pattern Recognition Neural Network']; baseline_output = [model '/yarr']; open_system(model);
固定小数点ツールを開くには Function Fitting Neural Network サブシステムを右クリックし、[固定小数点ツール] を選択します。または固定小数点ツールのコマンド ライン インターフェイスを使用します。固定小数点ツールとそのコマンド ライン インターフェイスを使用してモデルを変換用に準備し、システムを固定小数点に変換できます。また固定小数点ツールを使用して、シミュレーションと範囲解析によりオブジェクトの範囲とオーバーフローのインストルメンテーションを収集できます。この例では、固定小数点ツールのコマンド ライン インターフェイスを使用してニューラル ネットワークを固定小数点に変換します。
converter = DataTypeWorkflow.Converter(system_under_design);
範囲を収集するためのシミュレーションの実行
範囲を収集するインストルメンテーションでモデルをシミュレーションします。このバリアント コンフィギュレーションは、'Range collection using double override'
ショートカットを使用してシミュレートできます。後の手順で使用するシミュレーション実行名を保存します。
converter.applySettingsFromShortcut('Range collection using double override');
collect_ranges = converter.CurrentRunName;
sim_out = converter.simulateSystem();
変換前に適切な分類レートをプロットし、ベースラインの動作を確立します。
plotConfusionMatrix(sim_out, baseline_output, system_under_design, 'Classification rate before conversion');
固定小数点データ型の推奨
固定小数点ツールはシミュレーションから得られた範囲情報を使用して、設計対象システムのブロックの固定小数点データ型を推奨します。この例では、サブシステム内のすべてのブロックに対して符号付きデータ型が推奨されるように、ProposalSettings
オブジェクトで ProposeSignedness
オプションを無効にします。
ps = DataTypeWorkflow.ProposalSettings; converter.proposeDataTypes(collect_ranges, ps);
推奨されたデータ型の適用
既定では、固定小数点ツールはすべての推奨されたデータ型を適用します。applyDataTypes
メソッドを使用してデータ型を適用します。推奨のサブセットの適用のみ実行するには、固定小数点ツールで [確定] チェック ボックスを使用して、適用する推奨を指定します。
converter.applyDataTypes(collect_ranges);
データ型の検証
推奨された型は考えられるすべての入力を正しく処理する必要があります。新たに適用された型を使用してシミュレーションするモデルを設定し、ニューラル ネットワークの回帰精度が変換後も保持されているか確認します。
converter.applySettingsFromShortcut('Range collection with specified data types');
sim_out = converter.simulateSystem();
固定小数点モデルの適切な分類レートをプロットします。
plotConfusionMatrix(sim_out, baseline_output, system_under_design, 'Classification rate after fixed-point conversion');
活性化関数と最適化されたルックアップ テーブルとの置き換え
より効率的なコードにするために、第 1 層の活性化関数 Tanh をルックアップ テーブルまたは CORDIC 実装で置き換えます。この例では、ルックアップ テーブル オプティマイザーを使用してルックアップ テーブルを取得し tanh
を置き換えます。この例では、実行速度を上げるためにブレークポイント間隔に EvenPow2Spacing
を指定します。
block_path = [system_under_design '/Layer 1/tansig']; p = FunctionApproximation.Problem(block_path); p.Options.WordLengths = 16; p.Options.BreakpointSpecification = 'EvenPow2Spacing'; solution = p.solve; solution.replaceWithApproximate;
| ID | Memory (bits) | Feasible | Table Size | Breakpoints WLs | TableData WL | BreakpointSpecification | Error(Max,Current) | | 0 | 64 | 0 | 2 | 16 | 16 | EvenPow2Spacing | 7.812500e-03, 1.000000e+00 | | 1 | 8224 | 1 | 512 | 16 | 16 | EvenPow2Spacing | 7.812500e-03, 1.525879e-03 | | 2 | 4128 | 1 | 256 | 16 | 16 | EvenPow2Spacing | 7.812500e-03, 5.981445e-03 | | 3 | 2080 | 0 | 128 | 16 | 16 | EvenPow2Spacing | 7.812500e-03, 2.331543e-02 | Best Solution | ID | Memory (bits) | Feasible | Table Size | Breakpoints WLs | TableData WL | BreakpointSpecification | Error(Max,Current) | | 2 | 4128 | 1 | 256 | 16 | 16 | EvenPow2Spacing | 7.812500e-03, 5.981445e-03 |
同じ手順に従って第 2 層のソフトマックス実装の関数 exp
をルックアップ テーブルで置き換えます。
block_path = [system_under_design '/Layer 2/softmax/Exp']; p = FunctionApproximation.Problem(block_path); p.Options.WordLengths = 16; p.Options.BreakpointSpecification = 'EvenPow2Spacing';
最適化されたルックアップ テーブルを取得するには、入力に対して下限と上限の有限な範囲を定義します。
p.InputLowerBounds = -40; p.InputUpperBounds = 0; solution = p.solve; solution.replaceWithApproximate;
| ID | Memory (bits) | Feasible | Table Size | Breakpoints WLs | TableData WL | BreakpointSpecification | Error(Max,Current) | | 0 | 64 | 0 | 2 | 16 | 16 | EvenPow2Spacing | 7.812500e-03, 9.996643e-01 | | 1 | 2608 | 1 | 161 | 16 | 16 | EvenPow2Spacing | 7.812500e-03, 6.907394e-03 | | 2 | 1328 | 0 | 81 | 16 | 16 | EvenPow2Spacing | 7.812500e-03, 2.451896e-02 | Best Solution | ID | Memory (bits) | Feasible | Table Size | Breakpoints WLs | TableData WL | BreakpointSpecification | Error(Max,Current) | | 1 | 2608 | 1 | 161 | 16 | 16 | EvenPow2Spacing | 7.812500e-03, 6.907394e-03 |
関数をルックアップ テーブルの近似と置き換えた後にモデルの精度を確認します。
converter.applySettingsFromShortcut(converter.ShortcutsForSelectedSystem{2});
sim_out = converter.simulateSystem;
plotConfusionMatrix(sim_out, baseline_output, system_under_design, 'Classification rate after function replacement');
C コードの生成
C コードを生成するには、Function Fitting Neural Network サブシステムを右クリックし、[C/C++ コード]、[サブシステムのビルド] を選択します。調整可能なパラメーターのプロンプトが表示されたら [ビルド] ボタンをクリックします。
参考文献
[1] LeCun, Y., C. Cortes, and C. J. C. Burges. "The MNIST Database of Handwritten Digits." http://yann.lecun.com/exdb/mnist/.