tensorflow 2个keras随机播放每行梯度问题

问题描述 投票:2回答:1

我需要一个NN,它将为相同输入的任何排列提供相同的输出。正在尝试搜索解决方案(“排列不变性”),找到了一些图层,但未能使其正常工作。

我选择了不同的方法:我想创建一个层,作为我在模型中的第一个添加,它将随机地随机排列输入(每行独立)-请让我们遵循这种方法,我知道它可以在模型外部完成,但我希望它成为模型的一部分。我尝试过:

class ShuffleLayer(tf.keras.layers.Layer):
    def __init__(self, **kwargs):
        super(ShuffleLayer, self).__init__(**kwargs)

    def call(self, inputs):
        batchSize = tf.shape(inputs)[0]
        cols = tf.shape(inputs)[-1]
        order0 = tf.tile(tf.expand_dims(tf.range(0, batchSize), -1), [1, cols])
        order1 = tf.argsort(tf.random.uniform(shape=(batchSize, cols)))
        indices = tf.stack([tf.reshape(order0, [-1]), tf.reshape(order1, [-1])], axis=-1)
        outputs = tf.reshape(tf.gather_nd(inputs, indices), [batchSize, cols])
        return outputs

我遇到以下错误:

ValueError:变量的梯度为None。请确保您所有的操作都定义了渐变(即可区分)。没有的常见操作梯度:K.argmax,K.round,K.eval。

如何避免呢?我尝试使用tf.stop_gradient,但未成功。

python keras gradient shuffle tensorflow2.0
1个回答
0
投票

使用Lambda层:

首先,如果您的图层没有可训练的权重,则应使用Lambda图层,而不是自定义图层。它变得越来越简单。

def shuffleColumns(inputs):
    batchSize = tf.shape(inputs)[0]
    cols = tf.shape(inputs)[-1]
    order0 = tf.tile(tf.expand_dims(tf.range(0, batchSize), -1), [1, cols])
    order1 = tf.argsort(tf.random.uniform(shape=(batchSize, cols)))
    indices = tf.stack([tf.reshape(order0, [-1]), tf.reshape(order1, [-1])], axis=-1)
    outputs = tf.reshape(tf.gather_nd(inputs, indices), [batchSize, cols])
    return outputs

在模型中,使用Lambda(shuffleColumns)层。

关于错误

如果是第一层,则此错误可能不是由该层引起的。 (除非新版本的Tensorflow要求自定义图层具有权重和def build(self, input_shape):定义,这似乎不太合逻辑)。

似乎您在其他地方正在做其他事情。错误是:您正在使用某些阻止反向传播的操​​作,因为不可能拥有该操作的派生形式。

由于导数是相对于模型的“权重”采用的,因此这意味着操作必须在模型中的第一个权重张量之后(即:在包含可训练权重的第一层之后)。

[您需要在模型中搜索任何没有导数的东西,如错误提示:舍入,argmax,返回常量的条件,返回排序为y_true但不返回对y_pred的运算的损失,等

[当然,K.stop_gradients也是阻止反向传播的操​​作,如果您只是这样使用它肯定会导致此错误。

以下为您的操作提供了更简单的建议,但是这些错误都无法解决,因为这些错误不在别的地方。

建议的操作1

现在,使用tf.random.shuffle会更容易:

tf.random.shuffle

在模型中使用def shuffleColumns(x): x = tf.transpose(x) x = tf.random.shuffle(x) return tf.transpose(x) 层。的确,这将均等地洗排所有列,但每个批次将具有不同的排列。而且由于您将拥有多个时期,并且您将在每个时期之间改组(我认为是)样本(Lambda(shuffleColumns)中是自动的),因此您几乎不会重复批处理。因此:

  • 每个批次将具有不同的排列
  • 几乎不可能有两次相同的批次

此方法可能比您的方法快得多。

建议的操作2

如果您希望它们置换不变,为什么不使用fit而不是置换?对列进行排序,而不是要训练无限的排列,您只需消除排列的任何可能性。该模型应该学习得更快,但是不会考虑输入中各列的顺序。

使用图层tf.sort

此建议必须同时用于训练和推理。

© www.soinside.com 2019 - 2024. All rights reserved.