如何在Keras中使用函数API调用自定义层

4
我写了一个小型的Keras自定义层实现,其中我从https://keras.io/layers/writing-your-own-keras-layers/中直接复制了类定义。但是,当我尝试像调用标准Dense层一样调用这个自定义层时,我会收到“AssertionError”错误,并且我的pycharm会发出警告说该对象不可调用。我在这里缺少一些基本的东西,但我无法弄清楚。如果我切换行
model_out = MyLayer(2)(model_in)

为了

model_out = Dense(2)(model_in)

它有效

这是无法运行的代码:

from tensorflow.keras.layers import Dense, Input
from tensorflow.keras.models import Model
import numpy as np
from tensorflow.keras.layers import Layer
from tensorflow.keras import backend as K
from tensorflow.keras import optimizers


class MyLayer(Layer):

    def __init__(self, output_dim, **kwargs):
        self.output_dim = output_dim
        super(MyLayer, self).__init__(**kwargs)

    def build(self, input_shape):
        # Create a trainable weight variable for this layer.
        self.kernel = self.add_weight(name='kernel',
                                      shape=(input_shape[1], self.output_dim),
                                      initializer='uniform',
                                      trainable=True)
        super(MyLayer, self).build(input_shape)  # Be sure to call this at the end

    def call(self, x):
        return K.dot(x, self.kernel)

    def compute_output_shape(self, input_shape):
        return (input_shape[0], self.output_dim)


model_in = Input([4])
model_out = MyLayer(2)(model_in)
model = Model(inputs=model_in, outputs=model_out, name='my_model')

adamOpt = optimizers.Adam(lr=1e-4)
model.compile(optimizer=adamOpt, loss='mean_squared_error')

hist = model.fit(np.ones((10, 4)), np.ones((10, 2))+1, verbose=2, epochs=100, batch_size=np.power(2,2))

我预计这段代码可以编译和运行,如果我调用Dense而不是MyLayer的话,就像原本的做法一样。
完整错误信息。
Traceback (most recent call last):
  File "C:\CDocuments\python\venv\lib\site-packages\tensorflow\python\framework\tensor_util.py", line 527, in make_tensor_proto
    str_values = [compat.as_bytes(x) for x in proto_values]
  File "C:\CDocuments\python\venv\lib\site-packages\tensorflow\python\framework\tensor_util.py", line 527, in <listcomp>
    str_values = [compat.as_bytes(x) for x in proto_values]
  File "C:\CDocuments\python\venv\lib\site-packages\tensorflow\python\util\compat.py", line 61, in as_bytes
    (bytes_or_text,))
TypeError: Expected binary or unicode string, got Dimension(4)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "G:/My Drive/python/wholebrain_worm/extra_classes.py", line 31, in <module>
    model_out = MyLayer(2)(model_in)
  File "C:\CDocuments\python\venv\lib\site-packages\tensorflow\python\keras\engine\base_layer.py", line 746, in __call__
    self.build(input_shapes)
  File "G:/My Drive/python/wholebrain_worm/extra_classes.py", line 20, in build
    trainable=True)
  File "C:\CDocuments\python\venv\lib\site-packages\tensorflow\python\keras\engine\base_layer.py", line 609, in add_weight
    aggregation=aggregation)
  File "C:\CDocuments\python\venv\lib\site-packages\tensorflow\python\training\checkpointable\base.py", line 639, in _add_variable_with_custom_getter
    **kwargs_for_getter)
  File "C:\CDocuments\python\venv\lib\site-packages\tensorflow\python\keras\engine\base_layer.py", line 1977, in make_variable
    aggregation=aggregation)
  File "C:\CDocuments\python\venv\lib\site-packages\tensorflow\python\ops\variables.py", line 183, in __call__
    return cls._variable_v1_call(*args, **kwargs)
  File "C:\CDocuments\python\venv\lib\site-packages\tensorflow\python\ops\variables.py", line 146, in _variable_v1_call
    aggregation=aggregation)
  File "C:\CDocuments\python\venv\lib\site-packages\tensorflow\python\ops\variables.py", line 125, in <lambda>
    previous_getter = lambda **kwargs: default_variable_creator(None, **kwargs)
  File "C:\CDocuments\python\venv\lib\site-packages\tensorflow\python\ops\variable_scope.py", line 2437, in default_variable_creator
    import_scope=import_scope)
  File "C:\CDocuments\python\venv\lib\site-packages\tensorflow\python\ops\variables.py", line 187, in __call__
    return super(VariableMetaclass, cls).__call__(*args, **kwargs)
  File "C:\CDocuments\python\venv\lib\site-packages\tensorflow\python\ops\resource_variable_ops.py", line 297, in __init__
    constraint=constraint)
  File "C:\CDocuments\python\venv\lib\site-packages\tensorflow\python\ops\resource_variable_ops.py", line 409, in _init_from_args
    initial_value() if init_from_fn else initial_value,
  File "C:\CDocuments\python\venv\lib\site-packages\tensorflow\python\keras\engine\base_layer.py", line 1959, in <lambda>
    shape, dtype=dtype, partition_info=partition_info)
  File "C:\CDocuments\python\venv\lib\site-packages\tensorflow\python\ops\init_ops.py", line 255, in __call__
    shape, self.minval, self.maxval, dtype, seed=self.seed)
  File "C:\CDocuments\python\venv\lib\site-packages\tensorflow\python\ops\random_ops.py", line 235, in random_uniform
    shape = _ShapeTensor(shape)
  File "C:\CDocuments\python\venv\lib\site-packages\tensorflow\python\ops\random_ops.py", line 44, in _ShapeTensor
    return ops.convert_to_tensor(shape, dtype=dtype, name="shape")
  File "C:\CDocuments\python\venv\lib\site-packages\tensorflow\python\framework\ops.py", line 1050, in convert_to_tensor
    as_ref=False)
  File "C:\CDocuments\python\venv\lib\site-packages\tensorflow\python\framework\ops.py", line 1146, in internal_convert_to_tensor
    ret = conversion_func(value, dtype=dtype, name=name, as_ref=as_ref)
  File "C:\CDocuments\python\venv\lib\site-packages\tensorflow\python\framework\constant_op.py", line 229, in _constant_tensor_conversion_function
    return constant(v, dtype=dtype, name=name)
  File "C:\CDocuments\python\venv\lib\site-packages\tensorflow\python\framework\constant_op.py", line 208, in constant
    value, dtype=dtype, shape=shape, verify_shape=verify_shape))
  File "C:\CDocuments\python\venv\lib\site-packages\tensorflow\python\framework\tensor_util.py", line 531, in make_tensor_proto
    "supported type." % (type(values), values))
TypeError: Failed to convert object of type <class 'tuple'> to Tensor. Contents: (Dimension(4), 2). Consider casting elements to a supported type.

1
你能发布所有的错误吗? - giser_yugang
如果您能发布详细的错误信息,那将会很有帮助。 - Shubham Panchal
谢谢你指出这个问题,我已经编辑了文章并包含了完整的错误信息。 - Matt Creamer
1个回答

0

我知道这是Keras创建新层的示例,你可以在这里找到。

一个非常重要的细节是,这是一个keras的示例,但你正在使用tf.keras。我认为tensorflow中一定有一个bug,因为这个示例可以在keras中工作,但不能在tf.keras中工作。

通常情况下,不应该混合使用kerastf.keras,因为它们具有相同的API但不具有相同的实现。如果你将所有的tf.keras导入更改为普通的keras,那么代码就可以正确地工作了。


是的,使用纯Keras对我有用。您知道我应该在哪里提交这个错误吗? - Matt Creamer
@MattCreamer 在 TensorFlow 的 Github 上开一个问题。 - Dr. Snoopy
我认为错误的关键在于tf.kerasinput_shape[1]的类型是<class 'tensorflow.python.framework.tensor_shape.Dimension'>,而在kerasinput_shape[1]的类型是int。只需要将input_shape[1]更改为input_shape.as_list()[1]即可。 - giser_yugang

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接