基于tensorflow2.5,将Channel Attention部分中的全局平均池化替换为L2池化,对于Spatial Attention,将max pooling和average pooling分别替换为随机池化和L2池化,二者结合形成新的CBAM模块,并给出使用示例
时间: 2024-05-15 14:19:34 浏览: 167
Spatial Pyramid Pooling in Deep Convolutional Networks for Visua
首先,我们需要定义L2池化和随机池化的函数:
```python
import tensorflow as tf
def l2_pool(x, pool_size):
return tf.math.sqrt(tf.nn.avg_pool(tf.square(x), pool_size, strides=1, padding='SAME'))
def rand_pool(x, pool_size):
random_mat = tf.random.uniform(x.shape[:-1], dtype=tf.float32)
threshold = tf.math.reduce_max(random_mat) * 0.5
return tf.where(random_mat > threshold, tf.nn.avg_pool(x, pool_size, strides=1, padding='SAME'), tf.nn.max_pool(x, pool_size, strides=1, padding='SAME'))
```
然后,我们可以定义新的CBAM模块:
```python
import tensorflow as tf
class NewCBAM(tf.keras.layers.Layer):
def __init__(self, reduction_ratio=16):
super(NewCBAM, self).__init__()
self.reduction_ratio = reduction_ratio
self.gamma = tf.Variable(0.0, trainable=True)
# Channel Attention
self.avg_pool = tf.keras.layers.GlobalAveragePooling2D()
self.max_pool = tf.keras.layers.GlobalMaxPooling2D()
self.l2_pool = tf.keras.layers.Lambda(lambda x: l2_pool(x, pool_size=(1,1)))
self.dense1 = tf.keras.layers.Dense(units=tf.keras.backend.int_shape(x)[-1]//self.reduction_ratio, activation='relu')
self.dense2 = tf.keras.layers.Dense(units=tf.keras.backend.int_shape(x)[-1], activation='sigmoid')
# Spatial Attention
self.rand_pool = tf.keras.layers.Lambda(lambda x: rand_pool(x, pool_size=(3,3)))
self.l2_pool2 = tf.keras.layers.Lambda(lambda x: l2_pool(x, pool_size=(3,3)))
self.concat1 = tf.keras.layers.Concatenate(axis=-1)
self.conv1 = tf.keras.layers.Conv2D(filters=1, kernel_size=1, activation='sigmoid')
def call(self, x):
# Channel Attention
avg_pool = self.avg_pool(x)
max_pool = self.max_pool(x)
l2_pool = self.l2_pool(x)
concat = tf.concat([avg_pool, max_pool, l2_pool], axis=-1)
dense1 = self.dense1(concat)
dense2 = self.dense2(dense1)
channel_attention = tf.reshape(dense2, shape=(-1,1,1,tf.keras.backend.int_shape(x)[-1]))
channel_attention = tf.math.multiply(x, channel_attention)
# Spatial Attention
rand_pool = self.rand_pool(x)
l2_pool2 = self.l2_pool2(x)
concat2 = tf.concat([rand_pool, l2_pool2], axis=-1)
conv1 = self.conv1(concat2)
spatial_attention = tf.math.multiply(x, conv1)
# Fusion
fusion = tf.math.add(channel_attention, spatial_attention)
return tf.math.add(tf.math.multiply(x, 1-self.gamma), tf.math.multiply(fusion, self.gamma))
```
最后,我们可以使用新的CBAM模块:
```python
import tensorflow as tf
inputs = tf.keras.layers.Input(shape=(224, 224, 3))
x = tf.keras.layers.Conv2D(filters=64, kernel_size=3, padding='SAME')(inputs)
x = NewCBAM()(x)
x = tf.keras.layers.Conv2D(filters=128, kernel_size=3, padding='SAME')(x)
x = NewCBAM()(x)
x = tf.keras.layers.Conv2D(filters=256, kernel_size=3, padding='SAME')(x)
x = NewCBAM()(x)
x = tf.keras.layers.Conv2D(filters=512, kernel_size=3, padding='SAME')(x)
x = NewCBAM()(x)
x = tf.keras.layers.Conv2D(filters=1024, kernel_size=3, padding='SAME')(x)
x = NewCBAM()(x)
outputs = tf.keras.layers.GlobalAveragePooling2D()(x)
model = tf.keras.Model(inputs=inputs, outputs=outputs)
```
阅读全文