Изучение деталей реализации YOLO v3 — модель, часть 2

искусственный интеллект глубокое обучение Python Keras алгоритм Нейронные сети
Изучение деталей реализации YOLO v3 — модель, часть 2

YOLO,СейчасYou Only Look Once(Вы можете посмотреть его только один раз) аббревиатура, основанная на сверточной нейронной сети (CNN).Алгоритмы обнаружения объектов. иYOLO v3это третья версия YOLO, а именноYOLO,YOLO 9000,YOLO v3, эффект обнаружения является более точным и сильным.

Для получения более подробной информации о YOLO v3 вы можете обратиться к YOLO'sОфициальный сайт.

YOLO

YOLO — это американское высказывание You Only Live Once, жить можно только один раз, то есть жизнь слишком коротка, чтобы развлекаться.

Эта статья в основном делится,Как реализовать детали алгоритма YOLO v3, фреймворк Keras. Это часть 2, модель. И конечно же есть 3-я, энная, ведь это полная версия :)

GitHub для этой статьиисходный код:GitHub.com/spike king/can…

обновлено:

Добро пожаловать, обратите внимание, публичный аккаунт WeChatглубокий алгоритм(ID: DeepAlgorithm), узнайте больше о глубоких технологиях!


Вход

Во время обучения звонитеcreate_modelметод создания модели алгоритма. Поэтому в этом разделе основное внимание уделяется анализуcreate_modelлогика реализации.

существуетcreate_modelВ методе создается модель алгоритма YOLO v3, где параметры метода:

  • input_shape: введите размер изображения, по умолчанию (416, 416);
  • anchors: по умолчанию 9 якорей, структура (9, 2);
  • num_classes: Количество категорий При создании сети требуется только количество категорий. В сети значения категории располагаются в порядке 0~n, при этом категория входных данных также представлена ​​индексом;
  • load_pretrained: Использовать ли предварительно обученные веса. Веса перед тренировкой могут не только дать лучшие результаты, но и ускорить обучение модели;
  • freeze_body: Режим стоп-кадра, 1 или 2. Среди них 1 — заморозить слои в сети DarkNet53, 2 — сохранить только последние три сверточных слоя 1x1, а все остальные слои заморозить;
  • weights_path: читать путь предварительно обученных весов;

следующее:

def create_model(input_shape, anchors, num_classes, load_pretrained=True, freeze_body=2,
                 weights_path='model_data/yolo_weights.h5'):

логика

существуетcreate_modelВ методе сначала обрабатываются входные параметры:

  • Разделить ширину h и высоту w размера изображения;
  • Создайте входной слой для изображенийimage_input. Во входном слое размер изображения может быть указан явно, например (416, 416, 3), или неявно, с помощью «?», например (?, ?, 3);
  • Рассчитать количество анкеровnum_anchors;
  • Создайте истинное значение на основе количества якорейy_trueформат ввода.

Конкретная реализация выглядит следующим образом:

h, w = input_shape  # 尺寸
image_input = Input(shape=(w, h, 3))  # 图片输入格式
num_anchors = len(anchors)  # anchor数量

# YOLO的三种尺度,每个尺度的anchor数,类别数+边框4个+置信度1
y_true = [Input(shape=(h // {0: 32, 1: 16, 2: 8}[l], w // {0: 32, 1: 16, 2: 8}[l],
                       num_anchors // 3, num_classes + 5)) for l in range(3)]

Среди них истинное значениеy_true, значением истинности является Ground Truth. «//» — это символ делимости в синтаксисе Python. Зациклив, создайте список из 3 входных слоев, какy_true.y_trueСтруктура тензора (Tensor) выглядит следующим образом:

Tensor("input_2:0", shape=(?, 13, 13, 3, 6), dtype=float32)
Tensor("input_3:0", shape=(?, 26, 26, 3, 6), dtype=float32)
Tensor("input_4:0", shape=(?, 52, 52, 3, 6), dtype=float32)

где в истинном значенииy_trueСреди них 1-й бит — это количество входных выборок, 2-й ~ 3-й бит — это размер карты объектов, например 13x13, 4-й бит — это количество якорей в каждом изображении, а 5-й бит — это: категория ( n)+4 коробки Значение (xywh) + достоверность коробки (содержит ли она объект).

Затем, проходя внутрь, войдите в слой Inputimage_input, количество анкеров для каждой шкалыnum_anchors//3и количество категорийnum_classes, построить сеть для YOLO v3yolo_body,этоyolo_bodyМетоды — это основная логика.

который:

model_body = yolo_body(image_input, num_anchors // 3, num_classes)

Следующим шагом является загрузка логического блока предварительно обученных весов:

  1. Адреса на основе предварительно обученных весовweights_path, загрузите файл веса, установите параметры как, соответствующие названиюby_name, игнорируя несоответствияskip_mismatch;
  2. Выберите режим заморозки:
    • Режим 1 — заморозить 185 слоев, режим 2 — сохранить 3 нижних слоя, а остальные — заморозить. Вся модель имеет в общей сложности 252 слоя;
    • Установите замороженный слой как необучаемый,model_body.layers[i].trainable=False;

выполнить:

if load_pretrained:  # 加载预训练模型
    model_body.load_weights(weights_path, by_name=True, skip_mismatch=True)
    if freeze_body in [1, 2]:
        # Freeze darknet53 body or freeze all but 3 output layers.
        num = (185, len(model_body.layers) - 3)[freeze_body - 1]
        for i in range(num):
            model_body.layers[i].trainable = False  # 将其他层的训练关闭

Среди них слой 185 — это количество слоев сети DarkNet53, а нижние 3 слоя — это 3 сверточных слоя 1x1, используемых для прогнозирования конечного результата. Уровень 185 является последней остаточной единицей сети DarkNet53, и его вход и выход следующие:

input: [(None, 13, 13, 1024), (None, 13, 13, 1024)]
output: (None, 13, 13, 1024)

Три нижних сверточных слоя 1x1 преобразуют три матрицы признаков в три матрицы предсказания в следующем формате:

1: (None, 13, 13, 1024) -> (None, 13, 13, 18)
2: (None, 26, 26, 512) -> (None, 26, 26, 18)
3: (None, 52, 52, 256) -> (None, 52, 52, 18)

Затем постройте слой потерь модели.model_loss, содержание которого следующее:

  • Lambda — это пользовательский слой для Keras, вводmodel_body.outputиy_true, выводoutput_shapeесть (1,), значение потери;
  • Имя пользовательского слоя Lambda:yolo_loss;
  • Параметрами слоя являются якоря списка якорей, количество категорийnum_classesи порог IoUignore_thresh. в,ignore_threshИспользуется для фильтрации полей с небольшим IoU (пересечение над объединением, перекрытие) при потере достоверности объекта;
  • yolo_lossявляется основной логикой функции потерь.

Реализация выглядит следующим образом:

model_loss = Lambda(yolo_loss,
                    output_shape=(1,), name='yolo_loss',
                    arguments={'anchors': anchors,
                               'num_classes': num_classes,
                               'ignore_thresh': 0.5}
                    )(model_body.output + y_true)

Далее строим полную модель алгоритма, шаги следующие:

  • Входной слой модели:model_bodyввод (т.е.image_input) и истинное значениеy_true;
  • Выходной слой модели: пользовательскийmodel_lossслой, выход которого является значением потерь (None, 1);
  • Сохраните сетевую диаграмму моделиplot_modelи распечатать структуру сетиmodel.summary();

который:

model = Model(inputs=[model_body.input] + y_true, outputs=model_loss) # 模型
plot_model(model, to_file=os.path.join('model_data', 'model.png'), show_shapes=True, show_layer_names=True)  # 存储网络结构
model.summary()  # 打印网络

в,model_body.inputесть ли (?)(416,416,3)картинка;y_trueпредставляет собой структуру истинности, преобразованную помеченными данными, то есть:

[Tensor("input_2:0", shape=(?, 13, 13, 3, 6), dtype=float32),
  Tensor("input_3:0", shape=(?, 26, 26, 3, 6), dtype=float32),
  Tensor("input_4:0", shape=(?, 52, 52, 3, 6), dtype=float32)]

Наконец, эти логики завершают построение модели модели алгоритма.


Приложение 1. IoU

IoU, то есть Intersection over Union, который используется для расчета степени перекрытия между двумя графиками и используется для расчета степени корреляции между двумя ограничивающими прямоугольниками.Чем выше значение, тем выше степень корреляции. В NMS (немаксимальное подавление, немаксимальное подавление) или расчете mAP (средняя средняя точность) IoU используется для оценки корреляции двух блоков.

Как показано на рисунке:

IoU

выполнить:

def bb_intersection_over_union(boxA, boxB):
    boxA = [int(x) for x in boxA]
    boxB = [int(x) for x in boxB]

    xA = max(boxA[0], boxB[0])
    yA = max(boxA[1], boxB[1])
    xB = min(boxA[2], boxB[2])
    yB = min(boxA[3], boxB[3])

    interArea = max(0, xB - xA + 1) * max(0, yB - yA + 1)

    boxAArea = (boxA[2] - boxA[0] + 1) * (boxA[3] - boxA[1] + 1)
    boxBArea = (boxB[2] - boxB[0] + 1) * (boxB[3] - boxB[1] + 1)
    
    iou = interArea / float(boxAArea + boxBArea - interArea)

    return iou

Дополнение 2. Заморозить сетевой слой

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

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

В Keras, установив обучаемый параметр каждого слоя, вы можете контролировать, замораживать ли слой, например:

model_body.layers[i].trainable = False

OK, that's all! Enjoy it!

Добро пожаловать, обратите внимание, публичный аккаунт WeChatглубокий алгоритм(ID: DeepAlgorithm), узнайте больше о глубоких технологиях!