Этот пример показывает, как квантовать обучаемые параметры в слоях свертки нейронной сети глубокого обучения, которая имеет остаточные связи и была обучена классификации изображения с CIFAR-10 данными.
Нейронные сети используют память для хранения входных данных, параметров (весов) и активаций от каждого уровня по мере распространения входных данных по сети. Большинство нейронных сетей, которые создаются и обучаются с помощью Deep Learning, Toolbox™ использовать типы данных с плавающей запятой с одной точностью. Даже небольшие сети требуют значительного объема памяти и оборудования для выполнения этих арифметических операций с плавающей запятой. Эти ограничения могут препятствовать развертыванию моделей глубокого обучения на устройствах с низкой вычислительной мощностью и меньшими ресурсами памяти. Использование более низкой точности для хранения весов и активизаций позволяет уменьшить требования к памяти сети.
В этом примере для уменьшения объема памяти глубокой нейронной сети путем квантования весов, смещений и активизаций слоев свертки до 8-битных масштабированных целочисленных типов данных используется инструментарий Deep Learning Toolbox совместно с пакетом поддержки библиотеки квантования модели Deep Learning Toolbox.
Сеть в этом примере обучена классификации изображений с CIFAR-10 данными.
Остаточные соединения являются популярным элементом в сверточных нейронных сетевых архитектурах. Остаточная сеть - это тип сети DAG, которая имеет остаточные (или короткие) соединения, которые обходят основные сетевые уровни. Остаточные соединения позволяют градиентам параметров легче распространяться от выходного уровня к более ранним уровням сети, что позволяет обучать более глубокие сети. Эта увеличенная глубина сети может привести к более высокой точности при выполнении более сложных задач. Сведения об архитектуре сети и обучении см. в разделе Остаточная сеть поезда для классификации изображений.
Для выполнения этого примера необходимо иметь продукты, необходимые для квантования и развертывания сети глубокого обучения в среде графического процессора. Сведения об этих продуктах см. в разделе Предварительные условия потока операций квантования.
Загрузите предварительно обученную сеть. Сведения о создании и обучении сети с остаточными соединениями для классификации изображений см. в разделе Train Resident Network for Image Classification.
load('CIFARNet-20-16.mat','trainedNet'); net = trainedNet;
Остаточная сетевая архитектура состоит из следующих компонентов:
Основная ветвь с последовательно соединенными сверточными, пакетной нормализацией и уровнями ReLU.
Остаточные соединения, которые обходят сверточные блоки основной ветви. Остаточные соединения позволяют градиентам параметров легче перетекать от выходного уровня к более ранним уровням сети, что позволяет обучать более глубокие сети.
Основная ветвь сети содержит пять секций.
Начальный участок, содержащий слой ввода изображения и начальный сверток с активацией.
Три ступени сверточных слоев с различными размерами элементов (32 на 32, 16 на 16 и 8 на 8). Каждая ступень содержит N сверточных блоков. Каждый сверточный блок содержит N 3 на 3 сверточных слоя с включениями.
Заключительный раздел с глобальным средним объединением, полностью подключенными уровнями, уровнями softmax и классификацией.
Обученная сеть trainedNet является графом уровня для CIFAR-10 данных с остаточными соединениями.
netWidth - ширина сети, определяемая как количество фильтров в первых 3 на 3 свёрточных слоях сети.
numUnits - количество сверточных блоков в основной ветви сети. Поскольку сеть состоит из трех ступеней, где каждая ступень имеет одинаковое количество сверточных блоков, numUnits должно быть целым числом, кратным 3.
unitType - тип сверточной единицы, указанный как "standard" или "bottleneck". Стандартный сверточный блок состоит из двух сверточных слоев 3 на 3. Узкий сверточный блок состоит из трех сверточных слоев: слоя 1 на 1 для понижающей дискретизации в измерении канала, сверточного слоя 3 на 3 и слоя 1 на 1 для повышающей дискретизации в измерении канала. Следовательно, узкий сверточный блок имеет на 50% больше сверточных слоев, чем стандартный блок, но только вдвое меньше числа пространственных сверток 3 на 3. Два типа единиц имеют одинаковую вычислительную сложность, но общее количество элементов, распространяющихся в остаточных соединениях, в четыре раза больше при использовании узких единиц. Общая глубина, определяемая как максимальное количество последовательных сверточных и полностью соединенных слоев, составляет 2 *numUnits + 2 для сетей со стандартными блоками и 3 *numUnits + 2 для сетей с узкими местами.
Вы можете использовать analyzeNetwork для анализа архитектуры сети глубокого обучения.
analyzeNetwork(net)

Загрузите набор данных CIFAR-10 [1], выполнив приведенный ниже код. Набор данных содержит 60 000 изображений. Каждое изображение имеет размер 32 на 32 и имеет три цветовых канала (RGB). Размер набора данных составляет 175 МБ. В зависимости от подключения к Интернету процесс загрузки может занять некоторое время.
datadir = tempdir; downloadCIFARData(datadir);
Загрузите обучающие и тестовые образы CIFAR-10 в виде массивов 4-D. Обучающий набор содержит 50 000 изображений, а набор тестов - 10 000 изображений. Используйте CIFAR-10 тестовые образы для проверки сети.
[XTrain,YTrain,XValidation,YValidation] = loadCIFARData(datadir);
Можно просмотреть случайную выборку обучающих изображений с помощью следующего кода.
figure;
idx = randperm(size(XTrain,4),20);
im = imtile(XTrain(:,:,:,idx),'ThumbnailSize',[96,96]);
imshow(im)
Создание augmentedImageDatastore объект, используемый для калибровки и проверки. Используйте 200 случайных изображений для калибровки и 50 случайных изображений для проверки.
inputSize = net.Layers(1).InputSize; augimdsTrain = augmentedImageDatastore(inputSize,XTrain,YTrain); augimdsCalibration = shuffle(augimdsTrain).subset(1:200); augimdsValidation = augmentedImageDatastore(inputSize,XValidation,YValidation); augimdsValidation = shuffle(augimdsValidation).subset(1:50);
В этом примере используется среда выполнения графического процессора. Сведения о продуктах, необходимых для квантования и развертывания сети глубокого обучения в среде графического процессора, см. в разделе Предварительные условия потока операций квантования.
В окне команд MATLAB ® откройте приложение Глубокий сетевой квантователь.
deepNetworkQuantizer
Выберите «Создать» > «Квантовать сеть». Приложение автоматически проверяет среду выполнения.
В диалоговом окне выберите среду выполнения и сеть для квантования из базовой рабочей области. В этом примере выберите среду выполнения графического процессора и сеть DAG. net.
В разделе Калибровка (Calibrate) панели инструментов в разделе Калибровочные данные (Calibration Data) выберите augmentedImageDatastore объект из базового рабочего пространства, содержащего данные калибровки augimdsCalibration.
Щелкните Калибровка (Calibrate).
Глубокий сетевой квантователь использует калибровочные данные для проверки сети и сбора информации о диапазоне для обучаемых параметров на сетевых уровнях.
По завершении калибровки приложение отображает таблицу, содержащую веса и смещения в свертке, а также полностью соединенные слои сети и динамические диапазоны активизаций во всех слоях сети с их минимальными и максимальными значениями во время калибровки. Справа от таблицы приложение отображает гистограммы динамических диапазонов параметров. Серые области гистограмм указывают данные, которые не могут быть представлены квантованным представлением. Дополнительные сведения о том, как интерпретировать эти гистограммы, см. в разделе Квантование глубоких нейронных сетей.

В столбце «Уровень квантования» таблицы укажите, следует ли квантовать обучаемые параметры на уровне. Слои, которые не являются слоями свертки, не могут быть квантованы и поэтому не могут быть выбраны. Слои, которые не квантуются, остаются с одной точностью после квантования.
В разделе «Проверка» панели инструментов в разделе «Данные проверки» выберите augmentedImageDatastore объект из базовой рабочей области, содержащий данные проверки; augimdsValidation.
В разделе «Проверка» панели инструментов в разделе «Параметры квантования» выберите метрическую функцию для проверки. Приложение определяет метрическую функцию по умолчанию для проверки на основе типа сети, которую вы квантуете. Можно также добавить дополнительные пользовательские метрические функции для проверки. В этом примере введите имя пользовательской метрической функции hComputeAccuracy. Выберите Добавить для добавления hComputeAccuracy в список метрических функций, доступных в приложении. Выберите hComputeAccuracy в качестве метрической функции, используемой для проверки. Эта пользовательская метрическая функция сравнивает предсказанную метку с достоверностью основания и возвращает точность 1 верха. Пользовательская метрическая функция должна находиться в пути.

Щелкните Квантовать (Quantize) и Проверить (Validate)
Приложение квантует сеть и отображает сводку результатов проверки. Для этого набора калибровочных и валидационных изображений квантование сети приводит к снижению точности на 2% при уменьшении памяти обучаемых параметров на 73% для набора из 50 валидационных изображений.

После квантования и проверки сети можно экспортировать квантованную сеть или создать код. Для экспорта квантованной сети выберите «Экспорт» > «Экспорт квантователя», чтобы создать dlquantizer в базовой рабочей области. Чтобы открыть приложение GPU Coder и сгенерировать код GPU из квантованной нейронной сети, выберите Экспорт > Создать код. Чтобы узнать, как генерировать код CUDA для квантованной глубокой сверточной нейронной сети с помощью кодера GPU, см. раздел Создание кода для квантованных сетей глубокого обучения.
Можно использовать несколько метрических функций для оценки производительности квантованной сети одновременно с помощью dlquantizer функция.
Для начала загрузите предварительно обученную сеть и данные и подготовьте данные для калибровки и проверки, как описано выше.
Создать dlquantizer объект. Укажите сеть для квантования и используемую среду выполнения. Используйте calibrate функция для выполнения сети с образцами входных данных от augimdsCalibration и сбор информации о диапазоне.
dq = dlquantizer(net,'ExecutionEnvironment','GPU'); calResults = calibrate(dq,augimdsCalibration)
calResults=72×5 table
Optimized Layer Name Network Layer Name Learnables / Activations MinValue MaxValue
_________________________________ __________________ ________________________ _________ ________
{'convInp_reluInp_Weights' } {'reluInp' } "Weights" -0.020545 0.01913
{'convInp_reluInp_Bias' } {'reluInp' } "Bias" -0.54225 2.0243
{'S1U1_conv1_S1U1_relu1_Weights'} {'S1U1_relu1'} "Weights" -0.58949 0.5883
{'S1U1_conv1_S1U1_relu1_Bias' } {'S1U1_relu1'} "Bias" -0.87623 1.9467
{'S1U1_conv2_relu11_Weights' } {'relu11' } "Weights" -0.58679 0.39988
{'S1U1_conv2_relu11_Bias' } {'relu11' } "Bias" -0.59824 1.8325
{'S1U2_conv1_S1U2_relu1_Weights'} {'S1U2_relu1'} "Weights" -0.29821 0.33049
{'S1U2_conv1_S1U2_relu1_Bias' } {'S1U2_relu1'} "Bias" -1.3102 2.0253
{'S1U2_conv2_relu12_Weights' } {'relu12' } "Weights" -0.7149 0.48284
{'S1U2_conv2_relu12_Bias' } {'relu12' } "Bias" -0.84685 1.6346
{'S1U3_conv1_S1U3_relu1_Weights'} {'S1U3_relu1'} "Weights" -0.16697 0.15356
{'S1U3_conv1_S1U3_relu1_Bias' } {'S1U3_relu1'} "Bias" -1.3796 2.1583
{'S1U3_conv2_relu13_Weights' } {'relu13' } "Weights" -0.47026 0.60147
{'S1U3_conv2_relu13_Bias' } {'relu13' } "Bias" -1.0089 1.5606
{'S2U1_conv1_S2U1_relu1_Weights'} {'S2U1_relu1'} "Weights" -0.14931 0.13792
{'S2U1_conv1_S2U1_relu1_Bias' } {'S2U1_relu1'} "Bias" -1.8735 2.4623
⋮
Укажите метрические функции в dlquantizationOptions объект. Используйте validate функция для квантования обучаемых параметров в уровнях свертки сети и осуществления сети. validate использует метрические функции, определенные в dlquantizationOptions объект для сравнения результатов сети до и после квантования. В этом примере для оценки производительности сети используются метрики точности top-1 и top-5.
dqOpts = dlquantizationOptions('MetricFcn',... {@(x)hComputeAccuracy(x,net,augimdsValidation), ... @(x)hComputeTop_5(x,net,augimdsValidation)}); validationResults = validate(dq,augimdsValidation,dqOpts)
validationResults = struct with fields:
NumSamples: 50
MetricResults: [1×2 struct]
Осмотрите MetricResults.Result поле выходного сигнала проверки достоверности, чтобы видеть производительность квантованной сети, измеренную каждой используемой метрической функцией.
validationResults.MetricResults.Result
ans=2×3 table
NetworkImplementation MetricOutput LearnableParameterMemory(bytes)
_____________________ ____________ _______________________________
{'Floating-Point'} 0.98 1.1113e+06
{'Quantized' } 0.96 3.0057e+05
ans=2×3 table
NetworkImplementation MetricOutput LearnableParameterMemory(bytes)
_____________________ ____________ _______________________________
{'Floating-Point'} 1 1.1113e+06
{'Quantized' } 1 3.0057e+05
Для визуализации статистики калибровки сначала сохраните dlquantizer объект dq.
save('dlquantObj.mat','dq')
Затем импортируйте dlquantizer объект dq в приложении Глубокий сетевой квантователь, выбрав Создать > Импорт dlquantizer объект.
Создание кода CUDA ® для квантованной глубокой сверточной нейронной сети .
Запишите в MATLAB ® функцию начального уровня, которая:
Использует coder.loadDeepLearningNetwork функция для загрузки модели глубокого обучения, а также для построения и настройки класса CNN. Дополнительные сведения см. в разделе Загрузка предварительно обученных сетей для создания кода.
Требования predict (Deep Learning Toolbox) для прогнозирования ответов.
type('mynet_predict.m');function out = mynet_predict(netFile, im)
persistent net;
if isempty(net)
net = coder.loadDeepLearningNetwork(netFile);
end
out = net.predict(im);
end
Постоянный объект mynet загружает DAGNetwork объект. Первый вызов функции точки входа создает и настраивает постоянный объект. Последующие вызовы функции повторно используют тот же объект для вызова predict на входах, избегая реконструкции и перезагрузки сетевого объекта.
codegenДля настройки таких параметров построения, как имя выходного файла, расположение и тип, создаются объекты конфигурации кодера. Для создания объектов используйте coder.gpuConfig функция. Например, при генерации CUDA MEX с помощью команды codegen используйте cfg = coder.gpuConfig('mex').
Чтобы задать параметры генерации кода для cuDNN, установите DeepLearningConfig к свойству coder.CuDNNConfig объект, который создается с помощью coder.DeepLearningConfig.
Укажите местоположение файла MAT, содержащего данные калибровки.
Задайте точность вычислений вывода в поддерживаемых слоях с помощью команды DataType собственность. Для 8-разрядных целых чисел используйте 'int8'. Int8 точности требуется графический процессор CUDA с вычислительной способностью 6.1, 6.3 или выше. Используйте ComputeCapability имущества gpuConfig объект для установки соответствующего значения вычислительной способности.
cfg = coder.gpuConfig('mex'); cfg.TargetLang = 'C++'; cfg.DeepLearningConfig = coder.DeepLearningConfig('cudnn'); cfg.DeepLearningConfig.DataType = 'int8'; cfg.DeepLearningConfig.CalibrationResultFile = 'dlquantObj.mat'; netFile = 'mynet.mat'; save(netFile,'net');
Запустить codegen команда. codegen команда генерирует код CUDA из mynet_predict.m функция точки входа.
codegen -config cfg mynet_predict -args {coder.Constant(netFile), ones(inputSize, 'single')} -report
После успешного создания кода можно просмотреть полученный отчет о создании кода, щелкнув Просмотр отчета в окне команд MATLAB. Отчет отображается в окне Просмотр отчетов. Если генератор кода обнаруживает ошибки или предупреждения во время генерации кода, отчет описывает проблемы и предоставляет ссылки на проблемный код MATLAB. См. раздел Отчеты по созданию кода.

[1] Крижевский, Алекс. 2009. «Изучение нескольких слоев элементов из крошечных изображений». https://www.cs.toronto.edu/~kriz/learning-features-2009-TR.pdf