简体   繁体   English

将线性代数应用于 tensorflow 中的参差不齐的张量

[英]Apply linear algebra to ragged tensor in tensorflow

I'm using tensorflow v2.7.0 and trying to create a ML model using ragged tensor.我正在使用 tensorflow v2.7.0 并尝试使用不规则张量创建 ML model。

The issue is that tf.linalg.diag, tf.matmul and tf.linalg.det are not working with ragged tensor.问题是 tf.linalg.diag、tf.matmul 和 tf.linalg.det 不适用于不规则张量。 I've found a workaround by converting the ragged tensor in numpy and converting it back to a ragged tensor but it's not working when applying the layer in a global model.我通过转换 numpy 中的参差不齐的张量并将其转换回参差不齐的张量找到了一种解决方法,但是在全局 model 中应用图层时它不起作用。

The following code is working以下代码正在运行

 import tensorflow as tf class LRDet(tf.keras.layers.Layer): def __init__(self,numItems,rank=10): super(LRDet,self).__init__() self.numItems = numItems self.rank = rank def build(self,input_shape): V_init = tf.random_normal_initializer(mean=0.0,stddev=0.01) D_init = tf.random_normal_initializer(mean=1.0,stddev=0.01) self.V = tf.Variable(name='V',initial_value=V_init(shape=(self.numItems, self.rank)),trainable=True) self.D = tf.Variable(name='D',initial_value=D_init(shape=(self.numItems,)),trainable=True) def call(self,inputs): batch_size = inputs.nrows() subV = tf.gather(self.V,inputs) subD = tf.square(tf.gather(self.D,inputs,batch_dims=0))#tf.linalg.diag(tf.square(tf.gather(D,Xrag,batch_dims=0))) subD = tf.ragged.constant([tf.linalg.diag(subD[i]).numpy() for i in tf.range(batch_size)]) K = tf.ragged.constant([tf.matmul(subV[i],subV[i],transpose_b=True).numpy() for i in tf.range(batch_size)]) K = tf.add(K,subD) res = tf.ragged.constant([tf.linalg.det(K[i].to_tensor()).numpy() for i in tf.range(batch_size)]) return res numItems = 10 rank = 3 detX = LRDet(numItems,rank) X = [[1,2],[3],[4,5,6]] Xrag = tf.ragged.constant(X) _ = detX(Xrag)

But once I used this layer in a more global model I have the following error但是一旦我在更全局的 model 中使用了这一层,我就会遇到以下错误

OperatorNotAllowedInGraphError: Exception encountered when calling layer "lr_det_10" (type LRDet). OperatorNotAllowedInGraphError:调用层“lr_det_10”(类型 LRDet)时遇到异常。

 in user code: File "<ipython-input-57-6b073a14386e>", line 18, in call * subD = tf.ragged.constant([tf.linalg.diag(subD[i]).numpy() for i in tf.range(batch_size)]) OperatorNotAllowedInGraphError: iterating over `tf.Tensor` is not allowed: AutoGraph did convert this function. This might indicate you are trying to use an unsupported feature.

I tried to used tf.map_fn instead of list comprehension with.numpy() but without success.我尝试使用 tf.map_fn 而不是列表理解 with.numpy() 但没有成功。

Any help would be very much appreciated.任何帮助将不胜感激。

Thanks !谢谢 !

Here is an option running with tf.map_fn ;这是一个使用tf.map_fn运行的选项; however, it currently only runs on the CPU due to a very recent bug regarding tf.map_fn , ragged tensors and the GPU:然而,由于最近的一个关于tf.map_fn 、参差不齐的张量和 GPU 的错误,它目前只能在 CPU 上运行:

import os
os.environ["CUDA_VISIBLE_DEVICES"] = "-1" # do not access GPU
import tensorflow as tf

class LRDet(tf.keras.layers.Layer):
    
    def __init__(self,numItems,rank=10):
        super(LRDet,self).__init__()
        self.numItems = numItems
        self.rank = rank
    
    def build(self,input_shape):
        V_init = tf.random_normal_initializer(mean=0.0,stddev=0.01)
        D_init = tf.random_normal_initializer(mean=1.0,stddev=0.01)
        self.V = tf.Variable(name='V',initial_value=V_init(shape=(self.numItems, self.rank)),trainable=True)
        self.D = tf.Variable(name='D',initial_value=D_init(shape=(self.numItems,)),trainable=True)

    def call(self,inputs):
        batch_size = inputs.nrows()
        subV = tf.gather(self.V,inputs)
    
        subD = tf.square(tf.gather(self.D, inputs, batch_dims=0))
        subD = tf.map_fn(self.diag, subD, fn_output_signature=tf.RaggedTensorSpec(shape=[1, None, None],
                                                                    dtype=tf.type_spec_from_value(subD).dtype,
                                                                    ragged_rank=2,
                                                                    row_splits_dtype=tf.type_spec_from_value(subD).row_splits_dtype))
        subD = tf.squeeze(subD, 1)


        K = tf.map_fn(self.matmul, subV, fn_output_signature=tf.RaggedTensorSpec(shape=[1, None, None],
                                                                    dtype=tf.type_spec_from_value(subV).dtype,
                                                                    ragged_rank=2,
                                                                    row_splits_dtype=tf.type_spec_from_value(subV).row_splits_dtype))
        K = tf.squeeze(K, 1)
        K = tf.add(K,subD)

        res = tf.map_fn(self.det, K, tf.TensorSpec(shape=(), dtype=tf.float32, name=None))

        return res
        

    def diag(self, x):
      return tf.ragged.stack(tf.linalg.diag(x))

    def matmul(self, x):
      return tf.ragged.stack(tf.matmul(x, x,transpose_b=True))

    def det(self, x):
      return tf.linalg.det(x.to_tensor())


numItems = 10
rank = 3
input = tf.keras.layers.Input(shape=(None,), ragged=True, dtype=tf.int32)
detX = LRDet(numItems,rank)
output = detX(input)
model = tf.keras.Model(input, output)

X = [[1,2],[3],[4,5,6]]
Xrag = tf.ragged.constant(X)
y = tf.random.normal((3, 1))
model.compile(loss='mse', optimizer='adam')
model.fit(Xrag, y, batch_size=1, epochs=1)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM