我如何在 for 循环中使用 keras.Layer 的动态维度(无维度)?

Posted

技术标签:

【中文标题】我如何在 for 循环中使用 keras.Layer 的动态维度(无维度)?【英文标题】:how i use dynamic dimension(None dimension) of keras.Layer in for loop? 【发布时间】:2021-11-05 07:22:40 【问题描述】:

我想构建一个 keras 层,如下所示。 输入维度是(None,16,3),我想在“for循环”中使用它。但是当我在 Sequential Model 中使用这一层时,我得到了这个错误:

ValueError:无法将部分已知的 TensorShape 转换为张量:(?, 16, 3)

有人可以帮我吗?

class WeightedLayer(Layer):
 def __init__(self, n_input, n_memb, **kwargs):
    super(WeightedLayer, self).__init__( **kwargs)
    self.n = n_input   # 16 features
    self.m = n_memb    # 3 
    self.batch_size = None
    
 def build(self, batch_input_shape):
    #self.batch_size = batch_input_shape[0]
    self.batch_size = tf.shape(batch_input_shape)[0]
    super(WeightedLayer, self).build(batch_input_shape)
    
 def call(self, input_):
    CP = []
    for batch in range(self.batch_size):
        xd_shape = [self.m]
        c_shape = [1]
        cp = input_[batch,0,:]
        for d in range(1,self.n):
            c_shape.insert(0,self.m)
            xd_shape.insert(0,1)
            xd = tf.reshape(input_[batch,d,:], (xd_shape))
            c = tf.reshape(cp,(c_shape))
            cp = tf.matmul(c , xd)

        flat_cp = tf.reshape(cp,(1, self.m**self.n))
        CP.append(flat_cp)

    return tf.reshape(tf.stack(CP), (self.batch_size, self.m**self.n))

 def compute_output_shape(self,batch_input_shape):
  return tf.TensorShape([self.batch_size, self.m** self.n])


Model=keras.models.Sequential()
Model.add(Input(shape=(16,3), name='inputLayer'))
Model.add(WeightedLayer(n_input=16,n_memb=3))
Model.compile(loss= 'mean_squared_error' , optimizer= 'adam')
Model.fit(X_train, y_train,
      epochs=200,
      batch_size=10,
      validation_data = (X_test, y_test))

【问题讨论】:

哪一行引发了这个错误?我试过你的代码没有错误。 weighted_layer = WeightedLayer(16, 3) x = tf.random.normal((100, 16, 3)) y = weighted_layer(x) 我在Sequential Model中使用了这个层:Model=keras.models.Sequential() Model.add(Input(shape=(16,3), name='inputLayer')) Model.add( WeightedLayer(n_input=16,n_memb=3)) Model.compile(loss= 'mean_squared_error' , optimizer= 'adam') Model.fit(X_train, y_train, epochs=200, batch_size=10, validation_data = (X_test, y_test) ) 【参考方案1】:

Call 会制作一个符号图,稍后会运行很多次,我猜 tensorflow 不允许 python list 出现在图中。 关注这个doc

一种常见的模式是从循环中累积中间值。 通常,这是通过附加到 Python 列表或添加 Python 字典的条目。但是,由于这些是 Python 方面 效果,它们在动态展开时不会按预期工作 环形。使用 tf.TensorArray 动态累积结果 展开循环。

下面的例子会很有帮助。使用 tf.TensorArray

import tensorflow as tf
from tensorflow.keras.layers import Layer, Input
from tensorflow import keras
import numpy as np


class WeightedLayer(Layer):
    def __init__(self, n_input, n_memb, **kwargs):
        super(WeightedLayer, self).__init__(**kwargs)
        self.n = n_input  # 16 features
        self.m = n_memb  # 3

    def build(self, batch_input_shape):
        super(WeightedLayer, self).build(batch_input_shape)

    def call(self, input_):
        batch_size = tf.shape(input_)[0]
        ta = tf.TensorArray(tf.float32, size=0, dynamic_size=True)
        for i in tf.range(batch_size):
            ta = ta.write(i, tf.random.normal((1,))[0])
        return ta.stack()

    def compute_output_shape(self, batch_input_shape):
        return tf.TensorShape([self.batch_size, ])


X_train = np.random.uniform(0, 1, (200, 16, 3))
X_test = np.random.uniform(0, 1, (200, 16, 3))
y_train = np.random.uniform(0, 1, (200,))
y_test = np.random.uniform(0, 1, (200,))

Model = keras.models.Sequential()
Model.add(Input(shape=(16, 3), name='inputLayer'))
Model.add(WeightedLayer(n_input=16, n_memb=3))
Model.compile(loss='mean_squared_error', optimizer='adam')
Model.fit(X_train, y_train,
          epochs=20,
          batch_size=10,
          validation_data=(X_test, y_test))

【讨论】:

谢谢,我的数据看起来像 X_train = np.random.uniform((200, 16, 3)) 和 y_train = np.random.uniform((200,))。但在您的示例中:self.batch_size = K.int_shape(input_[0]) #(16,1) self.batch_size[0] #16 但我希望 for 循环 "batch" 为 200。

以上是关于我如何在 for 循环中使用 keras.Layer 的动态维度(无维度)?的主要内容,如果未能解决你的问题,请参考以下文章

Tensorflow+keras用代码给神经网络结构绘图

Keras官方中文文档:融合层Merge

如何在Django模板的内部for循环中使用外部for循环值

如何在 for 循环中创建多个复选框?

如何在 R 中使用“for”循环进行非连续观察

如何在bash for循环中使用变量[重复]