123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- # Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
- #
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- # http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- from __future__ import absolute_import
- from __future__ import division
- from __future__ import print_function
- from __future__ import unicode_literals
- import paddle.fluid as fluid
- from paddle.fluid import ParamAttr
- from paddle.fluid.initializer import ConstantInitializer
- def spatial_pool(x, pooling_type, name):
- _, channel, height, width = x.shape
- if pooling_type == 'att':
- input_x = x
- # [N, 1, C, H * W]
- input_x = fluid.layers.reshape(input_x, shape=(0, 1, channel, -1))
- context_mask = fluid.layers.conv2d(
- input=x,
- num_filters=1,
- filter_size=1,
- stride=1,
- padding=0,
- param_attr=ParamAttr(name=name + "_weights"),
- bias_attr=ParamAttr(name=name + "_bias"))
- # [N, 1, H * W]
- context_mask = fluid.layers.reshape(context_mask, shape=(0, 0, -1))
- # [N, 1, H * W]
- context_mask = fluid.layers.softmax(context_mask, axis=2)
- # [N, 1, H * W, 1]
- context_mask = fluid.layers.reshape(context_mask, shape=(0, 0, -1, 1))
- # [N, 1, C, 1]
- context = fluid.layers.matmul(input_x, context_mask)
- # [N, C, 1, 1]
- context = fluid.layers.reshape(context, shape=(0, channel, 1, 1))
- else:
- # [N, C, 1, 1]
- context = fluid.layers.pool2d(
- input=x, pool_type='avg', global_pooling=True)
- return context
- def channel_conv(input, inner_ch, out_ch, name):
- conv = fluid.layers.conv2d(
- input=input,
- num_filters=inner_ch,
- filter_size=1,
- stride=1,
- padding=0,
- param_attr=ParamAttr(name=name + "_conv1_weights"),
- bias_attr=ParamAttr(name=name + "_conv1_bias"),
- name=name + "_conv1", )
- conv = fluid.layers.layer_norm(
- conv,
- begin_norm_axis=1,
- param_attr=ParamAttr(name=name + "_ln_weights"),
- bias_attr=ParamAttr(name=name + "_ln_bias"),
- act="relu",
- name=name + "_ln")
- conv = fluid.layers.conv2d(
- input=conv,
- num_filters=out_ch,
- filter_size=1,
- stride=1,
- padding=0,
- param_attr=ParamAttr(
- name=name + "_conv2_weights",
- initializer=ConstantInitializer(value=0.0), ),
- bias_attr=ParamAttr(
- name=name + "_conv2_bias",
- initializer=ConstantInitializer(value=0.0), ),
- name=name + "_conv2")
- return conv
- def add_gc_block(x,
- ratio=1.0 / 16,
- pooling_type='att',
- fusion_types=['channel_add'],
- name=None):
- '''
- GCNet: Non-local Networks Meet Squeeze-Excitation Networks and Beyond, see https://arxiv.org/abs/1904.11492
- Args:
- ratio (float): channel reduction ratio
- pooling_type (str): pooling type, support att and avg
- fusion_types (list): fusion types, support channel_add and channel_mul
- name (str): prefix name of gc block
- '''
- assert pooling_type in ['avg', 'att']
- assert isinstance(fusion_types, (list, tuple))
- valid_fusion_types = ['channel_add', 'channel_mul']
- assert all([f in valid_fusion_types for f in fusion_types])
- assert len(fusion_types) > 0, 'at least one fusion should be used'
- inner_ch = int(ratio * x.shape[1])
- out_ch = x.shape[1]
- context = spatial_pool(x, pooling_type, name + "_spatial_pool")
- out = x
- if 'channel_mul' in fusion_types:
- inner_out = channel_conv(context, inner_ch, out_ch, name + "_mul")
- channel_mul_term = fluid.layers.sigmoid(inner_out)
- out = out * channel_mul_term
- if 'channel_add' in fusion_types:
- channel_add_term = channel_conv(context, inner_ch, out_ch,
- name + "_add")
- out = out + channel_add_term
- return out
|