tensorflow boolean_mask如何在两个张量之间掩盖?

时间:2019-04-08 09:59:21

标签: python tensorflow keras

我有如下代码:

def yolo_filter_boxes(box_confidence, boxes, box_class_probs, threshold = .6):
    """Filters YOLO boxes by thresholding on object and class confidence.

    Arguments:
    box_confidence -- tensor of shape (3, 3, 5, 1)
    boxes -- tensor of shape (3, 3, 5, 4)
    box_class_probs -- tensor of shape (3, 3, 5, 80)
    threshold -- real value, if [ highest class probability score < threshold], then get rid of the corresponding box

    Returns:
    scores -- tensor of shape (None,), containing the class probability score for selected boxes
    boxes -- tensor of shape (None, 4), containing (b_x, b_y, b_h, b_w) coordinates of selected boxes
    classes -- tensor of shape (None,), containing the index of the class detected by the selected boxes

    Note: "None" is here because you don't know the exact number of selected boxes, as it depends on the threshold. 
    For example, the actual output size of scores would be (10,) if there are 10 boxes.
    """

    # Step 1: Compute box scores
    box_scores = np.multiply(box_confidence, box_class_probs)

    # Step 2: Find the box_classes thanks to the max box_scores, keep track of the corresponding score
    box_classes = K.argmax(box_scores, -1)
    box_class_scores = K.max(box_scores, -1)

    # Step 3: Create a filtering mask based on "box_class_scores" by using "threshold". The mask should have the
    # same dimension as box_class_scores, and be True for the boxes you want to keep (with probability >= threshold)
    filtering_mask = K.greater_equal(box_class_scores,threshold)
    # Step 4: Apply the mask to scores, boxes and classes

    print(filtering_mask.shape)
    print(filtering_mask.eval())

    print(box_class_scores.shape)
    print(box_class_scores.eval())
    scores = tf.boolean_mask(box_class_scores, filtering_mask)
    print(scores.eval())
    boxes = tf.boolean_mask(boxes, filtering_mask)
    classes = tf.boolean_mask(box_classes, filtering_mask)

    return scores, boxes, classes


with tf.Session() as test_a:
    box_confidence = tf.random_normal([3, 3, 5, 1], mean=1, stddev=4, seed = 1)
    boxes = tf.random_normal([3, 3, 5, 4], mean=1, stddev=4, seed = 1)
    box_class_probs = tf.random_normal([3, 3, 5, 80], mean=1, stddev=4, seed = 1)
    scores, boxes, classes = yolo_filter_boxes(box_confidence, boxes, box_class_probs, threshold = 0.5)
    print("scores[2] = " + str(scores[2].eval()))
    print("boxes[2] = " + str(boxes[2].eval()))
    print("classes[2] = " + str(classes[2].eval()))
    print("scores.shape = " + str(scores.shape))
    print("boxes.shape = " + str(boxes.shape))
    print("classes.shape = " + str(classes.shape))

这是输出:

(3, 3, 5)
[[[ True  True  True  True  True]
  [ True  True  True  True  True]
  [ True False  True  True  True]]

 [[ True  True  True  True  True]
  [ True  True  True  True  True]
  [ True  True  True  True  True]]

 [[ True  True  True  True False]
  [ True  True  True  True  True]
  [ True  True  True  True  True]]]
(3, 3, 5)
[[[  45.00004959   21.20238304   17.39275742   26.73288918   49.47431946]
  [  22.16205978   27.96604347   12.38916492   33.66600418   62.04590225]
  [ 113.03194427    2.68868852    6.33391762   45.17211914   10.5103178 ]]

 [[   8.22186852   35.88579941   48.54780579   12.48789883   32.40937042]
  [  75.73269653   17.52830696   62.99983597   29.0468502    42.82471848]
  [  72.42234039  108.19727325   36.93912888   40.9789238    36.91137314]]

 [[   1.57321405    3.35663748   16.33576775    5.16499805   19.43038177]
  [  48.13769913   68.20082092   47.06818008    1.82166731   67.30760956]
  [  33.01203537   63.93298721    9.71860027   49.06838989   60.74739456]]]
[  22.63684464   10.29589462   58.76845551   74.67560577   20.25722504
   47.24279022    6.96320772   22.59087944   86.61974335    1.05248117
   57.47060394   92.50878143   16.8335762    23.29385757   78.58971405
    6.95861435   65.61254883   45.47106171   43.53435135   10.0660677
   60.34520721   28.5535984    15.9668026    45.14865494    5.49425364
    2.35473752   29.40540886    2.5579865    46.96302032    9.39739799
   45.78501892   49.42660904   34.68322754   40.72031784   58.91592407
   35.39850616   56.24537277    6.80519342    9.52552414  138.54457092
   14.07888412   56.37608719   69.59171295   25.83714676]
scores[2] = 62.0051
boxes[2] = [-1.89158893  0.7749185   3.57417917 -0.05729628]
classes[2] = 36
scores.shape = (?,)
boxes.shape = (?, 4)
classes.shape = (?,)

我有一个简单的问题。 scores的结果如何产生?它有44个元素,而filtering_maskbox_class_scores有45个元素(3 * 3 * 5),filtering_mask有2个假值,必须得分43个元素。即使filter_mask具有1个假值,分数中的数字均不匹配box_class_scores。 有人可以向我解释如何计算scores

1 个答案:

答案 0 :(得分:1)

问题不在于掩盖效果是否如您所愿。问题在于您在图形中使用随机值,其行为可能会有些令人惊讶。每次您呼叫eval()实际上是在默认会话中对run的呼叫。问题在于TensorFlow中随机值的工作方式。每次在会话上调用run时,都会生成一个新的随机值。这意味着每个eval调用都基于box_confidenceboxesbox_class_probs的不同值产生结果。有一些解决方法,要么简单地不使用随机值生成器作为输入,要么在对run的同一调用中评估所有输出(而不与eval一起使用)。由于您似乎正在编写测试代码,因此解决该问题的一种简单方法是将输入替换为由NumPy随机值构成的常量。

import tensorflow as tf
import numpy as np

def yolo_filter_boxes(box_confidence, boxes, box_class_probs, threshold = .6):
    # ...

with tf.Session() as test_a:
    np.random.seed(1)
    box_confidence = tf.constant(np.random.normal(loc=1, scale=4, size=[3, 3, 5, 1]), dtype=tf.float32)
    boxes = tf.constant(np.random.normal(loc=1, scale=4, size=[3, 3, 5, 4]), dtype=tf.float32)
    box_class_probs = tf.constant(np.random.normal(loc=1, scale=4, size=[3, 3, 5, 80]), dtype=tf.float32
    scores, boxes, classes = yolo_filter_boxes(box_confidence, boxes, box_class_probs, threshold = 0.5)
    print("scores[2] = " + str(scores[2].eval()))
    print("boxes[2] = " + str(boxes[2].eval()))
    print("classes[2] = " + str(classes[2].eval()))
    print("scores.shape = " + str(scores.shape))
    print("boxes.shape = " + str(boxes.shape))
    print("classes.shape = " + str(classes.shape))

或者您仍然可以使用TensorFlow随机数,但可以使用变量作为输入。与变量的区别在于,它们仅在初始化时评估其初始值,然后在会话之间保留其值(直到再次更改它),因此您不必每次都生成新的随机值。

import tensorflow as tf

def yolo_filter_boxes(box_confidence, boxes, box_class_probs, threshold = .6):
    # ...

with tf.Session() as test_a:
    box_confidence = tf.Variable(tf.random_normal([3, 3, 5, 1], mean=1, stddev=4, seed = 1)))
    boxes = tf.Variable(tf.random_normal([3, 3, 5, 4], mean=1, stddev=4, seed = 1))
    box_class_probs = tf.Variable(tf.random_normal([3, 3, 5, 80], mean=1, stddev=4, seed = 1))
    # You must initialize the variables
    test_a.run(tf.global_variables_initializer())
    scores, boxes, classes = yolo_filter_boxes(box_confidence, boxes, box_class_probs, threshold = 0.5)
    print("scores[2] = " + str(scores[2].eval()))
    print("boxes[2] = " + str(boxes[2].eval()))
    print("classes[2] = " + str(classes[2].eval()))
    print("scores.shape = " + str(scores.shape))
    print("boxes.shape = " + str(boxes.shape))
    print("classes.shape = " + str(classes.shape))