Генерация кода для квантованных нейронных сетей для глубокого обучения

Глубокое обучение использует архитектуры нейронной сети, которые содержат много слоев обработки, включая сверточные слои. Модели глубокого обучения обычно работают над большими наборами маркированных данных. Обучение эти модели и выполняющий вывод в вычислительном отношении интенсивно, используя существенное количество памяти. Нейронные сети используют память, чтобы сохранить входные данные, параметры (веса) и активации от каждого слоя, когда вход распространяет через сеть. Большинство предварительно обученных нейронных сетей и нейронных сетей, обученных при помощи Deep Learning Toolbox™, использует типы данных с плавающей запятой с одинарной точностью. Даже сети, которые малы в размере, требуют, чтобы значительный объем памяти и оборудование выполнили эти арифметические операции с плавающей точкой. Эти ограничения могут запретить развертывание моделей глубокого обучения к устройствам, которые имеют низкую вычислительную силу и меньшие ресурсы памяти. При помощи более низкой точности, чтобы сохранить веса и активации, можно уменьшать требования к памяти сети.

Можно использовать Deep Learning Toolbox в тандеме с пакетом поддержки Библиотеки Квантования Модели Deep Learning Toolbox, чтобы уменьшать объем потребляемой памяти глубокой нейронной сети путем квантования весов, смещений и активаций слоев свертки к 8-битным масштабированным целочисленным типам данных. Затем можно использовать GPU Coder™, чтобы сгенерировать оптимизированный CUDA®code для квантованной сети. Сгенерированный код использует в своих интересах библиотеку глубокой нейронной сети NVIDIA® CUDA (cuDNN) или высокоэффективную библиотеку вывода TensorRT™. сгенерированный код может быть интегрирован в ваш проект как исходный код, статические или динамические библиотеки или исполняемые файлы, что можно развернуть в разнообразие NVIDIA платформы графического процессора.

Пример: классифицируйте изображения Используя SqueezeNet

В этом примере вы используете GPU Coder, чтобы сгенерировать код CUDA для квантованной глубокой сверточной нейронной сети и классифицировать изображение. Пример использует предварительно обученный squeezenet сверточная нейронная сеть, чтобы продемонстрировать передачу обучения, квантование и генерацию кода CUDA для квантованной сети.

SqueezeNet был обучен на более чем миллионе изображений и может классифицировать изображения в 1 000 категорий объектов (таких как клавиатура, кофейная кружка, карандаш и многие животные). Сеть изучила богатые представления функции для широкого спектра изображений. Сеть берет изображение в качестве входа и выводит метку для объекта в изображении вместе с вероятностями для каждой из категорий объектов.

Дополнительные требования

  1. Deep Learning Toolbox.

  2. Модель Deep Learning Toolbox для пакета Сетевой поддержки SqueezeNet.

  3. Интерфейс GPU Coder для Библиотек Глубокого обучения поддерживает пакет.

  4. Библиотека Квантования Модели Deep Learning Toolbox поддерживает пакет. Чтобы установить пакеты поддержки, выберите пакет поддержки из меню MATLAB® Add-Ons.

  5. Инструментарий CUDA и cuDNN библиотеки. Для получения информации о поддерживаемых версиях компиляторов и библиотек, смотрите Устанавливающие Необходимые как условие продукты.

  6. Переменные окружения для компиляторов и библиотек. Для получения дополнительной информации смотрите Переменные окружения.

Передача обучения Используя SqueezeNet

Чтобы выполнить классификацию на новом наборе изображений, вы подстраиваете предварительно обученную сверточную нейронную сеть SqueezeNet, переводом учась. В передаче обучения можно взять предварительно обученную сеть и использовать ее в качестве начальной точки, чтобы изучить новую задачу. Подстройка сети с передачей обучения обычно намного быстрее и легче, чем обучение сети со случайным образом инициализированными весами с нуля. Можно быстро передать изученные функции новой задаче с помощью меньшего числа учебных изображений.

Загрузите обучающие данные

Разархивируйте и загрузите новые изображения как datastore изображений. imageDatastore функционируйте автоматически помечает изображения на основе имен папок и хранит данные как ImageDatastore объект. Datastore изображений позволяет вам сохранить большие данные изображения, включая данные, которые не умещаются в памяти, и эффективно считать пакеты изображений во время обучения сверточной нейронной сети. Разделите данные на наборы данных обучения и валидации. Используйте 70% изображений для обучения и 30% для валидации. splitEachLabel разделяет imds datastore в два новых хранилища данных.

unzip('MerchData.zip');
imds = imageDatastore('MerchData', ...
    'IncludeSubfolders',true, ...
    'LabelSource','foldernames');
[imdsTrain,imdsValidation] = splitEachLabel(imds,0.7,'randomized');

numTrainImages = numel(imdsTrain.Labels);
idx = randperm(numTrainImages,4);
img = imtile(imds, 'Frames', idx);

figure
imshow(img)
title('Random Images from Training Dataset');

Random images from the training dataset

Загрузите предварительно обученную сеть

  1. Загрузите предварительно обученную сеть SqueezeNet. Если у вас нет необходимых пакетов поддержки установленными, программное обеспечение обеспечивает ссылку на загрузку.

    net = squeezenet;
    

  2. Объект net содержит DAGNetwork объект. Первый слой, изображение ввело слой, требует входных изображений размера 227 227 3, где 3 количество цветовых каналов. Можно использовать analyzeNetwork функционируйте, чтобы отобразить интерактивную визуализацию сетевой архитектуры, обнаружить ошибки и проблемы в сети, и отобразить подробную информацию о слоях сети. Информация о слое включает размеры активаций слоя и настраиваемых параметров, общего количества настраиваемых параметров и размеров параметров состояния текущих слоев.

    inputSize = net.Layers(1).InputSize;
    analyzeNetwork(net);
    

Замените последние слои

  1. Сверточные слои сетевого извлечения отображают функции что последний learnable слой и итоговое использование слоя классификации, чтобы классифицировать входное изображение. Эти два слоя, 'conv10' and 'ClassificationLayer_predictions' в SqueezeNet содержите информацию о том, как сочетать функции, которые сеть извлекает в вероятности класса, значение потерь и предсказанные метки.

  2. Чтобы переобучить предварительно обученную сеть, чтобы классифицировать новые изображения, замените эти два слоя на новые слои, адаптированные к новому набору данных. Можно сделать это вручную или использовать функцию помощника findLayersToReplace найти эти слои автоматически.

    lgraph = layerGraph(net); 
    [learnableLayer,classLayer] = findLayersToReplace(lgraph);
    numClasses = numel(categories(imdsTrain.Labels));
    
    newConvLayer =  convolution2dLayer([1, 1],numClasses,'WeightLearnRateFactor',...
    10,'BiasLearnRateFactor',10,"Name",'new_conv');
    lgraph = replaceLayer(lgraph,'conv10',newConvLayer);
    
    newClassificatonLayer = classificationLayer('Name','new_classoutput');
    lgraph = replaceLayer(lgraph,'ClassificationLayer_predictions',newClassificatonLayer);
    
  3. findLayersToReplace.m Функция помощника

     findLayersToReplace.m

Обучение сети

  1. Сеть требует входных изображений размера 227 227 3, но изображения в хранилищах данных изображений имеют различные размеры. Используйте увеличенный datastore изображений, чтобы автоматически изменить размер учебных изображений. Задайте дополнительные операции увеличения, чтобы выполнить на учебных изображениях: случайным образом инвертируйте учебные изображения вдоль вертикальной оси, и случайным образом переведите их до 30 пикселей горизонтально и вертикально. Увеличение данных помогает препятствовать тому, чтобы сеть сверхсоответствовала и запомнила точные детали учебных изображений.

    pixelRange = [-30 30];
    imageAugmenter = imageDataAugmenter( ...
        'RandXReflection',true, ...
        'RandXTranslation',pixelRange, ...
        'RandYTranslation',pixelRange);
    augimdsTrain = augmentedImageDatastore(inputSize(1:2),imdsTrain, ...
        'DataAugmentation',imageAugmenter);
  2. Чтобы автоматически изменить размер изображений валидации, не выполняя дальнейшее увеличение данных, используйте увеличенный datastore изображений, не задавая дополнительных операций предварительной обработки.

    augimdsValidation = augmentedImageDatastore(inputSize(1:2),imdsValidation);
    
  3. Задайте опции обучения. Для передачи обучения сохраните функции от ранних слоев предварительно обученной сети (переданные веса слоя). Чтобы замедлить изучение в переданных слоях, установите начальную скорость обучения на маленькое значение. На предыдущем шаге вы увеличили факторы скорости обучения для сверточного слоя, чтобы ускорить изучение в новых последних слоях. Эта комбинация настроек скорости обучения приводит к быстрому изучению только в новых слоях и более медленном изучении в других слоях. При использовании обучение с переносом вы не должны обучаться для как много эпох. Эпоха является полным учебным циклом на целом обучающем наборе данных. Задайте мини-пакетный размер, чтобы быть 11 так, чтобы в каждую эпоху вы рассмотрели все данные. Программное обеспечение подтверждает сеть каждый ValidationFrequency итерации во время обучения.

    options = trainingOptions('sgdm', ...
        'MiniBatchSize',11, ...
        'MaxEpochs',7, ...
        'InitialLearnRate',2e-4, ...
        'Shuffle','every-epoch', ...
        'ValidationData',augimdsValidation, ...
        'ValidationFrequency',3, ...
        'Verbose',false, ...
        'Plots','training-progress');
  4. Обучите сеть, которая состоит из переданных и новых слоев.

    netTransfer = trainNetwork(augimdsTrain,lgraph,options);
    classNames = netTransfer.Layers(end).Classes;
    save('mySqueezenet.mat','netTransfer');
    

Квантуйте сеть

  1. Создайте dlquantizer возразите и задайте сеть, чтобы квантовать.

    quantObj = dlquantizer(net);
  2. Задайте метрическую функцию, чтобы использовать, чтобы сравнить поведение сети до и после квантования. Сохраните эту функцию в локальном файле.

    function accuracy = hComputeModelAccuracy(predictionScores, net, dataStore)
    %% Computes model-level accuracy statistics
        
        % Load ground truth
        tmp = readall(dataStore);
        groundTruth = tmp.response;
        
        % Compare with predicted label with actual ground truth 
        predictionError = {};
        for idx=1:numel(groundTruth)
            [~, idy] = max(predictionScores(idx,:)); 
            yActual = net.Layers(end).Classes(idy);
            predictionError{end+1} = (yActual == groundTruth(idx)); %#ok
        end
        
        % Sum all prediction errors.
        predictionError = [predictionError{:}];
        accuracy = sum(predictionError)/numel(predictionError);
    end
  3. Задайте метрическую функцию в dlquantizationOptions объект.

    quantOpts = dlquantizationOptions('MetricFcn', ...
        {@(x)hComputeModelAccuracy(x,netTransfer,augimdsValidation)});
  4. Используйте calibrate функционируйте, чтобы осуществить сеть с демонстрационными входными параметрами и собрать информацию области значений. calibrate функционируйте осуществляет сеть и собирает динамические диапазоны весов и смещений в свертке и полносвязных слоях сети и динамические диапазоны активаций во всех слоях сети. Функция возвращает таблицу. Каждая строка таблицы содержит информацию об области значений для настраиваемого параметра оптимизированной сети.

    calResults = calibrate(quantObj,augimdsTrain);
    save('squeezenetCalResults.mat','calResults');
    save('squeezenetQuantObj.mat','quantObj');
  5. Можно использовать validate функция, чтобы квантовать настраиваемые параметры в слоях свертки сети и осуществить сеть. Функция использует метрическую функцию, заданную в dlquantizationOptions объект сравнить результаты сети до и после квантования.

    valResults = validate(quantObj,augimdsValidation,quantOpts);
    

Создайте функцию точки входа

  1. Напишите функцию точки входа в MATLAB что:

    1. Использует coder.loadDeepLearningNetwork функционируйте, чтобы загрузить модель глубокого обучения и создать и настроить класс CNN. Для получения дополнительной информации смотрите Предварительно обученные сети Загрузки для Генерации кода.

    2. Вызовы predict предсказать ответы.

  2. Например:

    function out = predict_int8(netFile, in)
    
        persistent mynet;
        if isempty(mynet)
            net = coder.loadDeepLearningNetwork(netFile);
        end
        out = predict(mynet,in);
    end
    

    Постоянный объект mynet загружает DAGNetwork объект. В первом вызове функции точки входа постоянный объект создается и настраивается. На последующих вызовах функции тот же объект снова используется, чтобы вызвать predict на входных параметрах, избегая восстановления и перезагрузки сетевого объекта.

Генерация кода при помощи codegen

  1. Чтобы сконфигурировать настройки сборки, такие как имя выходного файла, местоположение и тип, вы создаете объекты настройки кодера. Чтобы создать объекты, используйте coder.gpuConfig функция. Например, при генерации MEX CUDA с помощью codegen команда, используйте cfg = coder.gpuConfig('mex');

  2. Чтобы задать параметры генерации кода для cuDNN, установите DeepLearningConfig свойство к coder.CuDNNConfig возразите, что вы создаете при помощи coder.DeepLearningConfig.

    cfg = coder.gpuConfig('mex');
    cfg.TargetLang = 'C++';
    cfg.GpuConfig.ComputeCapability = '6.1';
    cfg.DeepLearningConfig = coder.DeepLearningConfig('cudnn');
    cfg.DeepLearningConfig.AutoTuning = true;
    cfg.DeepLearningConfig.CalibrationResultFile = 'squeezenetQuantObj.mat';
    cfg.DeepLearningConfig.DataType = 'int8';
    

    Задайте местоположение MAT-файла, содержащего калибровочные данные.

    Задайте точность входа типа данных тензора к сети при помощи DataType свойство. Для 8-битного целого числа используйте 'int8'int8 точность требует, чтобы графический процессор CUDA с минимумом вычислил возможность 6,1. Используйте ComputeCapability свойство GpuConfig объект установить соответствующее вычисляет значение возможности.

  3. Запустите codegen команда. codegen команда генерирует код CUDA от predict_int8.m Функция точки входа MATLAB.

    codegen -config cfg -args {coder.Constant('mySqueezenet.mat'),...
    ones(inputSize} predict_int8 -d codegen_int8
    

  4. Когда генерация кода успешна, можно просмотреть получившийся отчет генерации кода путем нажатия на View Report в Окне Команды MATLAB. Отчет отображен в окне Report Viewer. Если генератор кода обнаруживает ошибки или предупреждения во время генерации кода, отчет описывает проблемы и обеспечивает ссылки на проблематичный код MATLAB. См. Отчеты Генерации кода (MATLAB Coder).

    Code generation successful: View report
    

Запустите сгенерированный MEX

  1. Изображение, которое вы хотите классифицировать, должно иметь тот же размер как входной размер сети. Считайте изображение, что вы хотите классифицировать и изменить размер его к входному размеру сети. Это изменение размеров немного изменяет соотношение сторон изображения.

    testImage = imread("MerchDataTest.jpg");
    testImage = imresize(testImage,inputSize(1:2));
    
  2. Вызов SqueezeNet предсказывает на входном изображении.

    predictScores(:,1) =  predict(netTransfer,testImage)';
    predictScores(:,2) = predict_int8_mex('mySqueezenet.mat',testImage);
    
  3. Отобразите предсказанные метки и их связанные вероятности как гистограмма.

    h = figure;
    h.Position(3) = 2*h.Position(3);
    ax1 = subplot(1,2,1);
    ax2 = subplot(1,2,2);
    
    image(ax1,testImage);
    barh(ax2,predictScores)
    xlabel(ax2,'Probability')
    yticklabels(ax2,classNames)
    ax2.XLim = [0 1.1];
    ax2.YAxisLocation = 'left';
    legend('Matlab Single','cuDNN 8-bit integer');
    sgtitle('Predictions using Squeezenet')
    

    Prediction outputs from the MATLAB and generated code. Input test image is
                MathWorks cube. Predicted result is MathWorks cube with 100% probability.

Смотрите также

Приложения

Функции

Объекты

Похожие темы