Этот пример показывает, как преобразовать модель классификации нейронной сети в Simulink™ в фиксированную точку с помощью Fixed-Point Tool и Lookup Table Optimizer. После преобразования можно сгенерировать код С с помощью Simulink Coder.
Используя Инструмент с Фиксированной Точкой (Fixed-Point Tool), можно преобразовать проект из плавающей точки в фиксированную точку. Используйте Lookup Table Optimizer, чтобы сгенерировать замены эффективной памяти интерполяционной таблицы для неограниченных функций, таких как exp
и log2
. Используя эти инструменты, этот пример показывает, как преобразовать обученную модель классификации нейронных сетей с плавающей точкой для использования встроенных эффективных типов данных с фиксированной точкой.
MNIST рукописный набор данных цифр является обычно используемым набором данных в области нейронных сетей. Для примера, показывающего простой способ создать двухслойную нейронную сеть с помощью этого набора данных, смотрите 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();
nntraintool('close');
После обучения сети используйте 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, щелкните правой кнопкой мыши Подсистему Function Fitting Neural Network и выберите 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 Activation на первом слое либо интерполяционной таблицей, либо реализацией 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 | 96 | 0 | 4 | 16 | 16 | EvenPow2Spacing | 7.812500e-03, 8.392944e-01 | | 2 | 160 | 0 | 8 | 16 | 16 | EvenPow2Spacing | 7.812500e-03, 7.229614e-01 | | 3 | 288 | 0 | 16 | 16 | 16 | EvenPow2Spacing | 7.812500e-03, 5.369873e-01 | | 4 | 544 | 0 | 32 | 16 | 16 | EvenPow2Spacing | 7.812500e-03, 2.825317e-01 | | 5 | 1056 | 0 | 64 | 16 | 16 | EvenPow2Spacing | 7.812500e-03, 8.178711e-02 | | 6 | 2080 | 0 | 128 | 16 | 16 | EvenPow2Spacing | 7.812500e-03, 2.331543e-02 | | 7 | 4128 | 1 | 256 | 16 | 16 | EvenPow2Spacing | 7.812500e-03, 5.981445e-03 | Best Solution | ID | Memory (bits) | Feasible | Table Size | Breakpoints WLs | TableData WL | BreakpointSpecification | Error(Max,Current) | | 7 | 4128 | 1 | 256 | 16 | 16 | EvenPow2Spacing | 7.812500e-03, 5.981445e-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 | 128 | 0 | 6 | 16 | 16 | EvenPow2Spacing | 7.812500e-03, 6.151613e-01 | | 2 | 208 | 0 | 11 | 16 | 16 | EvenPow2Spacing | 7.812500e-03, 4.098255e-01 | | 3 | 368 | 0 | 21 | 16 | 16 | EvenPow2Spacing | 7.812500e-03, 2.051429e-01 | | 4 | 688 | 0 | 41 | 16 | 16 | EvenPow2Spacing | 7.812500e-03, 7.796005e-02 | | 5 | 1328 | 0 | 81 | 16 | 16 | EvenPow2Spacing | 7.812500e-03, 2.451896e-02 | | 6 | 2608 | 1 | 161 | 16 | 16 | EvenPow2Spacing | 7.812500e-03, 6.907394e-03 | Best Solution | ID | Memory (bits) | Feasible | Table Size | Breakpoints WLs | TableData WL | BreakpointSpecification | Error(Max,Current) | | 6 | 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');
Чтобы сгенерировать код С, щелкните правой кнопкой мыши Подсистему Function Fitting Neural Network, выберите C/C++ Code > Build Subsystem
. При запросе настраиваемых параметров нажмите кнопку Build.