Keras自定义损失函数中的错误-tensotflow

时间:2019-05-03 21:15:40

标签: python tensorflow keras

我对tensorflow相当陌生,我遵循以下问题的答案,以便在Keras中构建自定义损失函数,该函数仅考虑前20个预测。

How can I sort the values in a custom Keras / Tensorflow Loss Function?

但是,当我尝试使用此代码编译模型时,出现以下有关尺寸的错误

InvalidArgumentError: input must have last dimension >= k = 20 but is 1 for 'loss_21/dense_65_loss/TopKV2' (op: 'TopKV2') with input shapes: [?,1], [] and with computed input tensors: input[1] = <20>.

下面是重新生成错误的代码的简化版本。

import tensorflow as tf    
from tensorflow.python.keras.models import Sequential
from tensorflow.python.keras.layers import Dense
from tensorflow.python.keras.optimizers import SGD

top = 20

def top_loss(y_true, y_pred):
    y_pred_top_k, y_pred_ind_k = tf.nn.top_k(y_pred, top)
    loss_per_sample = tf.reduce_mean(tf.reduce_sum(y_pred_top_k,
            axis=-1))

    return loss_per_sample

model = Sequential()
model.add(Dense(50, input_dim=201))
model.add(Dense(1))
sgd = SGD(lr=0.01, decay=0, momentum=0.9)
model.compile(loss=top_loss, optimizer=sgd)

编译模型时,错误会在top_loss函数的下一行引发。

y_pred_top_k, y_pred_ind_k = tf.nn.top_k(y_pred, top)

似乎y_pred在编译时默认为[?,1]形状,而tf.nn.top_k函数期望尺寸至少比'k`高(即20)。

我是否必须将y_pred转换为某种东西,以便tf.nn.top_k知道其尺寸正确?

1 个答案:

答案 0 :(得分:1)

使用:

y_pred_top_k, y_pred_ind_k = tf.nn.top_k(y_pred[:,0], top)

y_pred[:,0]获得整个批次的预测值,作为1级张量。

另一个问题:

但是,您仍然会遇到最后一批的问题。假设您的批次大小为32,而火车数据的大小为100,那么最后一批的大小将小于20,因此tf.nn.top_k将导致最后一批的运行时错误。只需确保您的最后批处理大小> = 20即可避免此问题。但是,更好的方法是检查当前批次是否小于20,如果是,则调整k的值以在top_k

中使用

代码

import tensorflow as tf    
from tensorflow.python.keras.models import Sequential
from tensorflow.python.keras.layers import Dense
from tensorflow.python.keras.optimizers import SGD

top = tf.constant(20)

def top_loss(y_true, y_pred):
    result = tf.cond(tf.math.greater(top_, tf.shape(y_true)[0]), 
                     lambda: tf.shape(y_true)[0], lambda: top)

    y_pred_top_k, y_pred_ind_k = tf.nn.top_k(y_pred[:,0], result)
    loss_per_sample = tf.reduce_mean(tf.reduce_sum(y_pred_top_k,
            axis=-1))

    return loss_per_sample

model = Sequential()
model.add(Dense(50, input_dim=201))
model.add(Dense(1))
sgd = SGD(lr=0.01, decay=0, momentum=0.9)
model.compile(loss=top_loss, optimizer=sgd)