keras.Model ValueError/TypeError 当输出来自自定义层时
keras.Model ValueError/TypeError when output is from customized layer
我正在尝试将函数建模为结合了自定义 Keras Layer
class 的 Keras 函数模型。这个想法是简单地让 Keras 层的 call
方法使用预定义的函数。该函数将输入一个给定的张量,比如 tensor1
,并为 tensor1
中的每个值 t
计算一个特定的点积。点积依赖于不同长度的张量(向量),但输出的是与 tensor1
.
相同长度的张量(向量)
当将 tensor1
传递给函数 TheFunction(tensor)
(定义如下)时,它 returns 是我预期的输出。此外,构建TheFunctionLayer
对象并传入tensor1
时,输出也符合预期,与TheFunction(tensor1)
.
相同。
当我尝试在同一事物上使用 Keras 的功能模型时出现问题。我正在尝试拥有它,以便我可以构建模型对象并将 tensor1
传递给它。但是,在尝试构建对象时,我得到了关于点积中张量维度的 ValueError
。但是如果我对模型定义中的输出声明做一点小改动,我会得到 TypeError
。下面是我的源代码和出现的问题:
进口:
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras.layers import Input, Layer
import numpy as np
涉及的张量:
tensor1 = [1,2,3,4,5,6,7,8,9,10]
tensor1 = tf.convert_to_tensor(tensor1, dtype=tf.float32)
tensor2 = [1,2,3,4,5]
tensor2 = tf.convert_to_tensor(tensor2, dtype=tf.float32)
tensor3 = [6,7,8,9,10]
tensor3 = tf.convert_to_tensor(tensor3, dtype=tf.float32)
点积函数:
def TheFunction(tensor):
tensor = tf.convert_to_tensor(tensor)
def prod_term(t):
return tensor3*t
def dot(t):
return tf.tensordot(tensor2,prod_term(t),axes=1)
return tf.map_fn(lambda t: dot(t), tensor)
点积函数的结果(维度没有问题):
<tf.Tensor: shape=(10,), dtype=float32, numpy=
array([ 130., 260., 390., 520., 650., 780., 910., 1040., 1170.,
1300.], dtype=float32)>
自定义Keras层(只需要call
,不需要__init__
):
class TheFunctionLayer(Layer):
def call(self,tensor):
return TheFunction(tensor)
TheFunctionLayer()(tensor1)
的结果(同样,尺寸没有问题):
<tf.Tensor: shape=(10,), dtype=float32, numpy=
array([ 130., 260., 390., 520., 650., 780., 910., 1040., 1170.,
1300.], dtype=float32)>
Keras 函数模型:
def TheFunctionModel(input_shape):
x = Input(shape=input_shape)
y = TheFunctionLayer()(x)
model = keras.Model(inputs=x, outputs=y)
return model
构建模型对象的结果TheFunctionModel(tf.shape(tensor1))
(与维度冲突):
ValueError: Dimensions must be equal, but are 5 and 10 for '{{node the_function_layer_19/map/while/mul}} = Mul[T=DT_FLOAT](the_function_layer_19/map/while/mul/x, the_function_layer_19/map/while/TensorArrayV2Read/TensorListGetItem)' with input shapes: [5], [10].
这里可能发生了什么?我对 TensorFlow 和 Keras 的工作方式还很陌生,但似乎如果我的函数的输出有效并且与张量维度没有冲突,为什么尝试构建模型对象会给我这个维度问题?
我要添加的另一件事是 TypeError
我在将 TheFunctionModel
的定义中的输出 y = TheFunctionLayer()(x)
更改为 y = TheFunctionLayer().call(x)
:
def TheFunctionModel(input_shape):
x = Input(shape=input_shape)
y = TheFunctionLayer().call(x)
model = keras.Model(inputs=x, outputs=y)
return model
TheFunctionModel(tf.shape(tensor1))
的结果(TypeError
而不是原来的 ValueError
):
TypeError: Could not build a TypeSpec for <KerasTensor: shape=(None, 10) dtype=float32 (created by layer 'tf.convert_to_tensor')> with type KerasTensor
如果更改模型定义中的输出是消除值错误的方法,那么我不确定我是否理解我遇到的类型错误以及如何修复它。
非常感谢对第一个值错误甚至第二个类型错误的建议和/或解决方案。
您忘记了批次维度,这就是它不起作用的原因。您将不得不像这样重写 TheFunction
:
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras.layers import Input, Layer
import numpy as np
tensor2 = tf.constant([1,2,3,4,5], dtype=tf.float32)
tensor3 = tf.constant([6,7,8,9,10], dtype=tf.float32)
def TheFunction(tensor):
def prod_term(t):
return tensor3*t
def dot(t):
return tf.tensordot(tensor2,prod_term(t),axes=1)
e = tf.zeros_like(tensor, dtype=tf.float32)
i = tf.constant(0)
while_condition = lambda i, e, tensor: tf.math.less(i, tf.shape(tensor)[0])
def body(i, ta, tensor):
tensor_shape = tf.shape(tensor)
j = tf.repeat([i], tensor_shape[-1])
indices = tf.stack([j, tf.range(tensor_shape[-1])], axis=1)
ta = tf.tensor_scatter_nd_update(tf.cast(ta, dtype=tf.float32), indices, tf.map_fn(lambda t: dot(t), tensor[i]))
return tf.add(i, 1), ta, tensor
_, e, _ = tf.while_loop(while_condition, body, loop_vars=(i, e, tensor))
return e
tf.while_loop
确保批次中的每个样本独立于其他样本进行计算。
您的模特:
tensor1 = [1,2,3,4,5,6,7,8,9,10]
tensor1 = tf.convert_to_tensor(tensor1, dtype=tf.float32)
class TheFunctionLayer(Layer):
def call(self,tensor):
return TheFunction(tensor)
def TheFunctionModel(input_shape = (10, )):
x = Input(shape=input_shape)
y = TheFunctionLayer()(x)
model = keras.Model(inputs=x, outputs=y)
return model
model = TheFunctionModel()
print(model(tf.expand_dims(tensor1, axis=0)))
tf.Tensor([[ 130. 260. 390. 520. 650. 780. 910. 1040. 1170. 1300.]], shape=(1, 10), dtype=float32)
我正在尝试将函数建模为结合了自定义 Keras Layer
class 的 Keras 函数模型。这个想法是简单地让 Keras 层的 call
方法使用预定义的函数。该函数将输入一个给定的张量,比如 tensor1
,并为 tensor1
中的每个值 t
计算一个特定的点积。点积依赖于不同长度的张量(向量),但输出的是与 tensor1
.
当将 tensor1
传递给函数 TheFunction(tensor)
(定义如下)时,它 returns 是我预期的输出。此外,构建TheFunctionLayer
对象并传入tensor1
时,输出也符合预期,与TheFunction(tensor1)
.
当我尝试在同一事物上使用 Keras 的功能模型时出现问题。我正在尝试拥有它,以便我可以构建模型对象并将 tensor1
传递给它。但是,在尝试构建对象时,我得到了关于点积中张量维度的 ValueError
。但是如果我对模型定义中的输出声明做一点小改动,我会得到 TypeError
。下面是我的源代码和出现的问题:
进口:
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras.layers import Input, Layer
import numpy as np
涉及的张量:
tensor1 = [1,2,3,4,5,6,7,8,9,10]
tensor1 = tf.convert_to_tensor(tensor1, dtype=tf.float32)
tensor2 = [1,2,3,4,5]
tensor2 = tf.convert_to_tensor(tensor2, dtype=tf.float32)
tensor3 = [6,7,8,9,10]
tensor3 = tf.convert_to_tensor(tensor3, dtype=tf.float32)
点积函数:
def TheFunction(tensor):
tensor = tf.convert_to_tensor(tensor)
def prod_term(t):
return tensor3*t
def dot(t):
return tf.tensordot(tensor2,prod_term(t),axes=1)
return tf.map_fn(lambda t: dot(t), tensor)
点积函数的结果(维度没有问题):
<tf.Tensor: shape=(10,), dtype=float32, numpy=
array([ 130., 260., 390., 520., 650., 780., 910., 1040., 1170.,
1300.], dtype=float32)>
自定义Keras层(只需要call
,不需要__init__
):
class TheFunctionLayer(Layer):
def call(self,tensor):
return TheFunction(tensor)
TheFunctionLayer()(tensor1)
的结果(同样,尺寸没有问题):
<tf.Tensor: shape=(10,), dtype=float32, numpy=
array([ 130., 260., 390., 520., 650., 780., 910., 1040., 1170.,
1300.], dtype=float32)>
Keras 函数模型:
def TheFunctionModel(input_shape):
x = Input(shape=input_shape)
y = TheFunctionLayer()(x)
model = keras.Model(inputs=x, outputs=y)
return model
构建模型对象的结果TheFunctionModel(tf.shape(tensor1))
(与维度冲突):
ValueError: Dimensions must be equal, but are 5 and 10 for '{{node the_function_layer_19/map/while/mul}} = Mul[T=DT_FLOAT](the_function_layer_19/map/while/mul/x, the_function_layer_19/map/while/TensorArrayV2Read/TensorListGetItem)' with input shapes: [5], [10].
这里可能发生了什么?我对 TensorFlow 和 Keras 的工作方式还很陌生,但似乎如果我的函数的输出有效并且与张量维度没有冲突,为什么尝试构建模型对象会给我这个维度问题?
我要添加的另一件事是 TypeError
我在将 TheFunctionModel
的定义中的输出 y = TheFunctionLayer()(x)
更改为 y = TheFunctionLayer().call(x)
:
def TheFunctionModel(input_shape):
x = Input(shape=input_shape)
y = TheFunctionLayer().call(x)
model = keras.Model(inputs=x, outputs=y)
return model
TheFunctionModel(tf.shape(tensor1))
的结果(TypeError
而不是原来的 ValueError
):
TypeError: Could not build a TypeSpec for <KerasTensor: shape=(None, 10) dtype=float32 (created by layer 'tf.convert_to_tensor')> with type KerasTensor
如果更改模型定义中的输出是消除值错误的方法,那么我不确定我是否理解我遇到的类型错误以及如何修复它。
非常感谢对第一个值错误甚至第二个类型错误的建议和/或解决方案。
您忘记了批次维度,这就是它不起作用的原因。您将不得不像这样重写 TheFunction
:
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras.layers import Input, Layer
import numpy as np
tensor2 = tf.constant([1,2,3,4,5], dtype=tf.float32)
tensor3 = tf.constant([6,7,8,9,10], dtype=tf.float32)
def TheFunction(tensor):
def prod_term(t):
return tensor3*t
def dot(t):
return tf.tensordot(tensor2,prod_term(t),axes=1)
e = tf.zeros_like(tensor, dtype=tf.float32)
i = tf.constant(0)
while_condition = lambda i, e, tensor: tf.math.less(i, tf.shape(tensor)[0])
def body(i, ta, tensor):
tensor_shape = tf.shape(tensor)
j = tf.repeat([i], tensor_shape[-1])
indices = tf.stack([j, tf.range(tensor_shape[-1])], axis=1)
ta = tf.tensor_scatter_nd_update(tf.cast(ta, dtype=tf.float32), indices, tf.map_fn(lambda t: dot(t), tensor[i]))
return tf.add(i, 1), ta, tensor
_, e, _ = tf.while_loop(while_condition, body, loop_vars=(i, e, tensor))
return e
tf.while_loop
确保批次中的每个样本独立于其他样本进行计算。
您的模特:
tensor1 = [1,2,3,4,5,6,7,8,9,10]
tensor1 = tf.convert_to_tensor(tensor1, dtype=tf.float32)
class TheFunctionLayer(Layer):
def call(self,tensor):
return TheFunction(tensor)
def TheFunctionModel(input_shape = (10, )):
x = Input(shape=input_shape)
y = TheFunctionLayer()(x)
model = keras.Model(inputs=x, outputs=y)
return model
model = TheFunctionModel()
print(model(tf.expand_dims(tensor1, axis=0)))
tf.Tensor([[ 130. 260. 390. 520. 650. 780. 910. 1040. 1170. 1300.]], shape=(1, 10), dtype=float32)