整个训练分两部分
原图尺寸:input_shape
标签:原始标签 box 为 (class, xmin, ymin, xmax, ymax),xmin, ymin, xmax, ymax 是左上角为坐标轴相对于原图的偏移。
anchor 总共 9 个,三个为一组分给三组输出,其中 anchor 的 0,1,2 分给 32x32 的输出,3,4,5 分给 16x16 的输出,6,7,8分给 8x8 的输出。anchor 的生产通过 k-mean 算法生成(参见附录)。
random crops, rotation, hue, saturation, exposure shift 等。最常用的是 Alex 的预处理方式,四个角剪切 + 中心,翻转,再四个角 + 中心
用 ImageNet 数据集经过 DarkNet53 + avgpool + softmax 之后,得到 1000 分类。
图片尺寸 :input_shape = [height, width]
图片预处理
resize 为 256x256 并除以 255 进行归一化
标签预处理
boxes 转换为 (x,y, w,h, class) 格式得到 true_box,x, y, w, h 除以图片 input_shape 进行归一化
标签计算
# yolo_1 初始化为 [batch_size, grid_1_h, grid_1_w, num_anchors, 4 + 1 + num_class] 的全零矩阵
# yolo_2 初始化为 [batch_size, grid_2_h, grid_2_w, num_anchors, 4 + 1 + num_class] 的全零矩阵
# yolo_3 初始化为 [batch_size, grid_3_h, grid_3_w, num_anchors, 4 + 1 + num_class] 的全零矩阵
# grid_1 为 [13, 13] grid_2 为 [26x26] grid_3 为 [52, 52]
grids = [grid3, grid2, grid1]
yolos = [yolo_3, yolo_2, yolo_1]
i = floor(box_output[1]) # box_ouput 所属 grid_cell 的 height
j = floor(box_output[0]) # box_ouput 所属 grid_cell 的 width
anchor_index = 最大 IOU 对应的 anchor 索引
yolo = yolos[anchor_index // 3] # 通过 anchor 定位到所属 yolo
grid = yolos[anchor_index // 3]
yolo[image_index, i, j, anchor_index%3, 4] = 1
yolo[image_index, i, j, anchor_index%3, 0:4]=[x/grid[1],y/grid[0],log(w)/anchor.w, log(h)/anchor.h]
yolo[image_index, i, j, anchor_index%3, 5+c] = 1 # c 为标签中分类索引
#由上可以非常容易知道, yolos 就是生成的标签
# true_box 初始化为 [batch_size, 1, 1, 1, num_box_per_image, 4]
true_box[image_index, 0,0,0, box_index] = [x/input_shape[0], y/input_shape[1], w/input_shape[0], h/input_shape[1]] #box_index 为当前 box 在图片中索引
object_mask = box_output[..., 4] # 记录某个 grid_cell 的某个 anchor 是否包含物体
对于 pred_1 (13x13) 有
# pred_1 为 [batch_size, grid_1_h, grid_1_w, num_anchors, 4 + 1 + num_classes]
# index 为 grid_1 的元素索引,(0,0),(0,1)...(w-1, h-1)
pred_box_xy = index + sigmoid(pred_1[..., 0:2]) / grid_1
pred_box_wh = exp(pred_1[..., 2:4]) * anchor / input_shape
pred_box_confidence = pred_1[..., 4]
pred_box_class = pred_1[..., 5:]
对 pred_2, pred_3 处理同上。
对于 pred_1
#计算 pred_box 与 true_box 的 IoU1,并且 IoU 小于 < 0.5 为 1,大于 0.5 为 0,这里有疑问?
pred_box_confidence = pred_box_confidence * IoU1
obj_scale = 5
noobj_scale = 1
wh_scale = exp(true_box_wh) * anchors / input_shape
wh_scale = 2 - wh_scale[0] * wh_scale[1]
# 标签
true_box_xy = yolo_1[image_index, i, j, anchor_index%3, 0:2]
true_box_wh = yolo_1[image_index, i, j, anchor_index%3, 2:4]
true_box_confidence = yolo_1[image_index, i, j, anchor_index%3, 4]
true_box_class = yolo_1[image_index, i, j, anchor_index%3, 5:]
# object_mask 使得只有对应 grid_cell 对应的 anchor 有对应标签物体存在是才计算 loss
xy_loss = object_mask * square(pred_box_xy - true_box_xy) * wh_scale
wh_loss = object_mask * square(pred_box_wh - true_box_wh) * wh_scale
confidence_loss = object_mask * square(pred_box_confidence - true_box_confidence) * obj_scale + (1-object_mask) * square(conf_delta) * noobj_scale
#logits = tf.nn.sparse_softmax_cross_entropy_with_logits
class_loss = object_mask * logits(true_box_class, pred_box_class)
loss = sum(xy_loss) + sum(wh_loss) + sum(confidence_loss) + sum(class_loss)
输入
图片尺寸 :input_shape = [height, width]
经过 DarkNet 之后,得到 yolo_output,维度为 [batch_size, height, width, num_anchors, 5 + num_classes]
其中最后一维依次为 [x,y,w,h, confidence, class_one_hot]
图片预处理
resize 为 256x256 并除以 255 进行归一化
对于 pred_1 (13x13) 有
# pred_1 为 [batch_size, grid_1_h, grid_1_w, num_anchors, 4 + 1 + num_classes]
# index 为 grid_1 的元素索引,(0,0),(0,1)...(w-1, h-1)
pred_box_xy = index + sigmoid(pred_1[..., 0:2])
pred_box_wh = pred_1[..., 2:4]
pred_box_confidence = sigmoid(pred_1[..., 4])
pred_box_class = pred_box_confidence * softmax(pred_1[..., 5:]) > 0.5
对 pred_box,保留 pred_box_confidence > 0.5 的元素。
对 pred_2, pred_3 处理同上。
对于任一 pred_box
比如 image_shape 为 [600,800],input_shape 为 [300, 500],那么 new_shape 为 [300, 400]
offset 为 [0, 0.125] scales 为 [0.5, 0.625]
对于任意 pred_box 进行以 0.45 为 IoU 阈值进行 NMS
以上就是 YoloV3 实现。
k-mean 的 anchor 生成算法