热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Tensorflow2.0YOLOV4tiny网络原理及代码解析(三)损失函数的构建

Tensorflow2.0—YOLOV4-tiny网络原理及代码解析(三)-损失函数的构建YOLOV4中的损失函数与V3还是有比较大的区别的ÿ
Tensorflow2.0—YOLO V4-tiny网络原理及代码解析(三)- 损失函数的构建

YOLO V4中的损失函数与V3还是有比较大的区别的,具体的可以看YOLOV4与YOLOV3的区别。
代码是在nets文件夹下面的loss.py文件中,在train.py中引用的是:

model_loss = Lambda(yolo_loss, output_shape=(1,), name='yolo_loss',arguments={'anchors': anchors, 'num_classes': num_classes, 'ignore_thresh': 0.5, 'label_smoothing': label_smoothing})(loss_input)

先来看下yolo_loss的参数:

def yolo_loss(args, #是一个列表,其中包含了预测结果和进行编码之后的真实框的结果,# [, 预测结果1# , 预测结果2# , 真实框1# ] 真实框2anchors, #[[ 10. 14.]# [ 23. 27.]# [ 37. 58.]# [ 81. 82.]# [135. 169.]# [344. 319.]]num_classes, #['aeroplane', 'bicycle', 'bird', 'boat', 'bottle', 'bus', 'car', 'cat', 'chair', 'cow', 'diningtable', 'dog', 'horse', 'motorbike', 'person', 'pottedplant', 'sheep', 'sofa', 'train', 'tvmonitor'],共20个分类ignore_thresh=.5, #阈值label_smoothing=0.1, #标签平滑print_loss=False, #是否打印损失normalize=True): #是否做归一化

把预测的与真实的进行分割出来,
y_true是一个列表,包含两个特征层,shape分别为(m,13,13,75),(m,26,26,75)
yolo_outputs是一个列表,包含两个特征层,shape分别为(m,13,13,3,25),(m,26,26,3,25)

y_true = args[num_layers:]
yolo_outputs = args[:num_layers]

然后就开始以特征层数开始循环,这里就以(m,13,13,3,25)为例:
先获得真实框(m,13,13,3,25)的第5个位置的数据,如果在编码中该位置存在gt框,那么就设置为1,表示第(i,j)特征图中第k个锚点框包含物体,否则一切都设置为0

object_mask = y_true[l][..., 4:5]

然后,再获得真实框(m,13,13,3,25)的第6-26个位置的数据:

true_class_probs = y_true[l][..., 5:]

接着,进行标签平滑:

if label_smoothing:true_class_probs = _smooth_labels(true_class_probs, label_smoothing)

def _smooth_labels(y_true, label_smoothing):num_classes = tf.cast(K.shape(y_true)[-1], dtype=K.floatx())label_smoothing = K.constant(label_smoothing, dtype=K.floatx())return y_true * (1.0 - label_smoothing) + label_smoothing / num_classes


接着,就是yolo_head:

yolo_head(yolo_outputs[l], #yolo模型预测的结果,shape=(None,13,13,75)anchors[anchor_mask[l]], #预测结果所对应的anchor,这里为#[[ 81. ,82.],# [135. ,169.],# [344. ,319.]]num_classes, #voc数据集的class数量,为20input_shape, #(416,416)calc_loss=True) #是否计算损失函数,在模型预测阶段,该参数为False

下面这一段代码有点难理解,其实它的作用就是创建(13,13,1,2)的网格

grid_shape = K.shape(feats)[1:3] # height, width,为(13,13)
grid_y = K.tile(K.reshape(K.arange(0, stop=grid_shape[0]), [-1, 1, 1, 1]),[1, grid_shape[1], 1, 1])
grid_x = K.tile(K.reshape(K.arange(0, stop=grid_shape[1]), [1, -1, 1, 1]),[grid_shape[0], 1, 1, 1])
grid = K.concatenate([grid_x, grid_y])
grid = K.cast(grid, K.dtype(feats))

举个例子:
在这里插入图片描述
在这幅图片中就可以很好的看到最终其实就是生成了(13,13,1,2)的网格。

feats = K.reshape(feats, [-1, grid_shape[0], grid_shape[1], num_anchors, num_classes + 5])

将预测结果(m,13,13,75)分割成(m,13,13,3,25)。

box_xy = (K.sigmoid(feats[..., :2]) + grid) / K.cast(grid_shape[...,::-1], K.dtype(feats))
box_wh = K.exp(feats[..., 2:4]) * anchors_tensor / K.cast(input_shape[...,::-1], K.dtype(feats))
box_confidence = K.sigmoid(feats[..., 4:5])
box_class_probs = K.sigmoid(feats[..., 5:])

这四行代码的目的是:将预测值转换为真实值!
第一行:将预测结果的xy(None,13,13,3,2)先加上grid,然后除以(13,13),就得到了转化后的进行归一化的xy,shape=(None,13,13,3,2)。
第二行:将预测结果的wh(None,13,13,3,2)先乘anchor的尺寸,然后除以输入大小,最后再进行指数计算,得到转换后的wh,shape同xy。
第三行和第四行:将预测得到的confidence和class_prob进行sigmoid转化。

最后,就可以将预测结果进行decode为预测真实框的形式~

if calc_loss == True:return grid, feats, box_xy, box_whreturn box_xy, box_wh, box_confidence, box_class_probs

在计算loss的时候返回grid, feats, box_xy, box_wh
在预测的时候返回box_xy, box_wh, box_confidence, box_class_probs

pred_box = K.concatenate([pred_xy, pred_wh])

将上述box_xy, box_wh进行合并,shape=(None,13,13,3,4)


下面,还有一个loop_body函数,来看看它是干嘛的。

#-----------------------------------------------------------## 对每一张图片计算ignore_mask#-----------------------------------------------------------#def loop_body(b, ignore_mask):#-----------------------------------------------------------## 取出n个真实框&#xff1a;n,4#-----------------------------------------------------------#true_box &#61; tf.boolean_mask(y_true[l][b,...,0:4], object_mask_bool[b,...,0])#-----------------------------------------------------------## 计算预测框与真实框的iou# pred_box 13,13,3,4 预测框的坐标# true_box n,4 真实框的坐标# iou 13,13,3,n 预测框和真实框的iou#-----------------------------------------------------------#iou &#61; box_iou(pred_box[b], true_box)#-----------------------------------------------------------## best_iou 13,13,3 每个特征点与真实框的最大重合程度#-----------------------------------------------------------#best_iou &#61; K.max(iou, axis&#61;-1)#-----------------------------------------------------------## 判断预测框和真实框的最大iou小于ignore_thresh# 则认为该预测框没有与之对应的真实框# 该操作的目的是&#xff1a;# 忽略预测结果与真实框非常对应特征点&#xff0c;因为这些框已经比较准了# 不适合当作负样本&#xff0c;所以忽略掉。#-----------------------------------------------------------#ignore_mask &#61; ignore_mask.write(b, K.cast(best_iou<ignore_thresh, K.dtype(true_box)))return b&#43;1, ignore_mask#-----------------------------------------------------------## 在这个地方进行一个循环、循环是对每一张图片进行的#-----------------------------------------------------------#_, ignore_mask &#61; tf.while_loop(lambda b,*args: b<m, loop_body, [0, ignore_mask])

步骤解释&#xff1a;
1.先取出真实框存在物体的框的xywh
2.与预测框进行iou计算
3.找到对应每个真实框最大的iou的预测框&#xff0c;best_iou &#61; &#xff08;13&#xff0c;13&#xff0c;3&#xff09;
4.判断预测框和真实框的最大iou小于ignore_thresh&#xff0c;则认为该预测框没有与之对应的真实框&#xff0c;这么做的目的是&#xff1a;忽略预测结果与真实框非常对应特征点&#xff0c;因为这些框已经比较准了&#xff0c;不适合当作负样本&#xff0c;所以忽略掉
5.把这些框放入ignore_mask中

#-----------------------------------------------------------## 真实框越大&#xff0c;比重越小&#xff0c;小框的比重更大。#-----------------------------------------------------------#box_loss_scale &#61; 2 - y_true[l][...,2:3]*y_true[l][...,3:4]#-----------------------------------------------------------## 计算Ciou loss#-----------------------------------------------------------#raw_true_box &#61; y_true[l][...,0:4]ciou &#61; box_ciou(pred_box, raw_true_box)ciou_loss &#61; object_mask * box_loss_scale * (1 - ciou)

这一部分是进行预测与真实的ciou损失&#xff01;但是代码实现中与论文中还是有一点区别的&#xff0c;在代码中还考虑到了真实框大小的因素&#xff1a;真实框越大&#xff0c;比重越小&#xff0c;小框的比重更大。&#xff08;这里我就不写ciou的代码了&#xff0c;有机会单独写一个blog~&#xff09;&#xff0c;得到的ciou_loss &#61; &#xff08;None,13,13,3,1&#xff09;。

最后&#xff0c;就是置信度损失和类别损失的计算了&#xff1a;

confidence_loss &#61; object_mask * K.binary_crossentropy(object_mask, raw_pred[...,4:5], from_logits&#61;True)&#43; \(1-object_mask) * K.binary_crossentropy(object_mask, raw_pred[...,4:5], from_logits&#61;True) * ignore_maskclass_loss &#61; object_mask * K.binary_crossentropy(true_class_probs, raw_pred[...,5:], from_logits&#61;True)

第一行&#xff1a;先计算真实框存在的confidence_loss&#xff0c;加上不存在真实框的confidence_loss&#xff08;这里要忽略那些ignore_mask里面的框&#xff09;。
第二行&#xff1a;直接计算预测和真实的类别损失。

num_pos &#43;&#61; tf.maximum(K.sum(K.cast(object_mask, tf.float32)), 1)loss &#43;&#61; location_loss &#43; confidence_loss &#43; class_lossloss &#61; K.expand_dims(loss, axis&#61;-1)if normalize:loss &#61; loss / num_poselse:loss &#61; loss / mfreturn loss

最后就是进行损失求和&#xff0c;若进行归一化&#xff0c;就将总损失除以正样本&#xff0c;要是不进行归一化&#xff0c;那就除以批次大小。最终得到最后的loss~


推荐阅读
  • 如何用Matlab快速画出带有3D渲染效果的复杂曲面
    简要地介绍了一下如何用Matlab快速画出带有3D渲染效果的复杂曲面图,包括三维曲面绘制、光线、材质、着色等等控制,以及如何 ... [详细]
  • 也就是|小窗_卷积的特征提取与参数计算
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了卷积的特征提取与参数计算相关的知识,希望对你有一定的参考价值。Dense和Conv2D根本区别在于,Den ... [详细]
  • 人脸检测 pyqt+opencv+dlib
    一、实验目标绘制PyQT界面,调用摄像头显示人脸信息。在界面中,用户通过点击不同的按键可以实现多种功能:打开和关闭摄像头, ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 推荐系统遇上深度学习(十七)详解推荐系统中的常用评测指标
    原创:石晓文小小挖掘机2018-06-18笔者是一个痴迷于挖掘数据中的价值的学习人,希望在平日的工作学习中,挖掘数据的价值, ... [详细]
  • 不同优化算法的比较分析及实验验证
    本文介绍了神经网络优化中常用的优化方法,包括学习率调整和梯度估计修正,并通过实验验证了不同优化算法的效果。实验结果表明,Adam算法在综合考虑学习率调整和梯度估计修正方面表现较好。该研究对于优化神经网络的训练过程具有指导意义。 ... [详细]
  • ASP.NET2.0数据教程之十四:使用FormView的模板
    本文介绍了在ASP.NET 2.0中使用FormView控件来实现自定义的显示外观,与GridView和DetailsView不同,FormView使用模板来呈现,可以实现不规则的外观呈现。同时还介绍了TemplateField的用法和FormView与DetailsView的区别。 ... [详细]
  • 本文介绍了使用Spark实现低配版高斯朴素贝叶斯模型的原因和原理。随着数据量的增大,单机上运行高斯朴素贝叶斯模型会变得很慢,因此考虑使用Spark来加速运行。然而,Spark的MLlib并没有实现高斯朴素贝叶斯模型,因此需要自己动手实现。文章还介绍了朴素贝叶斯的原理和公式,并对具有多个特征和类别的模型进行了讨论。最后,作者总结了实现低配版高斯朴素贝叶斯模型的步骤。 ... [详细]
  • 带添加按钮的GridView,item的删除事件
    先上图片效果;gridView无数据时显示添加按钮,有数据时,第一格显示添加按钮,后面显示数据:布局文件:addr_manage.xml<?xmlve ... [详细]
  • 本文介绍了如何使用MATLAB调用摄像头进行人脸检测和识别。首先需要安装扩展工具,并下载安装OS Generic Video Interface。然后使用MATLAB的机器视觉工具箱中的VJ算法进行人脸检测,可以直接调用CascadeObjectDetector函数进行检测。同时还介绍了如何调用摄像头进行人脸识别,并对每一帧图像进行识别。最后,给出了一些相关的参考资料和实例。 ... [详细]
  • 本文介绍了利用ARMA模型对平稳非白噪声序列进行建模的步骤及代码实现。首先对观察值序列进行样本自相关系数和样本偏自相关系数的计算,然后根据这些系数的性质选择适当的ARMA模型进行拟合,并估计模型中的位置参数。接着进行模型的有效性检验,如果不通过则重新选择模型再拟合,如果通过则进行模型优化。最后利用拟合模型预测序列的未来走势。文章还介绍了绘制时序图、平稳性检验、白噪声检验、确定ARMA阶数和预测未来走势的代码实现。 ... [详细]
  • 前端开发工程师必读书籍有哪些值得推荐?我们直接进入代码复杂版式设置,如下所示,先写些标签,源码在这个链接里面:https://codepen.io/Shadid ... [详细]
  • keras归一化激活函数dropout
    激活函数:1.softmax函数在多分类中常用的激活函数,是基于逻辑回归的,常用在输出一层,将输出压缩在0~1之间,且保证所有元素和为1,表示输入值属于每个输出值的概率大小2、Si ... [详细]
  • 代码如下:#coding:utf-8importstring,os,sysimportnumpyasnpimportmatplotlib.py ... [详细]
  • **************************************************************** ... [详细]
author-avatar
zackcoolgirl_497
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有