"ValueError: Unknown layer: ... "使用 Tensorflow 调用 copy.deepcopy(network) 时 [英] "ValueError: Unknown layer: ... " when calling copy.deepcopy(network) using Tensorflow

查看:58
本文介绍了"ValueError: Unknown layer: ... "使用 Tensorflow 调用 copy.deepcopy(network) 时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在 Tensorflow 中设计一个 NoisyNet,我需要为其定义一个自定义层.复制包含该自定义层的模型时,python 会引发错误 ValueError: Unknown layer: NoisyLayer.提供了层的实现 这里.

I am currently designing a NoisyNet in Tensorflow, for which I need to define a custom layer. When copying a model containing that custom layer, python raises the error ValueError: Unknown layer: NoisyLayer. The implementation of the layer is provided here.

目标是复制一个网络,创建它的第二个实例.为此,我使用命令 net_copy = copy.deepcopy(net_original),只要我不在要复制的模型中包含上面提到的自定义层,该命令就可以使用.我看到为了保存和加载存在一种指定自定义属性(例如自定义图层)的方法,但是我找不到适用于 copy.deepcopy() 的类似命令,其中副本通过import copy导入.

The goal is to copy one network creating a second instance of it. For that purpose, I use the command net_copy = copy.deepcopy(net_original), which works as long as I don't include the custom layer referred to above in the model to be copied. I saw that for saving and loading there exists a way of specifying custom attributes (such as custom layers), but yet I couldn't find a similar command that would work for copy.deepcopy(), where copy is imported via import copy.

我在 Python3 中使用 Tensorflow 1.12.0.

I am using Tensorflow 1.12.0 in Python3.

同样,自定义层在上面的链接下提供.使用自定义层的网络如下所示:

Again, the custom layer is provided under the link above. The network that uses the custom layer looks as follows:

class Network:
    def __init__(self, actionspace_size, learning_rate, gradient_momentum, gradient_min):
        frames_input = keras.layers.Input((84, 84, 4))
        actions_input = keras.layers.Input((actionspace_size,))

        conv1 = keras.layers.Conv2D(16, (8, 8), strides=(4, 4), activation="relu")(frames_input)
        conv2 = keras.layers.Conv2D(32, (4, 4), strides=(2, 2), activation="relu")(conv1)

        flattened = keras.layers.Flatten()(conv2)

        # NoisyNet        
        hidden = NoisyLayer(activation=tf.nn.relu)(inputs=flattened, resample_noise_flag=True)
        output = NoisyLayer(in_shape=(1,256), out_units=actionspace_size)(inputs=hidden, resample_noise_flag=True)

        filtered_output = keras.layers.merge.Multiply()([output, actions_input])

        self.model = keras.models.Model(inputs=[frames_input, actions_input], outputs=filtered_output)

        self.model.compile(loss='mse', optimizer=keras.optimizers.RMSprop(lr=learning_rate, rho=gradient_momentum, epsilon=gradient_min))

打电话时

q_net = Network(actionspace_size, learning_rate, gradient_momentum, gradient_min).
target_net = copy.deepcopy(q_net)

出现以下错误:

Traceback (most recent call last):
  File "DQN_tf_NoisyNet.py", line 315, in <module>
    main()
  File "DQN_tf_NoisyNet.py", line 252, in main
    target_net = copy.deepcopy(q_net)
  File "/usr/lib/python3.5/copy.py", line 182, in deepcopy
    y = _reconstruct(x, rv, 1, memo)
  File "/usr/lib/python3.5/copy.py", line 299, in _reconstruct
    y.__setstate__(state)
  File "/usr/local/lib/python3.5/dist-packages/keras/engine/network.py", line 1266, in __setstate__
    model = saving.unpickle_model(state)
  File "/usr/local/lib/python3.5/dist-packages/keras/engine/saving.py", line 435, in unpickle_model
    return _deserialize_model(f)
  File "/usr/local/lib/python3.5/dist-packages/keras/engine/saving.py", line 225, in _deserialize_model
    model = model_from_config(model_config, custom_objects=custom_objects)
  File "/usr/local/lib/python3.5/dist-packages/keras/engine/saving.py", line 458, in model_from_config
    return deserialize(config, custom_objects=custom_objects)
  File "/usr/local/lib/python3.5/dist-packages/keras/layers/__init__.py", line 55, in deserialize
    printable_module_name='layer')
  File "/usr/local/lib/python3.5/dist-packages/keras/utils/generic_utils.py", line 145, in deserialize_keras_object
    list(custom_objects.items())))
  File "/usr/local/lib/python3.5/dist-packages/keras/engine/network.py", line 1022, in from_config
    process_layer(layer_data)
  File "/usr/local/lib/python3.5/dist-packages/keras/engine/network.py", line 1008, in process_layer
    custom_objects=custom_objects)
  File "/usr/local/lib/python3.5/dist-packages/keras/layers/__init__.py", line 55, in deserialize
    printable_module_name='layer')
  File "/usr/local/lib/python3.5/dist-packages/keras/utils/generic_utils.py", line 138, in deserialize_keras_object
    ': ' + class_name)
ValueError: Unknown layer: NoisyLayer

我知道网络本身不是问题(深度复制方法都不是),因为一旦我用标准密集层替换了 NoisyLayers(自定义),两者都可以正常工作.

I know that the network itself is not the problem (neither the deepcopy approach), since both work fine again as soon as I replace the NoisyLayers (custom) by standard dense layers.

有谁知道如何复制包含自定义层的 Tensorflow 模型?提前致谢!

Does anyone know how to copy a Tensorflow model including custom layers? Thanks in advance!

推荐答案

找到解决方案:

问题再次在于 Tensorflow/Keras 不知道如何解释自定义层.因此,为了提供如何解释层的信息,可以使用 Keras 的 CustomObjectScope 并在该范围内复制模型,如下所示:

The problem, again, was that Tensorflow/Keras didn't know how to interpret the custom layer. So, to provide the information how to interpret a layer, one can use Keras's CustomObjectScope and copy the model within that scope as follows:

# Import
import copy
from keras.utils import CustomObjectScope

# Copy
with CustomObjectScope({"MyCustomLayer":MyCustomLayer}):
        model_copy = copy.deepcopy(model)

这负责复制部分.但是,只要没有将自定义输入指定为自定义层的构造函数 (__init(...)) 的参数,这只会开箱即用.

This takes care of the copying part. However, this is only going to work out of the box as long as there is no custom inputs specified as parameters to the custom layer's constructor (__init(...)).

我猜是这种情况,因为在幕后 copy() 函数似乎暂时保存,然后使用一些 pickle 功能重新加载原始模型,这样就必须声明值进一步的构造函数参数以及如下:

I guess this is case since behind the scenes the copy() function seems to temporarily save and then load again the original model using some pickle-functionality or so, such that one has to declare values for further constructor-parameters as well as follows:

如果自定义类的开头如下所示,其中output_dim是上面提到的自定义参数之一:

If the beginning of the custom class looks as follows, where output_dim is one of the custom parameters referred to above:

class MyCustomLayer(keras.layers.Layer):

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

然后必须向 MyCustomLayer 类添加一个函数,该函数还负责使自定义构造函数参数持久保存和加载(复制时):

then one has to add a function to the class MyCustomLayer that also takes care of making the custom constructor parameters persistent for saving and loading (while copying):

def get_config(self):
        config = super(MyCustomLayer, self).get_config()

        # Specify here all the values for the constructor's parameters
        config['output_dim'] = self.output_dim

        return config

这两个步骤解决了我的问题.

These two steps solved the problem in my case.

这篇关于&quot;ValueError: Unknown layer: ... &quot;使用 Tensorflow 调用 copy.deepcopy(network) 时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆