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()方法有关,但ValueErrors也可以通过K.categorical_crossentropy()方法生成。因此,问题可能出在您的张量 lossy_preds 或两者 y_trues 上。鉴于这些情况,我发现您可以尝试解决两件事:

    您可以将您的张量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 为损失函数构建自定义指标,但有错误

Keras 中的自定义损失函数(IoU 损失函数)和梯度误差?

如何为 keras 使用自定义损失函数

使用自定义损失函数编译 Keras 模型时出现 TypeError

如何在 tf.keras 自定义损失函数中触发 python 函数?

在具有条件的 keras 中实现自定义损失函数