【KERAS】Keras实现自定义层的多输出,AttributeError: 'tuple' object has no attribute '_keras_shape'

在用Keras编写自己的层的时候,需要得到两个输出,困扰了好一会,上网查资料也没有找到满意的答案,然后就根据错误提示查看源码解决问题。

C:\Anaconda3\python.exe D:/yangzhaolu/KERAS/Keras-Segmentation/test.py
Using TensorFlow backend.
Traceback (most recent call last):
  File "D:/yangzhaolu/KERAS/Keras-Segmentation/test.py", line 22, in <module>
    avgpool()
  File "D:/yangzhaolu/KERAS/Keras-Segmentation/test.py", line 15, in avgpool
    x, ind= MaxPooling2DWithArgmax(pool_size=(2,2))(img_input)
  File "C:\Anaconda3\lib\site-packages\keras\engine\topology.py", line 655, in __call__
    arguments=user_kwargs)
  
File "C:\Anaconda3\lib\site-packages\keras\engine\topology.py", line 717, in _add_inbound_node
    output_tensors[i]._keras_shape = output_shapes[i]
AttributeError: 'tuple' object has no attribute '_keras_shape'

以上代码是在编写MaxPooling2DWithArgmax层时遇到错误,MaxPooling2DWithArgmax层是用来实现语义分割SegNet网络中记录最大池化位置的一个网络层,我需要得到池化的结果pool以及池化结果的位置indices两个输出。以上是一个简单的介绍下面是解决方法:

根据错误提示找到源码:

File "C:\Anaconda3\lib\site-packages\keras\engine\topology.py", line 717, in _add_inbound_node
    output_tensors[i]._keras_shape = output_shapes[i]
AttributeError: 'tuple' object has no attribute '_keras_shape'

源码:

# Update tensor history, _keras_shape and _uses_learning_phase.
for i in range(len(output_tensors)):
    output_tensors[i]._keras_shape = output_shapes[i]
    uses_lp = any([getattr(x, '_uses_learning_phase', False) for x in input_tensors])
    uses_lp = getattr(self, 'uses_learning_phase', False) or uses_lp
    output_tensors[i]._uses_learning_phase = getattr(output_tensors[i], '_uses_learning_phase', False) or uses_lp
    output_tensors[i]._keras_history = (self, len(self._inbound_nodes) - 1, i)

然后顺着代码往上找:

# Arguments
input_tensors: list of input tensors.
output_tensors: list of output tensors.

这里的参数要求的是输出向量应该是列表类型,因此需要将输出向量的output_shape以及输出向量都放在一个list列表里面。

   
    def compute_output_shape(self, input_shape):
        if self.data_format == 'channels_first':
            rows = input_shape[2]
            cols = input_shape[3]
        elif self.data_format == 'channels_last':
            rows = input_shape[1]
            cols = input_shape[2]
        rows = conv_utils.conv_output_length(rows, self.pool_size[0], self.padding, self.strides[0])
        cols = conv_utils.conv_output_length(cols, self.pool_size[1], self.padding, self.strides[1])
        if self.data_format == 'channels_first':
            return [(input_shape[0], input_shape[1], rows, cols), (input_shape[0], input_shape[1], rows, cols)] # 转换成列表
        elif self.data_format == 'channels_last':
            return [(input_shape[0], rows, cols, input_shape[3]), (input_shape[0], rows, cols, input_shape[3])] # 转换成列表

    def _pooling_function(self, inputs, pool_size, strides,
                          padding, data_format):
        raise NotImplementedError

    def call(self, inputs):
        output, indices = self._pooling_function(inputs=inputs,
                                        pool_size=self.pool_size,
                                        strides=self.strides,
                                        padding=self.padding,
                                        data_format=self.data_format)
        return [output, indices] # 转换成列表

多输入的情况,同样道理,例如两个tensor相加,直接用Add() 层

Add()([x1, x2])

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值