目标检测之yolo源码分析
三、配置文件详解(config.py)
import os # 数据集路径,和模型检查点路径
#
# path and dataset parameter
# DATA_PATH = 'data' # 所有数据所在的根目录 PASCAL_PATH = os.path.join(DATA_PATH, 'pascal_voc') # VOC2012数据集所在的目录 CACHE_PATH = os.path.join(PASCAL_PATH, 'cache') # 保存生成的数据集标签缓冲文件所在文件夹 OUTPUT_DIR = os.path.join(PASCAL_PATH, 'output') # 保存生成的网络模型和日志文件所在的文件夹 WEIGHTS_DIR = os.path.join(PASCAL_PATH, 'weights') # 检查点文件所在的目录 WEIGHTS_FILE = None
# WEIGHTS_FILE = os.path.join(DATA_PATH, 'weights', 'YOLO_small.ckpt') # voc2012数据集类别名
CLASSES = ['aeroplane', 'bicycle', 'bird', 'boat', 'bottle', 'bus',
'car', 'cat', 'chair', 'cow', 'diningtable', 'dog', 'horse',
'motorbike', 'person', 'pottedplant', 'sheep', 'sofa',
'train', 'tvmonitor'] # 使用水平镜像,扩大一倍数据集?
FLIPPED = True # 网络模型参数
#
# model parameter
# # 图片大小
IMAGE_SIZE = 448 # 单元格大小,一共有7x7个单元格
CELL_SIZE = 7 # 每个单元格边界框的个数B = 2
BOXES_PER_CELL = 2 # 泄露修正线性激活函数的系数,就是lReLU的系数
ALPHA = 0.1 # 控制台输出信息
DISP_CONSOLE = False # 损失函数的权重设置
OBJECT_SCALE = 1.0 # 有目标时,置信度权重
NOOBJECT_SCALE = 1.0 # 没有目标时,置信度权重
CLASS_SCALE = 2.0 # 类别权重
COORD_SCALE = 5.0 # 边界框权重 # 训练参数设置
#
# solver parameter
# GPU = ''
# 学习率
LEARNING_RATE = 0.0001
# 退化学习率衰减步数
DECAY_STEPS = 30000
# 衰减率
DECAY_RATE = 0.1 STAIRCASE = True #批量大小
BATCH_SIZE = 45
# 最大迭代次数
MAX_ITER = 15000 # 日志文件保存间隔步
SUMMARY_ITER = 10
# 模型保存间隔步
SAVE_ITER = 1000 # 测试时的相关参数
#
# test parameter
#
# 格子有目标的置信度阈值
THRESHOLD = 0.2
# 非极大值抑制 IOU阈值
IOU_THRESHOLD = 0.5
四、yolo文件夹详解
yolo网络的建立是通过yolo文件夹中的yolo_net.py文件的代码实现的,yolo_net.py文件定义了YOLONet类,该类包含了网络初始化(__init__()),建立网络(build_networks)和loss函数(loss_layer())等方法
import numpy as np
import tensorflow as tf
import yolo.config as cfg slim = tf.contrib.slim class YOLONet(object):
1. 网络参数初始化
网络的所有初始化参数包含于__init__()方法中
# 网络参数初始化
def __init__(self, is_training=True):
'''
构造函数利用cfg文件对网络参数进行初始化,同时定义网络的输入和输出size等信息,
其中offset的作用应该是一个定长的偏移,boundery1和boundery2 作用是在输出中确定每种信息的长度(如类别,置信度等)
其中 boundery1指的是对于所有cell的类别的预测的张量维度,所以是self.cell_size * self.cell_size * self.num_class
boundery2指的是在类别之后每个cell所对应的bounding boxes的数量的总合,所以是
'''
# voc 2012数据集类别名
self.classes = cfg.CLASSES
# 类别个数C 20
self.num_class = len(self.classes) # 网络输入图像大小448, 448 x 448
self.image_size = cfg.IMAGE_SIZE
# 单元格大小S=7,将图像分为SxS的格子
self.cell_size = cfg.CELL_SIZE
# 每个网格边界框的个数B=2
self.boxes_per_cell = cfg.BOXES_PER_CELL # 网络输出的大小 S*S*(B*5 + C) = 1470
self.output_size = (self.cell_size * self.cell_size) *\
(self.num_class + self.boxes_per_cell * 5) # 图片的缩放比例 64
self.scale = 1.0 * self.image_size / self.cell_size # 将网络输出分离为类别和置信度以及边界框的大小,输出维度为7*7*20 + 7*7*2 + 7*7*2*4=1470
# 7*7*20
self.boundary1 = self.cell_size * self.cell_size * self.num_class
# 7*7*20 + 7*7*2
self.boundary2 = self.boundary1 +\
self.cell_size * self.cell_size * self.boxes_per_cell # 代价函数 权重
self.object_scale = cfg.OBJECT_SCALE #
self.noobject_scale = cfg.NOOBJECT_SCALE #
self.class_scale = cfg.CLASS_SCALE # 2.0
self.coord_scale = cfg.COORD_SCALE # 2.0 # 学习率0.0001
self.learning_rate = cfg.LEARNING_RATE
# 批大小 45
self.batch_size = cfg.BATCH_SIZE
#泄露修正线性激活函数 系数0.1
self.alpha = cfg.ALPHA # 偏置 形状[7,7,2]
self.offset = np.transpose(np.reshape(np.array(
[np.arange(self.cell_size)] * self.cell_size * self.boxes_per_cell),
(self.boxes_per_cell, self.cell_size, self.cell_size)), (1, 2, 0)) # 输入图片占位符 [None,image_size,image_size,3]
self.images = tf.placeholder(
tf.float32, [None, self.image_size, self.image_size, 3],
name='images')
# 构建网络,获取YOLO网络的输出(不经过激活函数的输出) 形状[None,1470]
self.logits = self.build_network(
self.images, num_outputs=self.output_size, alpha=self.alpha,
is_training=is_training) if is_training:
# 设置标签占位符 [None,S,S,5+C] 即[None,7,7,25]
self.labels = tf.placeholder(
tf.float32,
[None, self.cell_size, self.cell_size, 5 + self.num_class])
# 设置损失函数
self.loss_layer(self.logits, self.labels)
# 加入权重正则化之后的损失
self.total_loss = tf.losses.get_total_loss()
# 将损失以标量形式显示,该变量命名为total_loss
tf.summary.scalar('total_loss', self.total_loss)
2. 构建网络
网络的建立是通过build_network()函数实现的,网络由卷积层,池化层和全连接层组成,网络的输入维度是[None,448,448,3],输出维度为[None,1470]
def build_network(self,
images,
num_outputs,
alpha,
keep_prob=0.5,
is_training=True,
scope='yolo'):
'''
构建YOLO网络
args:
images:输入图片占位符[None,image_size,image_size,3] 这里是[None,448,448,3]
num_outputs: 标量,网络输出节点数 1470
alpha:泄露修正线性激活函数 系数0.1
keep_prob: 弃权 保留率
is_training:训练?
scope:命名空间名
return:
返回网络最后一层,激活函数处理之前的值 形状[None,1470]
'''
# 定义变量命名空间
with tf.variable_scope(scope):
# 定义共享参数,使用L2正则化
with slim.arg_scope(
[slim.conv2d, slim.fully_connected],
activation_fn=leaky_relu(alpha),
weights_regularizer=slim.l2_regularizer(0.0005),
weights_initializer=tf.truncated_normal_initializer(0.0, 0.01)
):
# pad_1 填充 454x454x3
net = tf.pad(
images, np.array([[0, 0], [3, 3], [3, 3], [0, 0]]),
name='pad_1')
# 卷积层 conv_2 s=2 (n-f+1)/s向上取整 224x224x64
net = slim.conv2d(
net, 64, 7, 2, padding='VALID', scope='conv_2')
# 池化层 pool_3 112x112x64
net = slim.max_pool2d(net, 2, padding='SAME', scope='pool_3') # 卷积层 conv_4 3x3x192 s=1 n/s向上取整 112x112x192
net = slim.conv2d(net, 192, 3, scope='conv_4')
# 池化层 pool_5 56x56x192
net = slim.max_pool2d(net, 2, padding='SAME', scope='pool_5') # 卷积层conv_6 1x1x128 s=1 n/s向上取整 56x56x128
net = slim.conv2d(net, 128, 1, scope='conv_6')
# 卷积层conv_7 3x3x256 s=1 n/s向上取整 56x56x256
net = slim.conv2d(net, 256, 3, scope='conv_7')
# 卷积层conv_8 1x1x256 s=1 n/s向上取整 56x56x256
net = slim.conv2d(net, 256, 1, scope='conv_8')
# 卷积层conv_9 3x3x512 s=1 n/s向上取整 56x56x512
net = slim.conv2d(net, 512, 3, scope='conv_9')
# 池化层 pool_10 28x28x512
net = slim.max_pool2d(net, 2, padding='SAME', scope='pool_10') # 卷积层conv_11 1x1x256 s=1 n/s向上取整 28x28x256
net = slim.conv2d(net, 256, 1, scope='conv_11')
# 卷积层conv_12 3x3x512 s=1 n/s向上取整 28x28x512
net = slim.conv2d(net, 512, 3, scope='conv_12') # 卷积层conv_13 1x1x256 s=1 n/s向上取整 28x28x256
net = slim.conv2d(net, 256, 1, scope='conv_13')
# 卷积层conv_14 3x3x512 s=1 n/s向上取整 28x28x512
net = slim.conv2d(net, 512, 3, scope='conv_14') net = slim.conv2d(net, 256, 1, scope='conv_15')
net = slim.conv2d(net, 512, 3, scope='conv_16') net = slim.conv2d(net, 256, 1, scope='conv_17')
net = slim.conv2d(net, 512, 3, scope='conv_18') # 卷积层conv_19 3x3x512 s=1 n/s向上取整 28x28x512
net = slim.conv2d(net, 512, 1, scope='conv_19')
# 卷积层conv_20 3x3x1024 s=1 n/s向上取整 28x28x1024
net = slim.conv2d(net, 1024, 3, scope='conv_20')
# 池化层 pool_21 14x14x1024
net = slim.max_pool2d(net, 2, padding='SAME', scope='pool_21') # 卷积层conv_22 1x1x512 s=1 n/s向上取整 14x14x512
net = slim.conv2d(net, 512, 1, scope='conv_22')
# 卷积层conv_23 3x3x1024 s=1 n/s向上取整 14x14x1024
net = slim.conv2d(net, 1024, 3, scope='conv_23') net = slim.conv2d(net, 512, 1, scope='conv_24')
net = slim.conv2d(net, 1024, 3, scope='conv_25')
net = slim.conv2d(net, 1024, 3, scope='conv_26') # pad_27 填充 16x16x2014
net = tf.pad(
net, np.array([[0, 0], [1, 1], [1, 1], [0, 0]]),
name='pad_27') # 卷积层conv_28 3x3x1024 s=2 (n-f+1)/s向上取整 7x7x1024
net = slim.conv2d(
net, 1024, 3, 2, padding='VALID', scope='conv_28') # 卷积层 conv_29 3x3x1024 s=1 n/s向上取整 7x7x1024
net = slim.conv2d(net, 1024, 3, scope='conv_29')
net = slim.conv2d(net, 1024, 3, scope='conv_30') # trans_31 转置 [None,1024,7,7]
net = tf.transpose(net, [0, 3, 1, 2], name='trans_31')
# flat_32 展开 50716=1024*7*7
net = slim.flatten(net, scope='flat_32')
# 全连接层 fc_33 512
net = slim.fully_connected(net, 512, scope='fc_33')
# 全连接层 fc_34 4096
net = slim.fully_connected(net, 4096, scope='fc_34')
# 惩罚项 dropout_35 4096
net = slim.dropout(
net, keep_prob=keep_prob, is_training=is_training,
scope='dropout_35') # 全连接层fc_36 num_outputs=1470
net = slim.fully_connected(
net, num_outputs, activation_fn=None, scope='fc_36')
return net
3、代价函数
目标检测之yolo源码分析的更多相关文章
- 第三十六节,目标检测之yolo源码解析
在一个月前,我就已经介绍了yolo目标检测的原理,后来也把tensorflow实现代码仔细看了一遍.但是由于这个暑假事情比较大,就一直搁浅了下来,趁今天有时间,就把源码解析一下.关于yolo目标检测的 ...
- HDFS源码分析数据块汇报之损坏数据块检测checkReplicaCorrupt()
无论是第一次,还是之后的每次数据块汇报,名字名字节点都会对汇报上来的数据块进行检测,看看其是否为损坏的数据块.那么,损坏数据块是如何被检测的呢?本文,我们将研究下损坏数据块检测的checkReplic ...
- yolo源码解析(3):视频检测流程
代码在自己电脑中!!!!不在服务器 根据前文所说yolo代码逻辑: ├── examples │ ├── darknet.c(主程序) │ │── xxx1.c │ └── xxx2.c │ ├── ...
- 【目标检测】YOLO:
PPT 可以说是讲得相当之清楚了... deepsystems.io 中文翻译: https://zhuanlan.zhihu.com/p/24916786 图解YOLO YOLO核心思想:从R-CN ...
- Yolov3&Yolov4网络结构与源码分析
Yolov3&Yolov4网络结构与源码分析 从2018年Yolov3年提出的两年后,在原作者声名放弃更新Yolo算法后,俄罗斯的Alexey大神扛起了Yolov4的大旗. 文章目录 1. 论 ...
- jQuery 2.0.3 源码分析 事件绑定 - bind/live/delegate/on
事件(Event)是JavaScript应用跳动的心脏,通过使用JavaScript ,你可以监听特定事件的发生,并规定让某些事件发生以对这些事件做出响应 事件的基础就不重复讲解了,本来是定位源码分析 ...
- Tomcat源码分析
前言: 本文是我阅读了TOMCAT源码后的一些心得. 主要是讲解TOMCAT的系统框架, 以及启动流程.若有错漏之处,敬请批评指教! 建议: 毕竟TOMCAT的框架还是比较复杂的, 单是从文字上理解, ...
- Nmap源码分析(脚本引擎)
Nmap提供了强大的脚本引擎(NSE),以支持通过Lua编程来扩展Nmap的功能.目前脚本库已经包含300多个常用的Lua脚本,辅助完成Nmap的主机发现.端口扫描.服务侦测.操作系统侦测四个基本功能 ...
- wifidog源码分析 - 用户连接过程
引言 之前的文章已经描述wifidog大概的一个工作流程,这里我们具体说说wifidog是怎么把一个新用户重定向到认证服务器中的,它又是怎么对一个已认证的用户实行放行操作的.我们已经知道wifidog ...
随机推荐
- Linux bash篇(二 操作环境)
1.命令执行的顺序 (1).相对/绝对路径 (2).由alias找到的命令 (3).由bash内置的命令 (4).通过$PATH变量找到的第一个命令 2.第一篇讲到的bash在注销后就会无效,如果想保 ...
- es实现mysql的like查询
es版本6.8 因为阿里云的dts同步最高支持es版本就是6.8 构建索引 PUT /z_test/ { "mappings": { "doc": { &quo ...
- .NET 下基于动态代理的 AOP 框架实现揭秘
.NET 下基于动态代理的 AOP 框架实现揭秘 Intro 之前基于 Roslyn 实现了一个简单的条件解析引擎,想了解的可以看这篇文章 https://www.cnblogs.com/weihan ...
- c++动态数组的优点,创建和删除
动态数组可以有两种使用方式: 1:不能预先知道数组的大小使用动态数组 传统数组(静态数组)是需要在程序运行前,就指定大小,比如说 int i = 10; int a[i]; 这种就是不合法的. 因为函 ...
- day01,了解gcc
今天主要是学一下gcc 功能选项: 一. 1. gcc -E:表示预处理,把指令处理掉 2.gcc -o:改变目标文件名称 3. gcc -c: 表示只编译不链接(也就是不生成a.out) 4. g ...
- Extjs更新grid
基于Extjs4.2 原理是创建一个新的store,来覆盖原有的store. //创建数据 var newdatas = { name: "ly", age: 17, adress ...
- Python函数的返回值和作用域
函数的返回值和作用域 1.返回值 def guess(x): if x > 3: return "> 3" else: retu ...
- poi导出word文档,doc和docx
maven <!-- https://mvnrepository.com/artifact/org.apache.poi/poi --><dependency> <gro ...
- 如何利用python实现报表自动化?让你更高效的完成工作内容
如果能够实现报表自动化,那我们将节约不少的时间,更高效的完成工作内容.那么,如何利用python实现报表自动化呢?本文将介绍xlwt .xlrd.xlutils的常用功能,xlwt写Excel时公式的 ...
- Category、load、initialize 源码讲解
今天深圳天气有暴风雨,没有事情干,趁着周末和平常晚上写一篇关于Category知识的梳理!可能针对平常只会知道些category基本结论知道的人有些帮助,写这篇博客会按照下面的目录结合实例以及Cate ...