1

我在 Tensorflow 中的一些张量操作上被困了几个小时。我正在尝试使用 Tensorflow 后端在 Keras 框架中实现一些损失函数,但到目前为止没有成功(尽管我相信我越来越接近了)。所讨论的损失函数是YOLO算法的损失函数。这个函数的问题在于它是一个 $L_2$ 范数,但由一些系数加权,具体取决于 $y_true$ 的值。因此,为了构建我的损失函数,我必须研究 $y_true$ 的值,而 Tensorflow 似乎不允许这样做......无论如何,到目前为止,我已经想出了这个技巧:

def defineMarkUp(y_true):
    num_example = y_true.shape[0]
    grid_h, grid_w = config.GRID_H, config.GRID_W
    box_nbr = config.BOX_NBR
    class_nbr = config.CLASS_NBR
    coord_c = config.COORD_C
    noobj_c = config.NOOBJ_C
    s = 5 + class_nbr

    mask = np.zeros(y_true.shape)

    for i in range(num_example):
        for j in range(grid_h):
            for k in range(grid_w):
                for l in range(box_nbr):
                    if np.sum(y_true[i, j, k, l * s + 5 : (l + 1) * s]) > 0:
                        mask[i, j, k, l * s : l * s + 4] = np.sqrt(coord_c)
                        mask[i, j, k, l * s + 4 : (l + 1) * s] = 1.0
                    else:
                        mask[i, j, k, l * s + 4] = np.sqrt(noobj_c)

    return mask



def yoloLoss(markups):
    grid_h, grid_w = config.GRID_H, config.GRID_W
    box_nbr = config.BOX_NBR
    class_nbr = config.CLASS_NBR
    s = 5 + class_nbr

    def loss(y_true, y_pred):

        mask = np.zeros((1,  grid_h, grid_w, box_nbr * s))
        mask = mask.astype(np.float32)
        for k in range(box_nbr):
            mask[:, :, :, k * s + 2 : k * s + 4] = 1.0
        dim_y_true = tf.sqrt(tf.multiply(y_true, mask))
        dim_y_pred = tf.sqrt(tf.multiply(y_pred, mask))

        other_y_true = tf.multiply(y_true, 1 - mask)
        other_y_pred = tf.multiply(y_pred, 1 - mask)

        new_y_true = other_y_true + dim_y_true 
        new_y_pred = other_y_pred + dim_y_pred

        return tf.reduce_mean(tf.square(tf.multiply(tf.cast(markups, tf.float32), (new_y_true - new_y_pred))))

    return loss

一点解释:在这里,函数defineMarkUp将所有标签视为np.array并创建一些掩码(根据位置等包含不同的权重......),然后我称之为:

model.compile(loss = [yoloLoss(Y_train)], optimizer = 'adadelta')

问题是,当使用批处理时,由于所有数据集的维度与我们的批处理不同,因此掩码不再适合,这意味着我需要在将$y_true$ 作为张量的情况下即时构建“标记” 。所以我尝试了这样的事情:

def defineMarkUp(y_true):
    num_example = y_true.get_shape().as_list()[0]
    grid_h, grid_w = config.GRID_H, config.GRID_W
    box_nbr = config.BOX_NBR
    class_nbr = config.CLASS_NBR
    coord_c = config.COORD_C
    noobj_c = config.NOOBJ_C
    s = 5 + class_nbr

    mask = np.zeros(y_true.get_shape().as_list())

    for i in range(num_example):
        for j in range(grid_h):
            for k in range(grid_w):
                for l in range(box_nbr):
                    if np.sum(y_true[i, j, k, l * s + 5 : (l + 1) * s]) > 0:
                        mask[i, j, k, l * s : l * s + 4] = np.sqrt(coord_c)
                        mask[i, j, k, l * s + 4 : (l + 1) * s] = 1.0
                    else:
                        mask[i, j, k, l * s + 4] = np.sqrt(noobj_c)

    return mask

def yoloLossFinal(y_true, y_pred):
    grid_h, grid_w = config.GRID_H, config.GRID_W
    box_nbr = config.BOX_NBR
    class_nbr = config.CLASS_NBR
    s = 5 + class_nbr
    coord_c, noobj_c = config.COORD_C, config.NOOBJ_C

    markups = defineMarkUp(y_true)

    mask = np.zeros((1,  grid_h, grid_w, box_nbr * s))
    mask = mask.astype(np.float32)

    for k in range(box_nbr):
        mask[:, :, :, k * s + 2 : k * s + 4] = 1.0

    dim_y_true = tf.sqrt(tf.multiply(y_true, mask))
    dim_y_pred = tf.sqrt(tf.multiply(y_pred, mask))

    other_y_true = tf.multiply(y_true, 1 - mask)
    other_y_pred = tf.multiply(y_pred, 1 - mask)

    new_y_true = other_y_true + dim_y_true 
    new_y_pred = other_y_pred + dim_y_pred

    return tf.reduce_mean(tf.square(tf.multiply(tf.cast(markups, tf.float32), (new_y_true - new_y_pred))))

但现在我得到了这个错误:

回溯(最近一次调用):文件“network.py”,第 214 行,在 yolo.compile(loss = yoloLossFinal, optimizer = 'adadelta') 文件“/anaconda3/lib/python3.6/site-packages/keras/ engine/training.py”,第 830 行,编译 sample_weight,掩码)文件“/anaconda3/lib/python3.6/site-packages/keras/engine/training.py”,第 429 行,加权 score_array = fn(y_true , y_pred) 文件“network.py”,第 192 行,在 yoloLossFinal 标记 = defineMarkUp(y_true) 文件“network.py”,第 143 行,在 defineMarkUp 掩码 = np.zeros(y_true.get_shape().as_list()) TypeError : 'NoneType' 对象不能解释为整数

因此,我尝试了其他方法:

def defineMarkUp(y_true):
    sess = tf.Session()
    with sess.as_default():
        yy = y_true.eval()

    num_example = yy.shape[0]
    grid_h, grid_w = config.GRID_H, config.GRID_W
    box_nbr = config.BOX_NBR
    class_nbr = config.CLASS_NBR
    coord_c = config.COORD_C
    noobj_c = config.NOOBJ_C
    s = 5 + class_nbr

    mask = np.zeros(y_true.shape)

    for i in range(num_example):
        for j in range(grid_h):
            for k in range(grid_w):
                for l in range(box_nbr):
                    if np.sum(yy[i, j, k, l * s + 5 : (l + 1) * s]) > 0:
                        mask[i, j, k, l * s : l * s + 4] = np.sqrt(coord_c)
                        mask[i, j, k, l * s + 4 : (l + 1) * s] = 1.0
                    else:
                        mask[i, j, k, l * s + 4] = np.sqrt(noobj_c)

    return mask

但是现在我收到了这个很长的错误消息:

回溯(最后一次调用):文件“/anaconda3/lib/python3.6/site-packages/tensorflow/python/client/session.py”,第 1322 行,在 _do_call return fn(*args) 文件“/anaconda3/ lib/python3.6/site-packages/tensorflow/python/client/session.py”,第 1307 行,在 _run_fn 选项、feed_dict、fetch_list、target_list、run_metadata)文件“/anaconda3/lib/python3.6/site-packages /tensorflow/python/client/session.py",第 1409 行,在 _call_tf_sessionrun run_metadata) tensorflow.python.framework.errors_impl.InvalidArgumentError:您必须使用 dtype 浮点数和形状 [?,?, ?,?] [[节点:conv2d_4_target = Placeholderdtype=DT_FLOAT, shape=[?,?,?,?], _device="/job:localhost/replica:0/task:0/device:CPU:0"]]

在处理上述异常的过程中,又出现了一个异常:

回溯(最后一次调用):文件“network.py”,第 218 行,在 yolo.compile(loss = yoloLossFinal, optimizer = 'adadelta') 文件“/anaconda3/lib/python3.6/site-packages/keras/ engine/training.py”,第 830 行,编译 sample_weight,掩码)文件“/anaconda3/lib/python3.6/site-packages/keras/engine/training.py”,第 429 行,加权 score_array = fn(y_true , y_pred) 文件“network.py”,第 196 行,在 yoloLossFinal 标记 = defineMarkUp(y_true) 文件“network.py”,第 137 行,在 defineMarkUp yy = y_true.eval() 文件“/anaconda3/lib/python3.6 /site-packages/tensorflow/python/framework/ops.py”,第 710 行,在 eval 中返回 _eval_using_default_session(self, feed_dict, self.graph, session) 文件“/anaconda3/lib/python3.6/site-packages/tensorflow/python/framework/ops.py”,第 5180 行,在 _eval_using_default_session 返回 session.run(tensors, feed_dict) 文件“/anaconda3/lib/python3.6/site-packages/tensorflow/python/ client/session.py”,第 900 行,运行 run_metadata_ptr) 文件“/anaconda3/lib/python3.6/site-packages/tensorflow/python/client/session.py”,第 1135 行,在 _run feed_dict_tensor,options,run_metadata )文件“/anaconda3/lib/python3.6/site-packages/tensorflow/python/client/session.py”,第1316行,在_do_run run_metadata)文件“/anaconda3/lib/python3.6/site-packages/tensorflow /python/client/session.py”,第 1335 行,在 _do_call raise type(e)(node_def, op, message) tensorflow.python.framework.errors_impl.InvalidArgumentError:您必须使用 dtype float 和 shape [?,?,?,?] [[Node: conv2d_4_target = Placeholderdtype=DT_FLOAT, shape=[?,?,?,?], _device=" /job:localhost/replica:0/task:0/device:CPU:0"]]

由操作“conv2d_4_target”引起,定义在:文件“network.py”,第 218 行,在 yolo.compile(loss = yoloLossFinal, optimizer = 'adadelta') 文件“/anaconda3/lib/python3.6/site-packages/ keras/engine/training.py”,第 725 行,在 compile dtype=K.dtype(self.outputs[i])) 文件“/anaconda3/lib/python3.6/site-packages/keras/backend/tensorflow_backend.py “,第 508 行,在占位符 x = tf.placeholder(dtype, shape=shape, name=name) 文件“/anaconda3/lib/python3.6/site-packages/tensorflow/python/ops/array_ops.py”中,行1808,在占位符返回 gen_array_ops.placeholder(dtype=dtype, shape=shape, name=name) 文件“/anaconda3/lib/python3.6/site-packages/tensorflow/python/ops/gen_array_ops.py”,第 4848 行,在占位符“占位符”中,dtype=dtype, shape=shape, name=name) 文件“/anaconda3/lib/python3.6/site-packages/tensorflow/python/framework/op_def_library.py”,第 787 行,在 _apply_op_helper op_def=op_def) 文件“/ anaconda3/lib/python3.6/site-packages/tensorflow/python/framework/ops.py”,第 3392 行,在 create_op op_def=op_def) 文件“/anaconda3/lib/python3.6/site-packages/tensorflow/python /framework/ops.py”,第 1718 行,在py",第 1718 行,在py",第 1718 行,在init self._traceback = self._graph._extract_stack() # pylint: disable=protected-access

InvalidArgumentError(参见上面的回溯):您必须为占位符张量“conv2d_4_target”提供一个值,其 dtype 为 float 和 shape [?,?,?,?] [[Node: conv2d_4_target = Placeholderdtype=DT_FLOAT, shape=[?,?, ?,?], _device="/job:localhost/replica:0/task:0/device:CPU:0"]

]

我一直在不懈地尝试实现这个损失函数,所以我真的希望有人能帮助我理解出了什么问题:(。到目前为止,我还有一个更普遍的问题,这可能与我的问题有关:如何真正在 Tensorflow 中实现一个损失函数,意思是:我们可以做什么,不可以做什么?

十分感谢!

4

0 回答 0