python - 为自定义损失函数分配张量对象
问题描述
我正在尝试为 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
我将不胜感激有关如何解决此问题的建议。谢谢。
解决方案
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
此代码将执行以下操作:
- 我们从您的 y_true 中减去 0.15(您的阈值),以便新值的阈值现在为 0。
- 我们将结果乘以一个大数字(我在这里选择了 1000,数字越大,“软阈值”就越陡峭。这意味着,所有高于阈值的值现在都是非常高的正值,所有值都低于你的阈值现在将是高负值。
- 我们将 sigmoid 函数应用于结果值。对于所有高正值,此函数将为 1,对于所有高负值,此函数将为 -0(两者之间有软过渡)。
- 现在,我们可以将我们的损失乘以logistic_values或1-logistic_values,它基本上充当掩码,分别屏蔽所有0 或1 的值。所有未被屏蔽的值现在可以乘以它们各自的因子 0.8 或 0.2。
推荐阅读
- r - 如何在 R 中使用命名空间处理 SVG?
- python - 如何让输入的数字保存在文本文件中
- php - Active Directory、PHP 的 ldap_search 和 objectGUID
- python - 从数据类中复制 setattr 和 delattr 的行为
- jquery - 谷歌分析事件触发,但使用 gtag.js 在电子商务中没有数据显示
- flutter - 颤振块没有第二次添加事件
- javascript - 无法将对象推入数组,因为它是未定义的 Javascript
- c# - 更改扩展窗口的窗口标题字体
- java - Lucene 建议:使用 CompletionQuery 时出现“不是 SuggestField”异常
- javascript - Redux 从本地文件加载初始数据,然后从状态加载