英文:
Tensorflow Keras Dot of Layers Shape Error
问题
我正在尝试创建一个回归模型,该模型输出标量密集层和标量自定义层的乘积。模型的输入是2D数组。
CustomLayer仅在输入数组的第一个元素上工作。因此,我的自定义层现在如下所示。
class CustomLayer(tf.keras.layers.Layer):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.a = tf.Variable(0.1, dtype=tf.float32, trainable=True)
self.b = tf.Variable(0.1, dtype=tf.float32, trainable=True)
self.rho = tf.Variable(0.1, dtype=tf.float32, trainable=True)
self.m = tf.Variable(0, dtype=tf.float32, trainable=True)
self.sigma = tf.Variable(0.1, dtype=tf.float32, trainable=True)
def call(self, inputs):
return self.a + self.b * (self.rho * (inputs[0] - self.m) + tf.math.sqrt(tf.math.square((inputs[0] - self.m)) + tf.math.square(self.sigma)))
和功能API看起来像这样:
inputs = keras.Input(shape=(2, ), name="digits")
x1 = layers.Dense(40, activation="softplus", kernel_initializer='normal')(inputs)
x2 = layers.Dense(1, activation="softplus")(x1)
custom = CustomLayer()(inputs)
outputs = layers.dot([custom, x2], 0) # 我应该使用axis = 0吗? # 此前在此处有一个拼写错误
model = keras.Model(inputs=inputs, outputs=outputs)
但是,无论我使用哪个轴,该代码都会报错。
Dot.build(self, input_shape)
134 axes = self.axes
135 if shape1[axes[0]] != shape2[axes[1]]:
--> 136 raise ValueError(
137 "Incompatible input shapes: "
138 f"axis values {shape1[axes[0]]} (at axis {axes[0]}) != "
139 f"{shape2[axes[1]]} (at axis {axes[1]}). "
140 f"Full input shapes: {shape1}, {shape2}"
141 )
ValueError: Incompatible input shapes: axis values 2 (at axis 0) != None (at axis 0). Full input shapes: (2,), (None, 1)
当我检查x2和custom层的形状时,我看到以下情况:
x2:我理解None来自于批处理大小。
'<KerasTensor: shape=(None, 1) dtype=float32 (created by layer 'dense_191')>'
custom:为什么这里没有None?
'<KerasTensor: shape=(2,) dtype=float32 (created by layer 'custom_layer_3')>'
如果我问了一些非常基础的问题,我深感抱歉。谢谢。
英文:
I am trying to create a regression model that outputs the multiplication of a scalar dense layer and a scalar custom layer. The input of the model is 2D array.
The CustomLayer only works on the first element of the input array. So my custom layer looks like this now.
class CustomLayer(tf.keras.layers.Layer):
def __init__(self, *args, **kwargs):
super().__init__( *args, **kwargs)
self.a = tf.Variable(0.1, dtype=tf.float32, trainable=True)
self.b = tf.Variable(0.1, dtype=tf.float32, trainable=True)
self.rho = tf.Variable(0.1, dtype=tf.float32, trainable=True)
self.m = tf.Variable(0, dtype=tf.float32, trainable=True)
self.sigma = tf.Variable(0.1, dtype=tf.float32, trainable=True)
def call(self, inputs):
return self.a + self.b * (self.rho * (inputs[0] - self.m) + tf.math.sqrt( tf.math.square( (inputs[0] - self.m) ) + tf.math.square( self.sigma)))
and the functional API looks like this :
inputs = keras.Input(shape=(2, ), name="digits")
x1 = layers.Dense(40, activation="softplus", kernel_initializer='normal')(inputs)
x2 = layers.Dense(1, activation="softplus")(x1)
custom = CustomLayer()(inputs)
outputs = layers.dot([custom, x2], 0) # Should I use axis = 0? # had a typo here earlier
model = keras.Model(inputs=inputs, outputs=outputs)
But the code gives an error no matter what axis I use.
Dot.build(self, input_shape)
134 axes = self.axes
135 if shape1[axes[0]] != shape2[axes[1]]:
--> 136 raise ValueError(
137 "Incompatible input shapes: "
138 f"axis values {shape1[axes[0]]} (at axis {axes[0]}) != "
139 f"{shape2[axes[1]]} (at axis {axes[1]}). "
140 f"Full input shapes: {shape1}, {shape2}"
141 )
ValueError: Incompatible input shapes: axis values 2 (at axis 0) != None (at axis 0). Full input shapes: (2,), (None, 1)
When I inspect the shape of the x2 and custom layer I see this:
x2: I understand the None comes from the batchsize.
<KerasTensor: shape=(None, 1) dtype=float32 (created by layer 'dense_191')>
custom: Why don't I have the None here?
<KerasTensor: shape=(2,) dtype=float32 (created by layer 'custom_layer_3')>
Apologies if I am asking something very trivial. Thank you.
答案1
得分: 1
首先,您的自定义层的输出形状为shape=(2,)
,而不是shape=(None, 2)
。您可以通过将inputs[0]
更改为inputs
来修复这个问题:
return self.a + self.b * (self.rho * (inputs - self.m) + tf.math.sqrt(tf.math.square(inputs - self.m) + tf.math.square(self.sigma)))
否则,您将丢弃批处理维度,并且只会取批处理的第一个元素。
其次,您现在有形状为(None, 2)
(自定义层)和(None, 1)
(x2)的形状。对于点积运算,两个向量必须具有相同的长度。因此,要么将x2
的输出更改为(None, 2)
,要么将您的CustomLayer
的输出更改为(None, 1)
。
编辑:如果您只想在CustomLayer中获取第一个标量元素,您可以将input[0]
更改为input[:, :1]
,以在调用函数中获得shape=(None, 1)
。
英文:
There are multiple things. First, your custom layer has an output shape shape=(2,)
instead of shape=(None, 2)
. You can fix that by changing inputs[0]
to inputs
in
return self.a + self.b * (self.rho * (inputs[0] - self.m) + tf.math.sqrt( tf.math.square( (inputs[0] - self.m) ) + tf.math.square( self.sigma)))
Otherwise, you would discard the batch dimension and will only take the first element of the batch.
Second, you now have shapes (None, 2)
(custom layer) and (None, 1)
(x2). For a dot product, both vectors have to have the same length. So either change the output of x2
to (None, 2)
, or change the output of your CustomLayer
to (None, 1)
.
Edit: If you only want to take the first scalar element in CustomLayer, you can change ìnput[0]
to input[:, :1]
to get shape=(None, 1)
in the call function.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论