gpt4 book ai didi

tensorflow - 在y_true和y_pred的不同大小的keras中实现自定义损失功能

转载 作者:行者123 更新时间:2023-12-04 01:12:37 25 4
gpt4 key购买 nike

我是Keras的新手。在使用TensorFlow后端在keras中编写自定义损失函数以获取以下损失方程式时,我需要一些帮助。

传递给损失函数的参数为​​:

  • y_true将具有(batch_size, N, 2)的形状。在这里,我们在批次中的每个样本中传递N (x, y)坐标。
  • y_pred将具有(batch_size, 256, 256, N)的形状。在这里,我们将在批次中的每个样本中传递N个256 x 256像素的预测热图。
  • i[0, 255] j[0, 255] Mn(i, j)代表第n个预测热图在像素位置 (i, j)的值。
    Mn(i, j) = Guassian2D((i, j), y_truen, std)其中
    std = standard deviation,两个维度(5 px)的标准偏差相同。

    y_truen是第n个(x,y)坐标。这是平均值。

    有关此详细信息,请检查本文中所述的l2损失
    Human Pose Estimation

    注意:我以y_true和y_pred的形状提到了batch_size。我假设Keras在整个批次上调用损失函数,而不是在批次中的单个样本上调用损失函数。如果我错了,请纠正我。
    def l2_loss(y_true, y_pred):
    loss = 0
    n = y_true.shape[0]
    for j in range(n):
    for i in range(num_joints):
    yv, xv = tf.meshgrid(tf.arange(0, im_height), tf.arange(0, im_width))
    z = np.array([xv, yv]).transpose(1, 2, 0)
    ground = np.exp(-0.5*(((z - y_true[j, i, :])**2).sum(axis=2))/(sigma**2))
    loss = loss + np.sum((ground - y_pred[j,:, :, i])**2)
    return loss/num_joints

    这是我到目前为止编写的代码。我知道这不会运行,因为我们不能在keras损失函数中使用直接的numpy ndarrays。另外,我需要消除循环!

    最佳答案

    您几乎可以将numpy函数转换为Keras后端函数。唯一需要注意的是设置正确的广播形状。

    def l2_loss_keras(y_true, y_pred):
    # set up meshgrid: (height, width, 2)
    meshgrid = K.tf.meshgrid(K.arange(im_height), K.arange(im_width))
    meshgrid = K.cast(K.transpose(K.stack(meshgrid)), K.floatx())

    # set up broadcast shape: (batch_size, height, width, num_joints, 2)
    meshgrid_broadcast = K.expand_dims(K.expand_dims(meshgrid, 0), -2)
    y_true_broadcast = K.expand_dims(K.expand_dims(y_true, 1), 2)
    diff = meshgrid_broadcast - y_true_broadcast

    # compute loss: first sum over (height, width), then take average over num_joints
    ground = K.exp(-0.5 * K.sum(K.square(diff), axis=-1) / sigma ** 2)
    loss = K.sum(K.square(ground - y_pred), axis=[1, 2])
    return K.mean(loss, axis=-1)

    验证:

    def l2_loss_numpy(y_true, y_pred):
    loss = 0
    n = y_true.shape[0]
    for j in range(n):
    for i in range(num_joints):
    yv, xv = np.meshgrid(np.arange(0, im_height), np.arange(0, im_width))
    z = np.stack([xv, yv]).transpose(1, 2, 0)
    ground = np.exp(-0.5*(((z - y_true[j, i, :])**2).sum(axis=2))/(sigma**2))
    loss = loss + np.sum((ground - y_pred[j,:, :, i])**2)
    return loss/num_joints

    batch_size = 32
    num_joints = 10
    sigma = 5
    im_width = 256
    im_height = 256

    y_true = 255 * np.random.rand(batch_size, num_joints, 2)
    y_pred = 255 * np.random.rand(batch_size, im_height, im_width, num_joints)

    print(l2_loss_numpy(y_true, y_pred))
    45448272129.0

    print(K.eval(l2_loss_keras(K.variable(y_true), K.variable(y_pred))).sum())
    4.5448e+10

    该数字在默认的 dtype float32下被截断。如果将 dtype设置为float64来运行它:

    y_true = 255 * np.random.rand(batch_size, num_joints, 2)
    y_pred = 255 * np.random.rand(batch_size, im_height, im_width, num_joints)

    print(l2_loss_numpy(y_true, y_pred))
    45460126940.6

    print(K.eval(l2_loss_keras(K.variable(y_true), K.variable(y_pred))).sum())
    45460126940.6

    编辑:

    看来Keras要求 y_truey_pred具有相同的维数。例如,在以下测试模型上:

    X = np.random.rand(batch_size, 256, 256, 3)
    model = Sequential([Dense(10, input_shape=(256, 256, 3))])
    model.compile(loss=l2_loss_keras, optimizer='adam')
    model.fit(X, y_true, batch_size=8)

    ValueError: Cannot feed value of shape (8, 10, 2) for Tensor 'dense_2_target:0', which has shape '(?, ?, ?, ?)'

    为了解决这个问题,您可以在将 expand_dims输入到模型之前,使用 y_true添加一个虚拟维度:

    def l2_loss_keras(y_true, y_pred):
    ...

    y_true_broadcast = K.expand_dims(y_true, 1) # change this line

    ...

    model.fit(X, np.expand_dims(y_true, axis=1), batch_size=8)

    关于tensorflow - 在y_true和y_pred的不同大小的keras中实现自定义损失功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47719448/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com