Преобразуйте нейронную сеть распознавания цифры в фиксированную точку и сгенерируйте код С

В этом примере показано, как преобразовать модель классификации нейронных сетей в Simulink™ к фиксированной точке с помощью Fixed-Point Tool и Lookup Table Optimizer. После преобразования можно сгенерировать код С с помощью Simulink Coder.

Обзор

Используя Fixed-Point Tool, можно преобразовать проект от плавающей точки до фиксированной точки. Используйте Lookup Table Optimizer, чтобы сгенерировать эффективные памятью замены интерполяционной таблицы для неограниченных функций, таких как exp и log2. Используя эти инструменты, этот пример показывает, как преобразовать обученную модель классификации нейронных сетей с плавающей точкой, чтобы использовать встроено-эффективные типы данных с фиксированной точкой.

Классификация цифр и набор данных MNIST

MNIST рукописный набор данных цифры является обычно используемым набором данных в области нейронных сетей. Для примера, показывающего простой способ создать 2D многоуровневую нейронную сеть с помощью этого набора данных, см. https://blogs.mathworks.com/loren/2015/08/04/artificial-neural-networks-for-beginners/

Сеть передачи данных и обучение нейронной сети

Загрузите данные и обучите сеть.

%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();

Подготовка модели к преобразованию фиксированной точки

После обучения сети используйте gensim функция от Deep Learning Toolbox™, чтобы сгенерировать модель 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);

Чтобы открыть Fixed-Point Tool, щелкните правой кнопкой по Функции, Соответствующей подсистеме Нейронной сети, и выберите Fixed-Point Tool. В качестве альтернативы используйте интерфейс командной строки Fixed-Point Tool. Инструмент Фиксированной точки и его интерфейс командной строки помогают вам подготовить свою модель к преобразованию и преобразовать вашу систему в фиксированную точку. Можно использовать Fixed-Point Tool, чтобы собрать область значений и инструментирование переполнения объектов в модели через анализ области значений и симуляцию. В этом примере используйте интерфейс командной строки Fixed-Point Tool, чтобы преобразовать нейронную сеть в фиксированную точку.

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');

Предложите типы данных с фиксированной точкой

Fixed-Point Tool использует информацию об области значений, полученную посредством симуляции, чтобы предложить типы данных с фиксированной точкой для блоков в системе в соответствии с проектом. В этом примере, чтобы гарантировать, что инструменты предлагают подписанные типы данных для всех блоков в подсистеме, отключают ProposeSignedness опция в ProposalSettings объект.

ps = DataTypeWorkflow.ProposalSettings;
converter.proposeDataTypes(collect_ranges, ps);

Примените предложенные типы данных

По умолчанию Fixed-Point Tool применяет все предложенные типы данных. Используйте applyDataTypes метод, чтобы применить типы данных. Если вы хотите только применить подмножество предложений в использовании Fixed-Point Tool флажок Accept, чтобы задать предложения, что вы хотите применяться.

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');

Замените функции активации на оптимизированную интерполяционную таблицу

Для более эффективного кода замените функцию Активации Tanh в первом слое или с интерполяционной таблицей или с реализацией CORDIC. В этом примере используйте Lookup Table Optimizer, чтобы заставить интерполяционную таблицу заменять 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 |          16416 |        1 |       1024 |              16 |           16 |         EvenPow2Spacing |     7.812500e-03, 4.272461e-04 |
|   2 |           8224 |        1 |        512 |              16 |           16 |         EvenPow2Spacing |     7.812500e-03, 1.525879e-03 |

Best Solution
|  ID |  Memory (bits) | Feasible | Table Size | Breakpoints WLs | TableData WL | BreakpointSpecification |             Error(Max,Current) |
|   2 |           8224 |        1 |        512 |              16 |           16 |         EvenPow2Spacing |     7.812500e-03, 1.525879e-03 |

Выполните те же шаги, чтобы заменить exp функция в softmax реализации во втором слое с интерполяционной таблицей.

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++ Code > Build Subsystem. Нажмите кнопку Build, когда запрошено настраиваемые параметры.