В этом примере показано, как обучить и развернуть детектор объектов YOLO v2.
Глубокое обучение - это мощный метод машинного обучения, который можно использовать для обучения надежных детекторов объектов. Существует несколько методов обнаружения объектов, включая более быстрый R-CNN, и вы смотрите только один раз (YOLO) v2. В этом примере выполняется подготовка детектора транспортного средства YOLO v2 с использованием trainYOLOv2ObjectDetector функция.
В этом примере используется небольшой набор данных транспортного средства, содержащий 295 изображений. Многие из этих изображений получены из наборов данных Caltech Cars 1999 и 2001, доступных на веб-сайте Caltech Computational Vision, созданном Пьетро Пероной и используемом с разрешения. Каждое изображение содержит один или два помеченных экземпляра транспортного средства. Небольшой набор данных полезен для изучения процедуры обучения YOLO v2, но на практике для обучения надежного детектора требуется больше маркированных изображений. Распакуйте изображения транспортного средства и загрузите данные об истинности грунта транспортного средства.
unzip vehicleDatasetImages.zip data = load('vehicleDatasetGroundTruth.mat'); vehicleDataset = data.vehicleDataset;
Данные транспортного средства хранятся в таблице из двух столбцов, где первый столбец содержит пути к файлу изображения, а второй столбец содержит ограничивающие рамки транспортного средства.
% Add the fullpath to the local vehicle data folder.
vehicleDataset.imageFilename = fullfile(pwd,vehicleDataset.imageFilename);Разбейте набор данных на обучающие и тестовые наборы. Выберите 60% данных для обучения, а остальные - для тестирования обученного детектора.
rng(0); shuffledIndices = randperm(height(vehicleDataset)); idx = floor(0.6 * length(shuffledIndices) ); trainingDataTbl = vehicleDataset(shuffledIndices(1:idx),:); testDataTbl = vehicleDataset(shuffledIndices(idx+1:end),:);
Использовать imageDatastore и boxLabelDataStore создание хранилищ данных для загрузки данных изображения и метки во время обучения и оценки.
imdsTrain = imageDatastore(trainingDataTbl{:,'imageFilename'});
bldsTrain = boxLabelDatastore(trainingDataTbl(:,'vehicle'));
imdsTest = imageDatastore(testDataTbl{:,'imageFilename'});
bldsTest = boxLabelDatastore(testDataTbl(:,'vehicle'));Объединение хранилищ данных меток изображений и полей.
trainingData = combine(imdsTrain,bldsTrain); testData = combine(imdsTest,bldsTest);
Сеть обнаружения объектов YOLO v2 состоит из двух подсетей. Сеть извлечения элементов, за которой следует сеть обнаружения. Сеть извлечения функций обычно представляет собой предварительно обученный CNN (для получения более подробной информации см. Предварительно обученные глубокие нейронные сети). В этом примере для извлечения элементов используется AlexNet. Вы также можете использовать другие предварительно обученные сети, такие как StartNet v2 или ResNet-18 также могут использоваться в зависимости от требований приложений. Подсеть обнаружения является небольшим CNN по сравнению с сетью извлечения признаков и состоит из нескольких сверточных слоев и слоев, специфичных для YOLO v2.
Используйте yolov2Layers для автоматического создания сети обнаружения объектов YOLO v2 с предварительно подготовленной сетью извлечения функций AlexNet. yolov2Layers требуется указать несколько входов для параметризации сети YOLO v2:
Размер сетевого входа
Якорные ящики
Сеть извлечения элементов
Сначала укажите размер сетевого входа и количество классов. При выборе размера сетевого ввода учитывайте минимальный размер, требуемый самой сетью, размер обучающих изображений и вычислительные затраты, понесенные при обработке данных выбранного размера. Если это возможно, выберите размер сетевого ввода, близкий к размеру обучающего изображения и превышающий размер ввода, требуемый для сети. Чтобы уменьшить вычислительные затраты на выполнение примера, укажите размер сетевого входа [224 224 3], который является минимальным размером, необходимым для запуска сети.
inputSize = [224 224 3];
Определите количество обнаруживаемых классов объектов.
numClasses = width(vehicleDataset)-1;
Обратите внимание, что учебные изображения, используемые в этом примере, больше 224 на 224 и различаются по размеру, поэтому перед началом обучения необходимо изменить размер изображений на этапе предварительной обработки.
Далее используйте estimateAnchorBoxes оценить ящики привязки на основе размера объектов в данных обучения. Чтобы учесть изменение размеров изображений перед обучением, измените размер обучающих данных для оценки полей привязки. Использовать transform для предварительной обработки данных обучения, затем определите количество анкерных ящиков и оцените их. Изменение размера обучающих данных в соответствии с размером входного изображения сети с помощью функции поддержки yolo_preprocessData.
trainingDataForEstimation = transform(trainingData,@(data)yolo_preprocessData(data,inputSize)); numAnchors = 7; [anchorBoxes, meanIoU] = estimateAnchorBoxes(trainingDataForEstimation, numAnchors)
anchorBoxes = 7×2
145 126
91 86
161 132
41 34
67 64
136 111
33 23
meanIoU = 0.8651
Дополнительные сведения о выборе анкерных ящиков см. в разделах Оценка анкерных ящиков по учебным данным (панель инструментов компьютерного зрения) (Toolbox™ компьютерного зрения) и Анкерные ящики для обнаружения объектов (панель инструментов компьютерного зрения).
Теперь используйте alexnet для загрузки предварительно подготовленной модели AlexNet.
featureExtractionNetwork = alexnet
featureExtractionNetwork =
SeriesNetwork with properties:
Layers: [25×1 nnet.cnn.layer.Layer]
InputNames: {'data'}
OutputNames: {'output'}
Выбрать 'relu5' в качестве слоя извлечения элементов для замены слоев после 'relu5' с подсетью обнаружения. Этот слой извлечения элементов выводит карты элементов, которые понижаются в 16 раз. Эта величина понижающей дискретизации является хорошим компромиссом между пространственным разрешением и прочностью выделенных признаков, поскольку признаки, извлеченные далее вниз по сети, кодируют более сильные признаки изображения за счет пространственного разрешения. Выбор оптимального слоя извлечения элементов требует эмпирического анализа.
featureLayer = 'relu5';Создайте сеть обнаружения объектов YOLO v2..
lgraph = yolov2Layers(inputSize,numClasses,anchorBoxes,featureExtractionNetwork,featureLayer);
Можно визуализировать сеть с помощью analyzeNetwork или Deep Network Designer из Deep Learning Toolbox™.
Если требуется дополнительный контроль над сетевой архитектурой YOLO v2, используйте Deep Network Designer для разработки сети обнаружения YOLO v2 вручную. Дополнительные сведения см. в разделе Проектирование сети обнаружения YOLO v2 (панель инструментов компьютерного зрения).
Увеличение данных используется для повышения точности сети путем случайного преобразования исходных данных во время обучения. С помощью увеличения данных можно добавить большее разнообразие к обучающим данным без фактического увеличения количества маркированных обучающих образцов.
Использовать transform для увеличения обучающих данных путем случайного разворота изображения и связанных меток полей по горизонтали. Обратите внимание, что увеличение данных не применяется к данным тестирования и проверки. В идеале, данные тестирования и проверки должны быть репрезентативными для исходных данных и оставлены неизмененными для объективной оценки.
augmentedTrainingData = transform(trainingData,@yolo_augmentData);
Предварительная обработка дополненных данных обучения и данных проверки для подготовки к обучению.
preprocessedTrainingData = transform(augmentedTrainingData,@(data)yolo_preprocessData(data,inputSize));
Использовать trainingOptions для указания параметров сетевого обучения. Набор 'ValidationData' к предварительно обработанным данным проверки. Набор 'CheckpointPath' во временное место. Это позволяет экономить частично обученные детекторы в процессе обучения. Если обучение прервано, например, из-за отключения питания или сбоя системы, вы можете возобновить обучение с сохраненной контрольной точки.
options = trainingOptions('sgdm', ... 'MiniBatchSize', 16, .... 'InitialLearnRate',1e-3, ... 'MaxEpochs',20,... 'CheckpointPath', tempdir, ... 'Shuffle','never');
Использовать trainYOLOv2ObjectDetector функция для обучения детектора объекта YOLO v2.
[detector,info] = trainYOLOv2ObjectDetector(preprocessedTrainingData,lgraph,options);
************************************************************************* Training a YOLO v2 Object Detector for the following object classes: * vehicle Training on single CPU. Initializing input data normalization. |========================================================================================| | Epoch | Iteration | Time Elapsed | Mini-batch | Mini-batch | Base Learning | | | | (hh:mm:ss) | RMSE | Loss | Rate | |========================================================================================| | 1 | 1 | 00:00:02 | 7.23 | 52.3 | 0.0010 | | 5 | 50 | 00:00:43 | 0.99 | 1.0 | 0.0010 | | 10 | 100 | 00:01:24 | 0.77 | 0.6 | 0.0010 | | 14 | 150 | 00:02:03 | 0.64 | 0.4 | 0.0010 | | 19 | 200 | 00:02:41 | 0.57 | 0.3 | 0.0010 | | 20 | 220 | 00:02:55 | 0.58 | 0.3 | 0.0010 | |========================================================================================| Detector training complete. *************************************************************************
В качестве быстрого теста запустите детектор на одном тестовом изображении. Убедитесь, что размер изображения совпадает с размером учебных изображений.
I = imread(testDataTbl.imageFilename{2});
I = imresize(I,inputSize(1:2));
[bboxes,scores] = detect(detector,I);Просмотрите результаты.
I_new = insertObjectAnnotation(I,'rectangle',bboxes,scores);
figure
imshow(I_new)
Загрузите предварительно обученную сеть.
snet=detector.Network; I_pre=yolo_pre_proc(I);
Использовать analyzeNetwork для получения информации о сетевых уровнях:
analyzeNetwork(snet)

Создайте целевой объект для целевого устройства с именем поставщика и интерфейсом для подключения целевого устройства к хост-компьютеру. Опции интерфейса - JTAG (по умолчанию) и Ethernet. Варианты поставщиков - Intel или Xilinx. Для программирования устройства используйте установленный пакет Xilinx Vivado Design Suite по Ethernet-соединению.
hTarget = dlhdl.Target('Xilinx', 'Interface', 'Ethernet');
Создание объекта dlhdl.Workflow класс. При создании объекта укажите сеть и имя битового потока. Укажите сохраненную сеть серии Pre-Trained, trainedNetNoCar, как сеть. Убедитесь, что имя битового потока соответствует типу данных и целевой плате FPGA. В этом примере целевой платой FPGA является ZCU102 плата Zynq UltraScale + MPSoC. Битовый поток использует один тип данных.
hW=dlhdl.Workflow('Network', snet, 'Bitstream', 'zcu102_single','Target',hTarget)
hW =
Workflow with properties:
Network: [1×1 DAGNetwork]
Bitstream: 'zcu102_single'
ProcessorConfig: []
Target: [1×1 dlhdl.Target]
Для компиляции snet series network, запустите функцию компиляции dlhdl.Workflow объект.
dn = hW.compile
### Compiling network for Deep Learning FPGA prototyping ...
### Targeting FPGA bitstream zcu102_single ...
### The network includes the following layers:
1 'data' Image Input 224×224×3 images with 'zerocenter' normalization (SW Layer)
2 'conv1' Convolution 96 11×11×3 convolutions with stride [4 4] and padding [0 0 0 0] (HW Layer)
3 'relu1' ReLU ReLU (HW Layer)
4 'norm1' Cross Channel Normalization cross channel normalization with 5 channels per element (HW Layer)
5 'pool1' Max Pooling 3×3 max pooling with stride [2 2] and padding [0 0 0 0] (HW Layer)
6 'conv2' Grouped Convolution 2 groups of 128 5×5×48 convolutions with stride [1 1] and padding [2 2 2 2] (HW Layer)
7 'relu2' ReLU ReLU (HW Layer)
8 'norm2' Cross Channel Normalization cross channel normalization with 5 channels per element (HW Layer)
9 'pool2' Max Pooling 3×3 max pooling with stride [2 2] and padding [0 0 0 0] (HW Layer)
10 'conv3' Convolution 384 3×3×256 convolutions with stride [1 1] and padding [1 1 1 1] (HW Layer)
11 'relu3' ReLU ReLU (HW Layer)
12 'conv4' Grouped Convolution 2 groups of 192 3×3×192 convolutions with stride [1 1] and padding [1 1 1 1] (HW Layer)
13 'relu4' ReLU ReLU (HW Layer)
14 'conv5' Grouped Convolution 2 groups of 128 3×3×192 convolutions with stride [1 1] and padding [1 1 1 1] (HW Layer)
15 'relu5' ReLU ReLU (HW Layer)
16 'yolov2Conv1' Convolution 256 3×3×256 convolutions with stride [1 1] and padding 'same' (HW Layer)
17 'yolov2Batch1' Batch Normalization Batch normalization with 256 channels (HW Layer)
18 'yolov2Relu1' ReLU ReLU (HW Layer)
19 'yolov2Conv2' Convolution 256 3×3×256 convolutions with stride [1 1] and padding 'same' (HW Layer)
20 'yolov2Batch2' Batch Normalization Batch normalization with 256 channels (HW Layer)
21 'yolov2Relu2' ReLU ReLU (HW Layer)
22 'yolov2ClassConv' Convolution 42 1×1×256 convolutions with stride [1 1] and padding [0 0 0 0] (HW Layer)
23 'yolov2Transform' YOLO v2 Transform Layer. YOLO v2 Transform Layer with 7 anchors. (SW Layer)
24 'yolov2OutputLayer' YOLO v2 Output YOLO v2 Output with 7 anchors. (SW Layer)
### Optimizing series network: Fused 'nnet.cnn.layer.BatchNormalizationLayer' into 'nnet.cnn.layer.Convolution2DLayer'
2 Memory Regions created.
Skipping: data
Compiling leg: conv1>>yolov2ClassConv ...
Compiling leg: conv1>>yolov2ClassConv ... complete.
Skipping: yolov2Transform
Skipping: yolov2OutputLayer
Creating Schedule...
......
Creating Schedule...complete.
Creating Status Table...
.....
Creating Status Table...complete.
Emitting Schedule...
.....
Emitting Schedule...complete.
Emitting Status Table...
.......
Emitting Status Table...complete.
### Allocating external memory buffers:
offset_name offset_address allocated_space
_______________________ ______________ ________________
"InputDataOffset" "0x00000000" "24.0 MB"
"OutputResultOffset" "0x01800000" "4.0 MB"
"SchedulerDataOffset" "0x01c00000" "0.0 MB"
"SystemBufferOffset" "0x01c00000" "28.0 MB"
"InstructionDataOffset" "0x03800000" "4.0 MB"
"ConvWeightDataOffset" "0x03c00000" "16.0 MB"
"EndOffset" "0x04c00000" "Total: 76.0 MB"
### Network compilation complete.
dn = struct with fields:
weights: [1×1 struct]
instructions: [1×1 struct]
registers: [1×1 struct]
syncInstructions: [1×1 struct]
Для развертывания сети на оборудовании Zynq ® UltraScale+™ MPSoC ZCU102 запустите функцию развертывания dlhdl.Workflow объект. Эта функция использует выходные данные функции компиляции для программирования платы FPGA с помощью файла программирования. Функция также загружает веса сети и смещения. Функция развертывания проверяет наличие инструмента Xilinx Vivado и поддерживаемой версии инструмента. Затем он начинает программировать устройство FPGA с помощью битового потока, отображает сообщения о ходе выполнения и время, необходимое для развертывания сети.
hW.deploy
### FPGA bitstream programming has been skipped as the same bitstream is already loaded on the target FPGA. ### Loading weights to Conv Processor. ### Conv Weights loaded. Current time is 20-Dec-2020 15:26:28
Выполните функцию прогнозирования на dlhdl.Workflow и отобразите результат:
[prediction, speed] = hW.predict(I_pre,'Profile','on');
### Finished writing input activations.
### Running single input activations.
Deep Learning Processor Profiler Performance Results
LastFrameLatency(cycles) LastFrameLatency(seconds) FramesNum Total Latency Frames/s
------------- ------------- --------- --------- ---------
Network 8615567 0.03916 1 8615567 25.5
conv1 1357049 0.00617
norm1 569406 0.00259
pool1 205869 0.00094
conv2 2207222 0.01003
norm2 360973 0.00164
pool2 197444 0.00090
conv3 976419 0.00444
conv4 761188 0.00346
conv5 521782 0.00237
yolov2Conv1 660213 0.00300
yolov2Conv2 661162 0.00301
yolov2ClassConv 136816 0.00062
* The clock frequency of the DL processor is: 220MHz
Отображение результатов прогнозирования.
[bboxesn, scoresn, labelsn] = yolo_post_proc(prediction,I_pre,anchorBoxes,{'Vehicle'});
I_new3 = insertObjectAnnotation(I,'rectangle',bboxesn,scoresn);
figure
imshow(I_new3)