【问题标题】:keras gives error when using two loss function for two outputskeras 在对两个输出使用两个损失函数时会出错
【发布时间】:2020-10-16 03:15:39
【问题描述】:

我有一个网络。最后一层之前的一层是致密层。我希望最后一层返回前一层的最大值和该最大值的索引。

所以如果密集层的输出是 [0,4,5,120,1],那么最后一层应该返回 [120, 3]。 我需要网络处理的损失仅根据最大值计算,而不是索引。因此,我为第二个输出(即索引)编写了一个损失函数,该函数始终返回零 - 但如果有更好的解决方案,除了如何修复此错误之外,我还想听听。

代码是:

def ignor_loss(preds, trues):
    return 0

# build deep q network
inputs = Input((240,256,3))
pool0 = MaxPooling2D()(inputs)
conv1 = Conv2D(30,3,activation='relu')(pool0)
pool1 = MaxPooling2D()(conv1)
conv2 = Conv2D(40,3,activation='relu')(pool1)
pool2 = MaxPooling2D()(conv2)
conv3 = Conv2D(50,3,activation='relu')(pool2)
pool3 = MaxPooling2D()(conv3)
conv4 = Conv2D(60,3,activation='relu')(pool3)
pool4 = MaxPooling2D()(conv4)
conv5 = Conv2D(80,3,activation='relu')(pool4)
flat = Flatten()(conv5)
dense1 = Dense(70)(flat)
dense2 = Dense(40)(dense1)
values = Dense(env.action_space.n)(dense2)
max_, ind = Lambda(lambda x : [K.max(x),K.argmax(x)])(values)
m = Model(inputs, [max_, ind])
m.compile('adam', ['mse',ignor_loss])

错误是:

TypeError: unsupported operand type(s) for -: 'int' and 'NoneType'

有什么想法吗?

编辑:

这是我更新的代码:

# build deep q network
inputs = Input((240,256,3))
pool0 = MaxPooling2D()(inputs)
conv1 = Conv2D(30,3,activation='relu')(pool0)
pool1 = MaxPooling2D()(conv1)
conv2 = Conv2D(40,3,activation='relu')(pool1)
pool2 = MaxPooling2D()(conv2)
conv3 = Conv2D(50,3,activation='relu')(pool2)
pool3 = MaxPooling2D()(conv3)
conv4 = Conv2D(60,3,activation='relu')(pool3)
pool4 = MaxPooling2D()(conv4)
conv5 = Conv2D(80,3,activation='relu')(pool4)
flat = Flatten()(conv5)
dense1 = Dense(70)(flat)
dense2 = Dense(40)(dense1)
q_values = Dense(env.action_space.n)(dense2)
max_q =  Lambda(lambda x : K.max(x), name='max')(q_values)
ind = Lambda(lambda x : K.argmax(x), name='ind')(q_values)
m = Model(inputs, [max_q,ind])
m.compile('adam', {'max':'mse','ind':'mse'}, loss_weights=[1., 0.0])

我仍然遇到同样的错误:

unsupported operand type(s) for -: 'int' and 'NoneType'

我需要知道为什么会出现这个错误?有什么想法吗?

编辑 2: 现在我将 keepdims=True 添加到 max 函数,并将 K.expand_dims 添加到 argmax 函数,如下所示:

q_values = Dense(env.action_space.n)(dense2)
max_q =  Lambda(lambda x : K.max(x, keepdims=True), name='max')(q_values)
ind = Lambda(lambda x : K.expand_dims(K.argmax(x)), name='ind')(q_values)
m = Model(inputs, [max_q,ind])
m.compile('adam', {'max':'mse','ind':'mse'}, loss_weights=[1., 0.0])

但我得到一个不同的错误:

TypeError: Expected int64, got 0.0 of type 'float' instead.

【问题讨论】:

    标签: tensorflow keras deep-learning loss-function


    【解决方案1】:

    我认为这是一个更清洁的解决方案

    1 步:将模型拟合到最大值

    X = np.random.uniform(0,1, (2,240,256,3))
    y = np.random.uniform(0,1, 2)
    
    inputs = Input((240,256,3))
    pool0 = MaxPooling2D()(inputs)
    conv1 = Conv2D(30,3,activation='relu')(pool0)
    pool1 = MaxPooling2D()(conv1)
    conv2 = Conv2D(40,3,activation='relu')(pool1)
    pool2 = MaxPooling2D()(conv2)
    conv3 = Conv2D(50,3,activation='relu')(pool2)
    pool3 = MaxPooling2D()(conv3)
    conv4 = Conv2D(60,3,activation='relu')(pool3)
    pool4 = MaxPooling2D()(conv4)
    conv5 = Conv2D(80,3,activation='relu')(pool4)
    flat = Flatten()(conv5)
    dense1 = Dense(70)(flat)
    dense2 = Dense(40)(dense1)
    values = Dense(10)(dense2) # in my case env.action_space.n is 10
    max_ = Lambda(lambda x: tf.reduce_max(x, axis=1, keepdims=True))(values)
    
    m = Model(inputs, max_)
    m.compile('adam', 'mse')
    m.fit(X,y, epochs=3)
    

    2 步:根据拟合模型返回 max 和 argmax 进行推断(这只需要构建一个新模型)

    ind = Lambda(lambda x: tf.expand_dims(tf.argmax(x, axis=1),-1))(values)
    final_model = Model(inputs, [max_, ind])
    final_model.predict(X) this return max and argmax
    

    EDIT:这里是操作所有操作的紧凑模型。如果你有两个输出,你需要传递给 keras 两个目标。因此,我将第二个目标生成为 0 的数组(它没有影响)

    def ignor_loss(trues, preds):
        return 0.
    
    X = np.random.uniform(0,1, (2,240,256,3))
    y = np.random.uniform(0,1, 2)
    
    inputs = Input((240,256,3))
    pool0 = MaxPooling2D()(inputs)
    conv1 = Conv2D(30,3,activation='relu')(pool0)
    pool1 = MaxPooling2D()(conv1)
    conv2 = Conv2D(40,3,activation='relu')(pool1)
    pool2 = MaxPooling2D()(conv2)
    conv3 = Conv2D(50,3,activation='relu')(pool2)
    pool3 = MaxPooling2D()(conv3)
    conv4 = Conv2D(60,3,activation='relu')(pool3)
    pool4 = MaxPooling2D()(conv4)
    conv5 = Conv2D(80,3,activation='relu')(pool4)
    flat = Flatten()(conv5)
    dense1 = Dense(70)(flat)
    dense2 = Dense(40)(dense1)
    values = Dense(10)(dense2) # in my case env.action_space.n is 10
    max_ = Lambda(lambda x: tf.reduce_max(x, axis=1, keepdims=True), name='max')(values)
    ind = Lambda(lambda x: tf.expand_dims(tf.argmax(x, axis=1),-1), name='ind')(values)
    
    m = Model(inputs, [max_,ind])
    m.compile('adam', loss={'max':'mse', 'ind':ignor_loss}, 
          loss_weights={'max':1., 'ind':0.})
    m.fit(X, {'max':y, 'ind':np.zeros_like(y)}, epochs=3)
    m.predict(X)
    

    【讨论】:

    • ty,但我知道这个解决方案。我有兴趣了解如何构建具有两个输出的模型并将损失仅应用于一个。无论如何,知道为什么我当前的解决方案不起作用。
    • 一般来说,我对 max 和 argmax 函数的方法持怀疑态度...但是,两个输出/损失需要 2 个目标...您是否有 2 个目标才能应用这种拟合?
    • 不确定您所说的目标是什么意思,但我需要将最大值设为某个值 - 也就是说,我有一个真正的 y - 并且索引是我需要用于不同目的的东西,我不想让网络在上面训练
    • 谢谢,但我想使用 keras 构建模型,而不是 tensorflow ......还有,为什么要使用 reduce_max 而不是 tf.max?另外,为什么在获取最大 ind 时需要扩展 dims?
    • 我会的,但我的代码仍然有效,我不知道。请看我的编辑。另外,我不知道你为什么使用reduce max 而不是max?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-29
    • 2021-02-19
    • 2020-03-05
    • 2019-07-06
    • 2018-09-10
    • 2019-01-11
    相关资源
    最近更新 更多