首页 > 解决方案 > 为自定义损失函数分配张量对象

问题描述

我正在尝试为 Keras 定义一个自定义 rmse 损失函数。我编写了下面的函数来惩罚数据值小于 0.15 时的损失,否则。

import keras.backend as K

def custom_rmse(y_true, y_pred):
  loss = K.square(y_pred - y_true)
  for i in range(len(y_true)):
    for j in range(y_true.shape[1]):
      tmp = float(y_true[i][j])
      if (tmp < 0.15):
        loss[i][j] *= 0.2
      else:
        loss[i][j] *=0.8
  loss = K.sqrt(K.sum(loss, axis=1)) 
  return loss

但是当我运行模型并尝试修复它时,我不断收到此错误

 /usr/local/lib/python3.7/dist-packages/keras/engine/training.py:853 train_function  *
        return step_function(self, iterator)
    <ipython-input-95-efab27dd2563>:8 custom_rmse  *
        if (tmp < 0.15):
    /usr/local/lib/python3.7/dist-packages/tensorflow/python/autograph/operators/control_flow.py:1172 if_stmt
        _tf_if_stmt(cond, body, orelse, get_state, set_state, symbol_names, nouts)
    /usr/local/lib/python3.7/dist-packages/tensorflow/python/autograph/operators/control_flow.py:1219 _tf_if_stmt
        cond, aug_body, aug_orelse, strict=True)
    /usr/local/lib/python3.7/dist-packages/tensorflow/python/util/dispatch.py:206 wrapper
        return target(*args, **kwargs)
    /usr/local/lib/python3.7/dist-packages/tensorflow/python/util/deprecation.py:549 new_func
        return func(*args, **kwargs)
    /usr/local/lib/python3.7/dist-packages/tensorflow/python/ops/control_flow_ops.py:1254 cond
        return cond_v2.cond_v2(pred, true_fn, false_fn, name)
    /usr/local/lib/python3.7/dist-packages/tensorflow/python/ops/cond_v2.py:88 cond_v2
        op_return_value=pred)
    /usr/local/lib/python3.7/dist-packages/tensorflow/python/framework/func_graph.py:1007 func_graph_from_py_func
        func_outputs = python_func(*func_args, **func_kwargs)
    /usr/local/lib/python3.7/dist-packages/tensorflow/python/autograph/operators/control_flow.py:1197 aug_body
        set_state(init_vars)
    /tmp/tmp_3e6lmrw.py:35 set_state
        (loss[i][j],) = vars_

    TypeError: 'Tensor' object does not support item assignment

我将不胜感激有关如何解决此问题的建议。谢谢。

标签: pythontensorflowmachine-learningkeras

解决方案


If-Else 语句通常不是损失函数的方法。大多数时候,最好以“软”的方式来实现您想要实现的目标。这可以通过(例如)通过以下方式对您的损失值使用陡峭的逻辑函数来完成:

def custom_rmse(y_true, y_pred):
    loss = K.square(y_pred - y_true)

    logistic_values = tf.sigmoid(1000 * (y_true - 0.15))
    loss = logistic_values * loss * 0.8 + (1-logistic_values * loss * 0.2)

    loss = K.sqrt(K.sum(loss, axis=1)) 
    return loss

此代码将执行以下操作:

  1. 我们从您的 y_true 中减去 0.15(您的阈值),以便新值的阈值现在为 0。
  2. 我们将结果乘以一个大数字(我在这里选择了 1000,数字越大,“软阈值”就越陡峭。这意味着,所有高于阈值的值现在都是非常高的正值,所有值都低于你的阈值现在将是高负值。
  3. 我们将 sigmoid 函数应用于结果值。对于所有高正值,此函数将为 1,对于所有高负值,此函数将为 -0(两者之间有软过渡)。
  4. 现在,我们可以将我们的损失乘以logistic_values1-logistic_values,它基本上充当掩码,分别屏蔽所有0 或1 的值。所有未被屏蔽的值现在可以乘以它们各自的因子 0.8 或 0.2。

推荐阅读