【问题标题】:how can i implement this custom loss function in tensorflow?如何在 tensorflow 中实现这个自定义损失函数?
【发布时间】:2021-06-07 07:36:45
【问题描述】:

我的损失函数:

我想为以下模型实现上述损失函数:

model_s=tf.keras.Sequential([
tf.keras.layers.Dense(100, input_shape=(50,),activation='tanh'),
tf.keras.layers.Dense(100,activation='tanh'),
tf.keras.layers.Dense(50,activation='sigmoid')])

model_s.compile(optimizer='adam',
             loss=loss_fn,
             metrics="accuracy",)


model_s.fit(x_train,y_train,epochs=5,batch_size=512)

我以两种方式实现了该功能,但在这两种情况下我都遇到了错误。 案例一:

def loss_fn(y_true,y_pred):
    y=tf.math.argmax(y_true)
    loss=(-(tf.math.log(y_pred[y])+tf.reduce_sum(tf.math.log(1-y_pred[:y]))))
    return tf.reduce_mean(loss)

#example
y_true=tf.constant([0,0,0,0,1])
y_pred=tf.constant([0,0,0,0,.9])
loss_fn(y_true,y_pred)

<tf.Tensor: shape=(), dtype=float32, numpy=0.105360545>

错误案例一:

TypeError: Only integers, slices (`:`), ellipsis (`...`), tf.newaxis (`None`) and scalar tf.int32/tf.int64 tensors are valid indices, got <tf.Tensor 'loss_fn/ArgMax:0' shape=(50,) dtype=int64>

案例2:

def loss_fn(y_true,y_pred):
    i=0
    loss=[]
    for pre in y_pred:
        y=tf.math.argmax(y_true[i])
        loss.append(-(tf.math.log(pre[y])+tf.reduce_sum(tf.math.log(1-pre[:y]))))
        i += 1
    return tf.reduce_mean(loss, axis=-1)

#example
y_true=tf.constant([[0,0,0,0,1],[0,0,0,1,0]])
y_pred=tf.constant([[0,0,0,0,.99],[0,0,0,.9,.3]])
loss_fn(y_true,y_pred)
<tf.Tensor: shape=(), dtype=float32, numpy=0.057705436>

错误情况2:

ValueError: Tried to convert 'input' to a tensor and failed. Error: The tensor 'Tensor("loss_fn/while/Neg:0", shape=(), dtype=float32)' cannot be accessed here: it is defined in another function or code block. Use return values, explicit Python locals or TensorFlow collections to access it. Defined in: FuncGraph(name=loss_fn_while_body_3814, id=2579287922312); accessed from: FuncGraph(name=train_function, id=2579286968840).

我知道第一种情况由于其输入形式可能不适用于不同的批量大小,但我已经对第二种情况的细节进行了很多更改,但有一件事始终保持不变:显示错误且功能无效:(

【问题讨论】:

  • 为什么使用pre[:y] 我猜如果你像这样使用它,y 应该是一个标量,但它是一个形状为 50 的张量。
  • @SebastianR。 y 是标量。 y=tf.math.argmax(y_true[i])。 pre[:y] 获取y_pred向量中的pre-y值(根据损失函数)
  • 在第二种情况下在第一种情况下 tf.Tensor 'loss_fn/ArgMax:0' shape=(50,) 是你的错误的原因。我认为您的第二种方法失败了,因为您迭代的维度在图形计算时是未知的。在应用日志之前,您可能能够使用 tf.gather 构建解决方案或计算乘以 y_pred 的二进制掩码。
  • 公式中的y'是什么?
  • @gobrewers14 如果 x 是输入,那么 y 是真正的标签或输出

标签: python tensorflow keras loss-function


【解决方案1】:

不要尝试索引您的预测,只需使用您的真实标签(采用 one-hot 格式)作为掩码来获得第 i 个预测(您可以通过跨行的乘法和求和来完成此操作)。然后使用您的 argmax 为第二部分创建序列掩码。

试试这个:

import tensorflow as tf


def custom_loss_fn(y_true, y_pred, num_labels=5):
    idx = tf.math.argmax(y_true, 1)
    msk = tf.cast(tf.sequence_mask(idx, num_labels), tf.float32)
    # 1st part
    fst = -tf.math.log(tf.math.reduce_sum(y_true * y_pred, 1))
    # 2nd part
    snd = tf.math.reduce_sum(tf.math.log(1.0 - y_pred * msk, 1))
    return tf.math.reduce_mean(fst + snd)

测试 1

y_true = tf.constant([[0, 0, 0, 0, 1]], tf.float32)
y_pred = tf.constant([[0, 0, 0, 0, 0.9]])

custom_loss_fn(y_true, y_pred)
# <tf.Tensor: shape=(), dtype=float32, numpy=0.105360545>

测试 2

y_true = tf.constant([[0, 0, 0, 0, 1], [0, 0, 0, 1, 0]], tf.float32)
y_pred = tf.constant([[0, 0, 0, 0, 0.99], [0, 0, 0, 0.9, 0.3]])

custom_loss_fn(y_true, y_pred)
# <tf.Tensor: shape=(), dtype=float32, numpy=0.057705436>

【讨论】:

    猜你喜欢
    • 2019-12-16
    • 2020-07-29
    • 2021-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-25
    • 2018-10-28
    相关资源
    最近更新 更多