Keras 自定义损失函数 dtype 错误
Posted
技术标签:
【中文标题】Keras 自定义损失函数 dtype 错误【英文标题】:Keras custom loss function dtype error 【发布时间】:2017-12-20 00:53:21 【问题描述】:我有一个 NN,它有两个相同的 CNN(类似于 Siamese 网络),然后合并输出,并打算在合并的输出上应用自定义损失函数,如下所示:
----------------- -----------------
| input_a | | input_b |
----------------- -----------------
| base_network | | base_network |
------------------------------------------
| processed_a_b |
------------------------------------------
在我的自定义损失函数中,我需要将 y 垂直分成两部分,然后对每一部分应用分类交叉熵损失。但是,我不断从我的损失函数中得到 dtype 错误,例如:
ValueError Traceback(最近调用 最后)在() ----> 1 model.compile(loss=categorical_crossentropy_loss, optimizer=RMSprop())
/usr/local/lib/python3.5/dist-packages/keras/engine/training.py 在 编译(自我,优化器,损失,指标,损失权重, sample_weight_mode, **kwargs) 第909章 第910章 --> 911 样本重量,掩码) 912 如果 len(self.outputs) > 1: 第913章
/usr/local/lib/python3.5/dist-packages/keras/engine/training.py 在 加权(y_true,y_pred,权重,掩码) 451#应用样本加权 452 如果权重不是无: --> 453 score_array *= 权重 454 score_array /= K.mean(K.cast(K.not_equal(weights, 0), K.floatx())) 455 返回 K.mean(score_array)
/usr/local/lib/python3.5/dist-packages/tensorflow/python/ops/math_ops.py 在 binary_op_wrapper(x, y) 827 如果不是实例(y,sparse_tensor.SparseTensor): 828尝试: --> 829 y = ops.convert_to_tensor(y, dtype=x.dtype.base_dtype, name="y") 830 除了类型错误: 831 # 如果 RHS 不是张量,它可能是张量感知对象
/usr/local/lib/python3.5/dist-packages/tensorflow/python/framework/ops.py 在 convert_to_tensor(值,dtype,名称,preferred_dtype) 第674章 第675章 --> 676 as_ref=False) 677 第678章
/usr/local/lib/python3.5/dist-packages/tensorflow/python/framework/ops.py 在 internal_convert_to_tensor(value, dtype, name, as_ref, 首选dtype) 739 如果 ret 为无,则为 740: --> 741 ret = conversion_func(值,dtype=dtype,name=name,as_ref=as_ref) 742 743 如果 ret 未实现:
/usr/local/lib/python3.5/dist-packages/tensorflow/python/framework/ops.py 在 _TensorTensorConversionFunction(t, dtype, name, as_ref) 第612章 613 “张量转换为 dtype %s 的张量请求 dtype %s: %r” --> 614 % (dtype.name, t.dtype.name, str(t))) 第615章 第616章
ValueError: Tensor 转换请求 dtype float64 for Tensor with dtype float32: 'Tensor("processed_a_b_sample_weights_1:0", shape=(?,), dtype=float32)'
这是重现错误的 MWE:
import tensorflow as tf
from keras import backend as K
from keras.layers import Input, Dense, merge, Dropout
from keras.models import Model, Sequential
from keras.optimizers import RMSprop
import numpy as np
# define the inputs
input_dim = 10
input_a = Input(shape=(input_dim,), name='input_a')
input_b = Input(shape=(input_dim,), name='input_b')
# define base_network
n_class = 4
base_network = Sequential(name='base_network')
base_network.add(Dense(8, input_shape=(input_dim,), activation='relu'))
base_network.add(Dropout(0.1))
base_network.add(Dense(n_class, activation='relu'))
processed_a = base_network(input_a)
processed_b = base_network(input_b)
# merge left and right sections
processed_a_b = merge([processed_a, processed_b], mode='concat', concat_axis=1, name='processed_a_b')
# create the model
model = Model(inputs=[input_a, input_b], outputs=processed_a_b)
# custom loss function
def categorical_crossentropy_loss(y_true, y_pred):
# break (un-merge) y_true and y_pred into two pieces
y_true_a, y_true_b = tf.split(value=y_true, num_or_size_splits=2, axis=1)
y_pred_a, y_pred_b = tf.split(value=y_pred, num_or_size_splits=2, axis=1)
loss = K.categorical_crossentropy(output=y_pred_a, target=y_true_a) + K.categorical_crossentropy(output=y_pred_b, target=y_true_b)
return K.mean(loss)
# compile the model
model.compile(loss=categorical_crossentropy_loss, optimizer=RMSprop())
【问题讨论】:
哪一行给出了错误? 另外,您好,欢迎来到 Stack Overflow,请花点时间通过 welcome tour 了解您在此处的方式(并获得您的第一个徽章),阅读如何创建 @ 987654322@ 并查看How to Ask Good Questions,这样您就有机会获得反馈和有用的答案。 @GrayCygnus 错误来自第一次使用损失函数的编译行。 好的,我明白了,您正在根据您的标签使用 tensorflow 作为后端。你试过用 theano 代替吗? @GrayCygnus 请查看更新后的问题。它与重量有关! 【参考方案1】:正如您的错误所示,您正在使用float32
数据,它需要float64
。有必要将错误追溯到其特定的行,以明确要纠正的张量并能够更好地帮助您。
不过,它似乎与K.mean()
方法有关,但ValueError
s也可以通过K.categorical_crossentropy()
方法生成。因此,问题可能出在您的张量 loss
、y_pred
s 或两者 y_true
s 上。鉴于这些情况,我发现您可以尝试解决两件事:
您可以将您的张量cast(假设它是loss
)设置为所需的(float64)类型,如下所示:
from keras import backend as K
new_tensor = K.cast(loss, dtype='float64')
您可以通过将参数dtype
传递给Input()
调用(如these 示例中的建议),在开头声明您的输入为float64 类型,如下所示:
input_a = Input(shape=(input_dim,), name='input_a', dtype='float64')
【讨论】:
以上是关于Keras 自定义损失函数 dtype 错误的主要内容,如果未能解决你的问题,请参考以下文章
Keras 中的自定义损失函数(IoU 损失函数)和梯度误差?
使用自定义损失函数编译 Keras 模型时出现 TypeError