Глубокое обучение использует архитектуры нейронной сети, которые содержат много слоев обработки, включая сверточные слои. Модели глубокого обучения обычно работают над большими наборами маркированных данных. Обучение эти модели и выполняющий вывод в вычислительном отношении интенсивно, используя существенное количество памяти. Нейронные сети используют память, чтобы сохранить входные данные, параметры (веса) и активации от каждого слоя, когда вход распространяет через сеть. Большинство предварительно обученных нейронных сетей и нейронных сетей, обученных при помощи Deep Learning Toolbox™, использует типы данных с плавающей запятой с одинарной точностью. Даже сети, которые малы в размере, требуют, чтобы значительный объем памяти и оборудование выполнили эти арифметические операции с плавающей точкой. Эти ограничения могут запретить развертывание моделей глубокого обучения к устройствам, которые имеют низкую вычислительную силу и меньшие ресурсы памяти. При помощи более низкой точности, чтобы сохранить веса и активации, можно уменьшать требования к памяти сети.
Можно использовать Deep Learning Toolbox в тандеме с пакетом поддержки Библиотеки Квантования Модели Deep Learning Toolbox, чтобы уменьшать объем потребляемой памяти глубокой нейронной сети путем квантования весов, смещений и активаций слоев свертки к 8-битным масштабированным целочисленным типам данных. Затем можно использовать GPU Coder™, чтобы сгенерировать оптимизированный CUDA®code для квантованной сети. Сгенерированный код использует в своих интересах библиотеку глубокой нейронной сети NVIDIA® CUDA (cuDNN) или высокоэффективную библиотеку вывода TensorRT™. сгенерированный код может быть интегрирован в ваш проект как исходный код, статические или динамические библиотеки или исполняемые файлы, что можно развернуть в разнообразие NVIDIA платформы графического процессора.
В этом примере вы используете GPU Coder, чтобы сгенерировать код CUDA для квантованной глубокой сверточной нейронной сети и классифицировать изображение. Пример использует предварительно обученный squeezenet
сверточная нейронная сеть, чтобы продемонстрировать передачу обучения, квантование и генерацию кода CUDA для квантованной сети.
SqueezeNet был обучен на более чем миллионе изображений и может классифицировать изображения в 1 000 категорий объектов (таких как клавиатура, кофейная кружка, карандаш и многие животные). Сеть изучила богатые представления функции для широкого спектра изображений. Сеть берет изображение в качестве входа и выводит метку для объекта в изображении вместе с вероятностями для каждой из категорий объектов.
Deep Learning Toolbox.
Модель Deep Learning Toolbox для пакета Сетевой поддержки SqueezeNet.
Интерфейс GPU Coder для Библиотек Глубокого обучения поддерживает пакет.
Библиотека Квантования Модели Deep Learning Toolbox поддерживает пакет. Чтобы установить пакеты поддержки, выберите пакет поддержки из меню MATLAB® Add-Ons.
Инструментарий CUDA и cuDNN библиотеки. Для получения информации о поддерживаемых версиях компиляторов и библиотек, смотрите Устанавливающие Необходимые как условие продукты.
Переменные окружения для компиляторов и библиотек. Для получения дополнительной информации смотрите Переменные окружения.
Чтобы выполнить классификацию на новом наборе изображений, вы подстраиваете предварительно обученную сверточную нейронную сеть 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');
Загрузите предварительно обученную сеть SqueezeNet. Если у вас нет необходимых пакетов поддержки установленными, программное обеспечение обеспечивает ссылку на загрузку.
net = squeezenet;
Объект net
содержит DAGNetwork
объект. Первый слой, изображение ввело слой, требует входных изображений размера 227 227 3, где 3 количество цветовых каналов. Можно использовать analyzeNetwork
функционируйте, чтобы отобразить интерактивную визуализацию сетевой архитектуры, обнаружить ошибки и проблемы в сети, и отобразить подробную информацию о слоях сети. Информация о слое включает размеры активаций слоя и настраиваемых параметров, общего количества настраиваемых параметров и размеров параметров состояния текущих слоев.
inputSize = net.Layers(1).InputSize; analyzeNetwork(net);
Сверточные слои сетевого извлечения отображают функции что последний learnable слой и итоговое использование слоя классификации, чтобы классифицировать входное изображение. Эти два слоя, 'conv10'
and 'ClassificationLayer_predictions'
в SqueezeNet содержите информацию о том, как сочетать функции, которые сеть извлекает в вероятности класса, значение потерь и предсказанные метки.
Чтобы переобучить предварительно обученную сеть, чтобы классифицировать новые изображения, замените эти два слоя на новые слои, адаптированные к новому набору данных. Можно сделать это вручную или использовать функцию помощника 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);
findLayersToReplace.m
Функция помощника
Сеть требует входных изображений размера 227 227 3, но изображения в хранилищах данных изображений имеют различные размеры. Используйте увеличенный datastore изображений, чтобы автоматически изменить размер учебных изображений. Задайте дополнительные операции увеличения, чтобы выполнить на учебных изображениях: случайным образом инвертируйте учебные изображения вдоль вертикальной оси, и случайным образом переведите их до 30 пикселей горизонтально и вертикально. Увеличение данных помогает препятствовать тому, чтобы сеть сверхсоответствовала и запомнила точные детали учебных изображений.
pixelRange = [-30 30]; imageAugmenter = imageDataAugmenter( ... 'RandXReflection',true, ... 'RandXTranslation',pixelRange, ... 'RandYTranslation',pixelRange); augimdsTrain = augmentedImageDatastore(inputSize(1:2),imdsTrain, ... 'DataAugmentation',imageAugmenter);
Чтобы автоматически изменить размер изображений валидации, не выполняя дальнейшее увеличение данных, используйте увеличенный datastore изображений, не задавая дополнительных операций предварительной обработки.
augimdsValidation = augmentedImageDatastore(inputSize(1:2),imdsValidation);
Задайте опции обучения. Для передачи обучения сохраните функции от ранних слоев предварительно обученной сети (переданные веса слоя). Чтобы замедлить изучение в переданных слоях, установите начальную скорость обучения на маленькое значение. На предыдущем шаге вы увеличили факторы скорости обучения для сверточного слоя, чтобы ускорить изучение в новых последних слоях. Эта комбинация настроек скорости обучения приводит к быстрому изучению только в новых слоях и более медленном изучении в других слоях. При использовании обучение с переносом вы не должны обучаться для как много эпох. Эпоха является полным учебным циклом на целом обучающем наборе данных. Задайте мини-пакетный размер, чтобы быть 11 так, чтобы в каждую эпоху вы рассмотрели все данные. Программное обеспечение подтверждает сеть каждый ValidationFrequency
итерации во время обучения.
options = trainingOptions('sgdm', ... 'MiniBatchSize',11, ... 'MaxEpochs',7, ... 'InitialLearnRate',2e-4, ... 'Shuffle','every-epoch', ... 'ValidationData',augimdsValidation, ... 'ValidationFrequency',3, ... 'Verbose',false, ... 'Plots','training-progress');
Обучите сеть, которая состоит из переданных и новых слоев.
netTransfer = trainNetwork(augimdsTrain,lgraph,options); classNames = netTransfer.Layers(end).Classes; save('mySqueezenet.mat','netTransfer');
Создайте dlquantizer
возразите и задайте сеть, чтобы квантовать.
quantObj = dlquantizer(net);
Задайте метрическую функцию, чтобы использовать, чтобы сравнить поведение сети до и после квантования. Сохраните эту функцию в локальном файле.
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
Задайте метрическую функцию в dlquantizationOptions
объект.
quantOpts = dlquantizationOptions('MetricFcn', ... {@(x)hComputeModelAccuracy(x,netTransfer,augimdsValidation)});
Используйте calibrate
функционируйте, чтобы осуществить сеть с демонстрационными входными параметрами и собрать информацию области значений. calibrate
функционируйте осуществляет сеть и собирает динамические диапазоны весов и смещений в свертке и полносвязных слоях сети и динамические диапазоны активаций во всех слоях сети. Функция возвращает таблицу. Каждая строка таблицы содержит информацию об области значений для настраиваемого параметра оптимизированной сети.
calResults = calibrate(quantObj,augimdsTrain); save('squeezenetCalResults.mat','calResults'); save('squeezenetQuantObj.mat','quantObj');
Можно использовать validate
функция, чтобы квантовать настраиваемые параметры в слоях свертки сети и осуществить сеть. Функция использует метрическую функцию, заданную в dlquantizationOptions
объект сравнить результаты сети до и после квантования.
valResults = validate(quantObj,augimdsValidation,quantOpts);
Напишите функцию точки входа в MATLAB что:
Использует coder.loadDeepLearningNetwork
функционируйте, чтобы загрузить модель глубокого обучения и создать и настроить класс CNN. Для получения дополнительной информации смотрите Предварительно обученные сети Загрузки для Генерации кода.
Вызовы predict
предсказать ответы.
Например:
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
Чтобы сконфигурировать настройки сборки, такие как имя выходного файла, местоположение и тип, вы создаете объекты настройки кодера. Чтобы создать объекты, используйте coder.gpuConfig
функция. Например, при генерации MEX CUDA с помощью codegen
команда, используйте cfg = coder.gpuConfig('mex');
Чтобы задать параметры генерации кода для 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
объект установить соответствующее вычисляет значение возможности.
Запустите codegen
команда. codegen
команда генерирует код CUDA от predict_int8.m
Функция точки входа MATLAB.
codegen -config cfg -args {coder.Constant('mySqueezenet.mat'),... ones(inputSize} predict_int8 -d codegen_int8
Когда генерация кода успешна, можно просмотреть получившийся отчет генерации кода путем нажатия на View Report в Окне Команды MATLAB. Отчет отображен в окне Report Viewer. Если генератор кода обнаруживает ошибки или предупреждения во время генерации кода, отчет описывает проблемы и обеспечивает ссылки на проблематичный код MATLAB. См. Отчеты Генерации кода (MATLAB Coder).
Code generation successful: View report
Изображение, которое вы хотите классифицировать, должно иметь тот же размер как входной размер сети. Считайте изображение, что вы хотите классифицировать и изменить размер его к входному размеру сети. Это изменение размеров немного изменяет соотношение сторон изображения.
testImage = imread("MerchDataTest.jpg");
testImage = imresize(testImage,inputSize(1:2));
Вызов SqueezeNet предсказывает на входном изображении.
predictScores(:,1) = predict(netTransfer,testImage)';
predictScores(:,2) = predict_int8_mex('mySqueezenet.mat',testImage);
Отобразите предсказанные метки и их связанные вероятности как гистограмма.
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')
calibrate
| codegen
| coder.loadDeepLearningNetwork
| dlquantizationOptions
| dlquantizer
| validate