Tensorflow-Faster代码解析:network.py

本文深入解析TensorFlow中Faster网络的实现细节,探讨网络架构设计及数据在网络中的流动过程,通过network.py代码展开讨论。
摘要由CSDN通过智能技术生成

训练、测试都是调用了网络。那么网络是如何张开、恢复、调用,数据是如何在网络里面流动的呢?

network类基本包含了整个网络的架构设计,直接给出代码解析:

# --------------------------------------------------------
# Tensorflow Faster R-CNN
# Licensed under The MIT License [see LICENSE for details]
# Written by Xinlei Chen
# 南石北岸生2019.4.7
# https://mp.csdn.net/postedit
# --------------------------------------------------------
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import tensorflow as tf
import tensorflow.contrib.slim as slim
from tensorflow.contrib.slim import losses
from tensorflow.contrib.slim import arg_scope

import numpy as np

from layer_utils.snippets import generate_anchors_pre, generate_anchors_pre_tf
from layer_utils.proposal_layer import proposal_layer, proposal_layer_tf
from layer_utils.proposal_top_layer import proposal_top_layer, proposal_top_layer_tf
from layer_utils.anchor_target_layer import anchor_target_layer
from layer_utils.proposal_target_layer import proposal_target_layer
from utils.visualization import draw_bounding_boxes

from model.config import cfg

class Network(object):
  def __init__(self):#构造方法,自动生成下列变量,用了self,可以不传入值得生成变量。
    self._predictions = {}#
    self._losses = {}
    self._anchor_targets = {}
    self._proposal_targets = {}
    self._layers = {}
    self._gt_image = None
    self._act_summaries = []
    self._score_summaries = {}
    self._train_summaries = []
    self._event_summaries = {}
    self._variables_to_fix = {}
  #最后还原图像的时候加上均值并且进行通道变换
  def _add_gt_image(self):
    # add back mean
    image = self._image + cfg.PIXEL_MEANS
    # BGR to RGB (opencv uses BGR)
    resized = tf.image.resize_bilinear(image, tf.to_int32(self._im_info[:2] / self._im_info[2]))
    self._gt_image = tf.reverse(resized, axis=[-1])
  #以下都是tensorboard用到的summary
  def _add_gt_image_summary(self):
    # use a customized visualization function to visualize the boxes
    if self._gt_image is None:
      self._add_gt_image()
    image = tf.py_func(draw_bounding_boxes, 
                      [self._gt_image, self._gt_boxes, self._im_info],
                      tf.float32, name="gt_boxes")
    
    return tf.summary.image('GROUND_TRUTH', image)

  def _add_act_summary(self, tensor):
    tf.summary.histogram('ACT/' + tensor.op.name + '/activations', tensor)
    tf.summary.scalar('ACT/' + tensor.op.name + '/zero_fraction',
                      tf.nn.zero_fraction(tensor))

  def _add_score_summary(self, key, tensor):
    tf.summary.histogram('SCORE/' + tensor.op.name + '/' + key + '/scores', tensor)

  def _add_train_summary(self, var):
    tf.summary.histogram('TRAIN/' + var.op.name, var)
  #rpn对block4的feature maps 利用18个1x1的卷积得到一个18通道的特征图,对于特征图上每一个点,都对应一个长度为18的向量
  #这个向量对应这9个尺寸的anchor,每个anchor对应了前景和背景两类。
  def _reshape_layer(self, bottom, num_dim, name):#num_dim是要强制转换的通道数。
    #整体思路:首先进行通道顺序变换,然后强制将1x18通道形状转换为2x9的通道形状
    input_shape = tf.shape(bottom)#读取数据维度
    with tf.variable_scope(name) as scope:#打开变量域,定位这个变量
      # change the channel to the caffe format
	  #将通道顺序变换
      to_caffe = tf.transpose(bottom, [0, 3, 1, 2])
      # then force it to have channel 2
	  #首先进行tf.concat,得到一个shape,按照这个shape进行reshape,
      #	  
      reshaped = tf.reshape(to_caffe,
                            tf.concat(axis=0, values=[[1, num_dim, -1], [input_shape[2]]]))
      # then swap the channel back
	  #然后将通道顺序换回原来的通道。
      to_tf = tf.transpose(reshaped, [0, 2, 3, 1])
      return to_tf
	  #针对以上,给出1组示例,帮助理解。
#feature map 大小为38x38x24,24是因为我设置的anchor参数为[4,8,16,32]和[0.5,1,2]。每个anchor centre有3x4=12个anchor框,每个框有前景和背景2类得分值。所以是24.

#softmax用于将得分转换为概率
#key:tf.nn.softmax()
  def _softmax_layer(self, bottom, name):
    if name.startswith('rpn_cls_prob_reshape'):
      input_shape = tf.shape(bottom)#输入的shape
      bottom_reshaped = tf.reshape(bottom, [-1, input_shape[-1]])#重新排版一下得分矩阵以满足tf.nn.softmax的输入要求
      reshaped_score = tf.nn.softmax(bottom_reshaped, name=name)#将得分矩阵转换为概率矩阵。
      return tf.reshape(reshaped_score, input_shape)#转换回输入的数据组织顺序
    return tf.nn.softmax(bottom, name=name)#如果不是rpn_cls_prob_reshape,即不是经过reshape的rpn_cls_prob,就直接满足tf.nn.softmax了,可以直接调用并返回结果
  #测试的时候有两种模式,一种是top,一种是nms,都是对众多框的选测方法,nms快,top慢,但是文档解释说top更好,默认是nms。
  def _proposal_top_layer(self, rpn_cls_prob, rpn_bbox_pred, name):
  #这个函数跟proposal_layer()功能类似
    with tf.variable_scope(name) as scope:
      if cfg.USE_E2E_TF:#USE_E2E_TF是端端的tf模型,这个参数默认为True。相对的是非端端的tf模型,可以输入到多个tf实例模型里面运行。
	  #端到端的tf模型只在测试的前馈过程中测试过。这个参数最好别动,不然下面代码可能会出BUG
	   #proposal_top_layer的函数有两种,一种是非tf的,一种是tf的。这个版本的faster用的tf实现的。毕竟tf可以调用gpu,更快。
        rois, rpn_scores = proposal_top_layer_tf(
          rpn_cls_prob,
          rpn_bbox_pred,
          self._im_info,
          self._feat_stride,
          self._anchors,
          self._num_anchors
        )#选择前TEST.RPN_TOP_N个,这个参数默认是C.TRAIN.RPN_PRE_NMS_TOP_N = 12000
		#需要注意的是,对于得到的框数m,m小于12000的话,会从5000个值里面随机选择m个框,所以会选到空白,导致丢失重要的框,不过这种情况很少发生
      else:
	  #如果不是端端的tfmodel,就调用tf.py_func,将tensor转换为numpy array格式进行np的处理,然后输出numpy array,并转换为tensor后返回。
        rois, rpn_scores = tf.py_func(proposal_top_layer,
                              [rpn_cls_prob, rpn_bbox_pred, self._im_info,
                               self._feat_stride, self._anchors, self._num_anchors],
                              [tf.float32, tf.float32], name="proposal_top")
        
      rois.set_shape([cfg.TEST.RPN_TOP_N, 5])
      rpn_scores.set_shape([cfg.TEST.RPN_TOP_N, 1])
    #以上总之就是proposals挑选的两种方法nms、TOP中的TOP。TOP又分两种模式,端到端的tf处理或者调用np处理,增加tensor接口的灵活性,结果没差。
    return rois, rpn_scores
  #和上面对应,下面的是nms模式。函数名字的区别就是有无top。
  #_proposal_layer从所有anchor框中选择出选择C.TRAIN.RPN_POST_NMS_TOP_N = 2000个作为rois供给fast rcnn部分,即rois, roi_scores = self._proposal_layer(rpn_cls_prob, rpn_bbox_pred, "rois")  
  def _proposal_layer(self, rpn_cls_prob, rpn_bbox_pred, name):
    with tf.variable_scope(name) as scope:
      if cfg.USE_E2E_TF:
        rois, rpn_scores = proposal_layer_tf(
          rpn_cls_prob,
          rpn_bbox_pred,
          self._im_in
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值