python - tf.one_hot 没有渐变

标签 python tensorflow keras

我正在尝试创建一个具有整数输出的自定义损失函数(在损失函数中转换为一个热编码)。

但问题是 one_hot 没有可微分的梯度。 有任何解决方法吗?

def new_loss(hidden, output, random_size=20):

    output1 = tf.cast(
        output,
        dtype=tf.int32,
    )
    one_hot = tf.one_hot(output1, num_words, dtype=tf.int32,)

    one_hot = tf.cast(
        one_hot,
        dtype=tf.float32
    )

    score = K.dot(hidden, one_hot)
    random_words = tf.random.uniform((random_size,), maxval=num_words, dtype=tf.dtypes.int32)
    random_words_1_hot = tf.one_hot(random_words, num_words, dtype=tf.float32)
    scores = K.dot(random_words_1_hot, hidden)
    average = K.sum(K.log (1 - K.sigmoid(scores)) / random_size)

    return (-1 * K.log (K.sigmoid(score)) - average)
ValueError: An operation has `None` for gradient. Please make sure that all of your ops have a gradient defined (i.e. are differentiable). Common ops without gradient: K.argmax, K.round, K.eval.

最佳答案

问题不在于 one_hot 编码本身,而在于一系列转换操作。更具体地说,TensorFlow 不会通过整数传播。假设 hiddenoutput 都是 float 类型,如果你改变这个

output1 = tf.cast(output, dtype=tf.int32,)
one_hot = tf.one_hot(output1, num_words, dtype=tf.int32,)

one_hot = tf.cast(one_hot, dtype=tf.float32)

为此

one_hot = tf.one_hot(tf.cast(output, tf.int32), num_words, dtype=tf.float32)

你会得到你的渐变。

更详细的例子:

one_hot1 = tf.one_hot(tf.cast(np.random.rand(2), tf.int32), num_words, dtype=tf.float32)
hidden = tf.constant([1.,2.,3.,4.], shape=(2,2))

one_hot = tf.cast(one_hot1, dtype=tf.float32)

hidden1 = tf.cast(hid, tf.float32)
score = tf.matmul(hidden, one_hot)
random_words = tf.random.uniform((random_size,), maxval=num_words, dtype=tf.float32)
random_words_1_hot = tf.one_hot(tf.cast(random_words, tf.int32), num_words, dtype=tf.float32)
scores = tf.matmul(random_words_1_hot, hidden)
average = tf.reduce_sum(tf.log(1 - tf.sigmoid(scores)) / random_size)

res = -1 * tf.log(tf.sigmoid(score)) - average
grads = tf.gradients(res, [hidden1, one_hot1])
sess = tf.Session()
print(sess.run(res))
print(sess.run(grads))

为了保持一致性,我使用了核心 TF 操作。您可以看到,如果 one_hot1 最初创建为 tf.int,然后重新转换为 float,则不会有渐变。更多信息请点击此处 https://github.com/tensorflow/tensorflow/issues/20524

关于python - tf.one_hot 没有渐变,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55482146/

相关文章:

python - ValueError : None is only supported in the 1st dimension. 张量 'flatbuffer_data' 具有无效形状 '[None, None, 1, 512]'

python - keras:样本权重多重不平衡输出

python - 如何有条件地选择numpy数组中的元素

python - 使用 kedro run CLI 命令覆盖嵌套参数

python - Pandas 将两列相加,跳过 NaN

python-3.x - 刚刚切换到 TensorFlow 2.1 并收到一些烦人的警告

python - 在 Tensorflow 中使用 leaky relu

python - 导入错误: No module named generator

python - 导出tensorflow模型时为"Cannot infer num from shape"

python - Keras 在预测时加载神经网络的权重/错误