【问题标题】:TensorFlow 2: RuntimeError: Cannot use a constraint function on a sparse variableTensorFlow 2:RuntimeError:无法对稀疏变量使用约束函数
【发布时间】:2020-11-17 05:31:36
【问题描述】:

我用embeddings_constraint定义了一个嵌入对象:

from tensorflow.keras.layers import Embedding
from tensorflow.keras.constraints import UnitNorm
. . .
emb = Embedding(input_dim, output_dim, name='embedding_name', embeddings_constraint=UnitNorm(axis=1))
. . .

稍后在代码中,当我想训练包含emb 的模型时,我从函数model.fit 中得到一个异常:

RuntimeError: Cannot use a constraint function on a sparse variable.

但是,当我不对 emb 施加嵌入约束时,代码不会引发错误。此外,我在 TF 1 上进行了尝试,它运行良好(有和没有embeddings_constraint)。根据GitHub discussion 的说法,这似乎是 TF 2 错误,但没有提出可行的解决方案。

有什么办法解决这个问题吗?

【问题讨论】:

    标签: tensorflow keras tensorflow2.0 keras-layer keras-2


    【解决方案1】:

    解决此问题的方法是直接调用约束,如下所示:

    from tensorflow.keras.layers import Embedding
    from tensorflow.keras.constraints import UnitNorm
    . . .
    emb = Embedding(input_dim, output_dim, name='embedding_name')
    norm_layer = UnitNorm(axis=1)
    norm_embedding = norm_layer(emb(embedding_id_input))
    . . .
    

    【讨论】:

      【解决方案2】:

      我也打了这个,添加到 tensorflow github 问题中,在 tf 2.7 和 tf-nightly 中尝试过,仍然看到错误,所以提出了新的 keras 问题:https://github.com/keras-team/keras/issues/15818

      解决方法不会解决所有用例 - 它限制了嵌入活动,而不是整个嵌入矩阵。我确实有一个使用 keras 回调的解决方法 - 但我发现它减慢了训练速度 - 我相信回调适用于无法在 GPU 上运行的 numpy 数组 - 但如果有用,这里是方法

      import numpy as np
      import tensorflow as tf
      
      
      class ConstrainEmbeddings(tf.keras.callbacks.Callback):
          def __init__(self, min_norm, emb, eps=1e-9):
              super(ConstrainEmbeddings, self).__init__()
              self.min_norm = min_norm
              self.emb = emb
              self.eps = eps
      
          def on_batch_begin(self, *args, **kwargs):
              W = self.emb.get_weights()[0]
              norms = tf.maximum(self.eps, tf.norm(W, axis=1))
              delta = tf.expand_dims(tf.math.divide(self.min_norm, norms) - 1.0, 1)
              deltaW = tf.math.multiply(W, delta)
              constrainedW = W + tf.expand_dims(tf.cast(norms < self.min_norm, dtype=tf.float32), 1) * deltaW
              self.emb.set_weights([constrainedW])
      
      
      def constrain_embeddings(use_keras):
          N = 10
          batch_size = 5
          data = {
              'X': np.random.randint(0, 10, N),
              'Y': np.random.randint(0, 2, N)
          }
      
          def get_labels(features):
              labels = features.pop('Y')
              return features, labels
      
          dset = tf.data.Dataset.from_tensor_slices(data).map(get_labels).batch(batch_size)
      
          inp = tf.keras.Input(shape=(1,), name='X', dtype='int64')
          constraint = tf.keras.constraints.MaxNorm(max_value=0.1) if use_keras else None
      
          emb = tf.keras.layers.Embedding(
              10, 3, input_length=1,
              embeddings_initializer=tf.keras.initializers.RandomUniform(minval=-1.0, maxval=1.0),
              embeddings_constraint=constraint
          )
          emb_out = emb(inp)
          out = tf.keras.layers.Dense(1)(emb_out)
          model = tf.keras.Model(inputs=inp, outputs=out)
          model.compile(optimizer='adam', loss=tf.keras.losses.binary_crossentropy)
          callbacks = [ConstrainEmbeddings(.3, emb)] if not use_keras else []
          model.fit(dset, epochs=10, callbacks=callbacks)
      
      
      if __name__ == '__main__':
          print("tensorflow git version: ", tf.version.GIT_VERSION)
          constrain_embeddings(use_keras=False)
      

      【讨论】:

        猜你喜欢
        • 2018-07-19
        • 2020-03-14
        • 2017-04-30
        • 1970-01-01
        • 1970-01-01
        • 2017-12-03
        • 1970-01-01
        • 1970-01-01
        • 2019-04-11
        相关资源
        最近更新 更多