В этом примере показано, как обучить и развернуть детектор объектов 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 (для получения более подробной информации см. Предварительно обученные глубокие нейронные сети). В этом примере для извлечения элементов используются ResNet-18. В зависимости от требований приложений можно также использовать другие предварительно обученные сети, такие как StartNet v2 или ResNet-50. Подсеть обнаружения является небольшим CNN по сравнению с сетью извлечения признаков и состоит из нескольких сверточных слоев и слоев, специфичных для YOLO v2.
Используйте yolov2Layers функция для создания сети обнаружения объектов YOLO v2 автоматически с использованием предварительно подготовленной сети извлечения элементов ResNet-18. 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™ компьютерного зрения) и Анкерные ящики для обнаружения объектов (панель инструментов компьютерного зрения).
Теперь используйте resnet18 для загрузки предварительно подготовленной модели ResNet-18.
featureExtractionNetwork = resnet18;
Выбрать 'res4b_relu' в качестве слоя извлечения элементов для замены слоев после 'res4b_relu' с подсетью обнаружения. Этот слой извлечения элементов выводит карты элементов, которые понижаются в 16 раз. Эта величина понижающей дискретизации является хорошим компромиссом между пространственным разрешением и прочностью выделенных признаков, поскольку признаки, извлеченные далее вниз по сети, кодируют более сильные признаки изображения за счет пространственного разрешения. Выбор оптимального слоя извлечения элементов требует эмпирического анализа.
featureLayer = 'res4b_relu';Создайте сеть обнаружения объектов 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 | 8.43 | 71.1 | 0.0010 | | 5 | 50 | 00:01:26 | 0.71 | 0.5 | 0.0010 | | 10 | 100 | 00:02:46 | 0.75 | 0.6 | 0.0010 | | 14 | 150 | 00:04:04 | 0.53 | 0.3 | 0.0010 | | 19 | 200 | 00:05:23 | 0.48 | 0.2 | 0.0010 | | 20 | 220 | 00:05:53 | 0.57 | 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 'zscore' normalization (SW Layer)
2 'conv1' Convolution 64 7×7×3 convolutions with stride [2 2] and padding [3 3 3 3] (HW Layer)
3 'bn_conv1' Batch Normalization Batch normalization with 64 channels (HW Layer)
4 'conv1_relu' ReLU ReLU (HW Layer)
5 'pool1' Max Pooling 3×3 max pooling with stride [2 2] and padding [1 1 1 1] (HW Layer)
6 'res2a_branch2a' Convolution 64 3×3×64 convolutions with stride [1 1] and padding [1 1 1 1] (HW Layer)
7 'bn2a_branch2a' Batch Normalization Batch normalization with 64 channels (HW Layer)
8 'res2a_branch2a_relu' ReLU ReLU (HW Layer)
9 'res2a_branch2b' Convolution 64 3×3×64 convolutions with stride [1 1] and padding [1 1 1 1] (HW Layer)
10 'bn2a_branch2b' Batch Normalization Batch normalization with 64 channels (HW Layer)
11 'res2a' Addition Element-wise addition of 2 inputs (HW Layer)
12 'res2a_relu' ReLU ReLU (HW Layer)
13 'res2b_branch2a' Convolution 64 3×3×64 convolutions with stride [1 1] and padding [1 1 1 1] (HW Layer)
14 'bn2b_branch2a' Batch Normalization Batch normalization with 64 channels (HW Layer)
15 'res2b_branch2a_relu' ReLU ReLU (HW Layer)
16 'res2b_branch2b' Convolution 64 3×3×64 convolutions with stride [1 1] and padding [1 1 1 1] (HW Layer)
17 'bn2b_branch2b' Batch Normalization Batch normalization with 64 channels (HW Layer)
18 'res2b' Addition Element-wise addition of 2 inputs (HW Layer)
19 'res2b_relu' ReLU ReLU (HW Layer)
20 'res3a_branch2a' Convolution 128 3×3×64 convolutions with stride [2 2] and padding [1 1 1 1] (HW Layer)
21 'bn3a_branch2a' Batch Normalization Batch normalization with 128 channels (HW Layer)
22 'res3a_branch2a_relu' ReLU ReLU (HW Layer)
23 'res3a_branch2b' Convolution 128 3×3×128 convolutions with stride [1 1] and padding [1 1 1 1] (HW Layer)
24 'bn3a_branch2b' Batch Normalization Batch normalization with 128 channels (HW Layer)
25 'res3a' Addition Element-wise addition of 2 inputs (HW Layer)
26 'res3a_relu' ReLU ReLU (HW Layer)
27 'res3a_branch1' Convolution 128 1×1×64 convolutions with stride [2 2] and padding [0 0 0 0] (HW Layer)
28 'bn3a_branch1' Batch Normalization Batch normalization with 128 channels (HW Layer)
29 'res3b_branch2a' Convolution 128 3×3×128 convolutions with stride [1 1] and padding [1 1 1 1] (HW Layer)
30 'bn3b_branch2a' Batch Normalization Batch normalization with 128 channels (HW Layer)
31 'res3b_branch2a_relu' ReLU ReLU (HW Layer)
32 'res3b_branch2b' Convolution 128 3×3×128 convolutions with stride [1 1] and padding [1 1 1 1] (HW Layer)
33 'bn3b_branch2b' Batch Normalization Batch normalization with 128 channels (HW Layer)
34 'res3b' Addition Element-wise addition of 2 inputs (HW Layer)
35 'res3b_relu' ReLU ReLU (HW Layer)
36 'res4a_branch2a' Convolution 256 3×3×128 convolutions with stride [2 2] and padding [1 1 1 1] (HW Layer)
37 'bn4a_branch2a' Batch Normalization Batch normalization with 256 channels (HW Layer)
38 'res4a_branch2a_relu' ReLU ReLU (HW Layer)
39 'res4a_branch2b' Convolution 256 3×3×256 convolutions with stride [1 1] and padding [1 1 1 1] (HW Layer)
40 'bn4a_branch2b' Batch Normalization Batch normalization with 256 channels (HW Layer)
41 'res4a' Addition Element-wise addition of 2 inputs (HW Layer)
42 'res4a_relu' ReLU ReLU (HW Layer)
43 'res4a_branch1' Convolution 256 1×1×128 convolutions with stride [2 2] and padding [0 0 0 0] (HW Layer)
44 'bn4a_branch1' Batch Normalization Batch normalization with 256 channels (HW Layer)
45 'res4b_branch2a' Convolution 256 3×3×256 convolutions with stride [1 1] and padding [1 1 1 1] (HW Layer)
46 'bn4b_branch2a' Batch Normalization Batch normalization with 256 channels (HW Layer)
47 'res4b_branch2a_relu' ReLU ReLU (HW Layer)
48 'res4b_branch2b' Convolution 256 3×3×256 convolutions with stride [1 1] and padding [1 1 1 1] (HW Layer)
49 'bn4b_branch2b' Batch Normalization Batch normalization with 256 channels (HW Layer)
50 'res4b' Addition Element-wise addition of 2 inputs (HW Layer)
51 'res4b_relu' ReLU ReLU (HW Layer)
52 'yolov2Conv1' Convolution 256 3×3×256 convolutions with stride [1 1] and padding 'same' (HW Layer)
53 'yolov2Batch1' Batch Normalization Batch normalization with 256 channels (HW Layer)
54 'yolov2Relu1' ReLU ReLU (HW Layer)
55 'yolov2Conv2' Convolution 256 3×3×256 convolutions with stride [1 1] and padding 'same' (HW Layer)
56 'yolov2Batch2' Batch Normalization Batch normalization with 256 channels (HW Layer)
57 'yolov2Relu2' ReLU ReLU (HW Layer)
58 'yolov2ClassConv' Convolution 42 1×1×256 convolutions with stride [1 1] and padding [0 0 0 0] (HW Layer)
59 'yolov2Transform' YOLO v2 Transform Layer. YOLO v2 Transform Layer with 7 anchors. (SW Layer)
60 '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'
5 Memory Regions created.
Skipping: data
Compiling leg: conv1>>pool1 ...
Compiling leg: conv1>>pool1 ... complete.
Compiling leg: res2a_branch2a>>res2a_branch2b ...
Compiling leg: res2a_branch2a>>res2a_branch2b ... complete.
Compiling leg: res2b_branch2a>>res2b_branch2b ...
Compiling leg: res2b_branch2a>>res2b_branch2b ... complete.
Compiling leg: res3a_branch1 ...
Compiling leg: res3a_branch1 ... complete.
Compiling leg: res3a_branch2a>>res3a_branch2b ...
Compiling leg: res3a_branch2a>>res3a_branch2b ... complete.
Compiling leg: res3b_branch2a>>res3b_branch2b ...
Compiling leg: res3b_branch2a>>res3b_branch2b ... complete.
Compiling leg: res4a_branch1 ...
Compiling leg: res4a_branch1 ... complete.
Compiling leg: res4a_branch2a>>res4a_branch2b ...
Compiling leg: res4a_branch2a>>res4a_branch2b ... complete.
Compiling leg: res4b_branch2a>>res4b_branch2b ...
Compiling leg: res4b_branch2a>>res4b_branch2b ... complete.
Compiling leg: yolov2Conv1>>yolov2ClassConv ...
Compiling leg: yolov2Conv1>>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" "4.0 MB"
"SystemBufferOffset" "0x02000000" "28.0 MB"
"InstructionDataOffset" "0x03c00000" "4.0 MB"
"ConvWeightDataOffset" "0x04000000" "20.0 MB"
"EndOffset" "0x05400000" "Total: 84.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
### Programming FPGA Bitstream using Ethernet... Downloading target FPGA device configuration over Ethernet to SD card ... # Copied /tmp/hdlcoder_rd to /mnt/hdlcoder_rd # Copying Bitstream hdlcoder_system.bit to /mnt/hdlcoder_rd # Set Bitstream to hdlcoder_rd/hdlcoder_system.bit # Copying Devicetree devicetree_dlhdl.dtb to /mnt/hdlcoder_rd # Set Devicetree to hdlcoder_rd/devicetree_dlhdl.dtb # Set up boot for Reference Design: 'AXI-Stream DDR Memory Access : 3-AXIM' Downloading target FPGA device configuration over Ethernet to SD card done. The system will now reboot for persistent changes to take effect. System is rebooting . . . . . . ### Programming the FPGA bitstream has been completed successfully. ### Loading weights to Conv Processor. ### Conv Weights loaded. Current time is 04-Jan-2021 13:59:03
Выполните функцию прогнозирования на 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 16974672 0.07716 1 16974672 13.0
conv1 2224187 0.01011
pool1 573166 0.00261
res2a_branch2a 972763 0.00442
res2a_branch2b 972632 0.00442
res2a 209363 0.00095
res2b_branch2a 972674 0.00442
res2b_branch2b 973107 0.00442
res2b 209914 0.00095
res3a_branch1 538478 0.00245
res3a_branch2a 747078 0.00340
res3a_branch2b 904530 0.00411
res3a 104830 0.00048
res3b_branch2a 904540 0.00411
res3b_branch2b 904278 0.00411
res3b 104900 0.00048
res4a_branch1 485804 0.00221
res4a_branch2a 485923 0.00221
res4a_branch2b 880309 0.00400
res4a 52446 0.00024
res4b_branch2a 880071 0.00400
res4b_branch2b 880065 0.00400
res4b 52456 0.00024
yolov2Conv1 880210 0.00400
yolov2Conv2 880375 0.00400
yolov2ClassConv 179300 0.00081
* 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)