0

我正在尝试使用张量流度量来跟踪 SSD 网络在训练/验证期间产生了多少误报。

我尝试自己编写,但是当它应该产生一个整数时它会输出一个浮点数(例如,有 1.3 个假阴性预测没有意义)。这告诉我我的代码要么做错了事,要么 tensorflow 正在添加一个我没有补偿的标量。代码如下。

我还尝试使用我已经为其他类型的指标工作的内置指标。问题是 SSD 输出张量的输出具有传递给度量的形状,每个项目都有形状(#boxes,#classes),而内置的tf.keras.metrics.FalseNegatives度量类期望单个值输入.

归根结底,我这样做是为了了解网络在哪里出现问题,这样我就可以看看添加其他类型的类是否会改善它。如果有更好的方法,请告诉我!这是我的第一个迁移学习项目

代码。为传递给构建器函数的每个类生成假阴性度量,该构建器函数为每个类返回一个度量函数。通常,这还包括其他指标,但我在这里对其进行了修剪,仅包括计算 # 假阴性:

def build_class_metric_functions(class_list):
'''
based on the number of input classes, generate a list of tensorflow compliant metric functions
Returns:
    a list of metric functions separated for each classification
'''

class_funs = []

for class_i, class_str in enumerate(class_list):

    def _build_function_FN(y_true, y_pred, class_i=class_i):  # adding class_i triggers early binding
        ''' number of false negatives per image 
        
        Arguments:
        y_true (array): A Numpy array of shape `(batch_size, #boxes, #classes + 12)`,
            where `#boxes` is the total number of boxes that the model predicts
            per image. Be careful to make sure that the index of each given
            box in `y_true` is the same as the index for the corresponding
            box in `y_pred`. The last axis must have length `#classes + 12` and contain
            `[classes one-hot encoded, 4 ground truth box coordinate offsets, 8 arbitrary entries]`
            in this order, including the background class. The last eight entries of the
            last axis are not used by this function and therefore their contents are
            irrelevant, they only exist so that `y_true` has the same shape as `y_pred`,
            where the last four entries of the last axis contain the anchor box
            coordinates, which are needed during inference. Important: Boxes that
            you want the cost function to ignore need to have a one-hot
            class vector of all zeros.
        y_pred (Keras tensor): The model prediction. The shape is identical
            to that of `y_true`, i.e. `(batch_size, #boxes, #classes + 12)`.
            The last axis must contain entries in the format
            `[classes one-hot encoded, 4 predicted box coordinate offsets, 8 arbitrary entries]`.
        
        '''
        batch_size = tf.shape(y_pred)[0]  # Output dtype: tf.int32
        y_true_classes = y_true[:, :, 0:-12]  # background is index 0
        y_true_class = tf.argmax(y_true_classes, axis=-1)
        y_pred_classes = y_pred[:, :, 0:-12]
        y_pred_class = tf.argmax(y_pred_classes, axis=-1)

        zero = y_pred_classes[:, :, 0] * tf.constant(0.0)  # all zeros
        one = zero + tf.constant(1.0)  # all ones

        wanted_class = tf.constant(class_i, dtype=tf.float32)
        _class = tf.cast(zero + wanted_class, dtype=tf.int64)

        tp = tf.where(
            tf.equal(_class, y_true_class),  # if ground truth is positive...
            tf.where(tf.equal(y_true_class, y_pred_class), zero, one),  # ...and pred is wrong return 1
            zero  # do not count positive predictions
        )

        # tf divides by batch size and number of images, this makes the output floats rather than
        # tensorflow_mul attempts to compensate for this
        #       also, when writing to file, it may zero it out if the value is low (< ~0.001)
        tensorflow_mul = tf.to_float(batch_size)
        return tf.reduce_sum(tp) * tensorflow_mul

    fun_sufix = class_str + str(class_i)  # appending class_i ensures metrics are unique
    fn_fun = _build_function_FN
    fn_fun.__name__ = 'class_FN_' + fun_sufix
    class_funs.append(fn_fun)

return class_funs

以下是在训练之前传递指标的方式:

METRICS = [
    # ...other metrics added here...
] + build_class_metric_functions(['background', 'apple', 'orange'])

model.compile(optimizer=adam, loss=ssd_loss.compute_loss, metrics=METRICS)
4

0 回答 0