import math
from keras.layers import *
from keras.layers import Activation
from keras.layers import GlobalAveragePooling2D
import keras.backend asK
import tensorflow as tf
def eca_layer(inputs_tensor=None,num=None,gamma=2,b=1,**kwargs):"""
ECA-NET
:param inputs_tensor: input_tensor.shape=[batchsize,h,w,channels]
:param num:
:param gamma:
:param b:
:return:
"""
channels =K.int_shape(inputs_tensor)[-1]
t =int(abs((math.log(channels,2)+b)/gamma))
k = t if t%2else t+1
x_global_avg_pool =GlobalAveragePooling2D()(inputs_tensor)
x =Reshape((channels,1))(x_global_avg_pool)
x =Conv1D(1,kernel_size=k,padding="same",name="eca_conv1_"+str(num))(x)
x =Activation('sigmoid', name='eca_conv1_relu_'+str(num))(x)#shape=[batch,chnnels,1]
x =Reshape((1,1, channels))(x)
output =multiply([inputs_tensor,x])return output
import math
import numpy as np
import tensorflow as tf
from keras import backend
from keras import backend asK
from keras.applications import imagenet_utils
from keras.applications.imagenet_utils import decode_predictions
from keras.layers import (Activation, Add, Conv2D, Dense, DepthwiseConv2D, Reshape, MaxPooling2D,UpSampling2D,
Dropout, GlobalAveragePooling2D, GlobalMaxPooling2D, Multiply, Concatenate,AveragePooling2D,
Input, Lambda, MaxPooling2D, ZeroPadding2D)
from keras.layers.normalization import BatchNormalization
from keras.models import Model
from keras.preprocessing import image
from keras.utils.data_utils import get_file
def hard_swish(x):return x *K.relu(x +3.0, max_value=6.0)/6.0
def relu6(x):returnK.relu(x, max_value=6)
def _conv_block(inputs, filters, kernel=(3,3), strides=(1,1)):x=Conv2D(filters, kernel,
padding='same',
use_bias=False,
strides=strides,
name='conv1')(inputs)
x =BatchNormalization(name='conv1_bn')(x)returnActivation(hard_swish, name='conv1_relu')(x)
def squeeze_dw(inputs, block_id=0):# 注意力机制单元
input_channels =int(inputs.shape[-1])
x =GlobalAveragePooling2D(name="conv_dw_%d_se_gap"% block_id)(inputs)
x =Dense(int(input_channels /16), kernel_initializer='random_uniform', name="conv_dw_%d_se_fc1"% block_id)(x)
x =Activation(K.relu, name="conv_dw_%d_se_relu"% block_id)(x)
x =Dense(input_channels, kernel_initializer='random_uniform', name="conv_dw_%d_se_fc2"% block_id)(x)
x =Activation(K.sigmoid, name="conv_dw_%d_se_sigmoid"% block_id)(x)
x =Reshape((1,1, input_channels), name="conv_dw_%d_se_reshape"% block_id)(x)
x =Multiply()([inputs, x])return x
def squeeze_pw(inputs, block_id=0):# 注意力机制单元
input_channels =int(inputs.shape[-1])
x =GlobalAveragePooling2D(name="conv_pw_%d_se_gap"% block_id)(inputs)
x =Dense(int(input_channels /16), kernel_initializer='random_uniform', name="conv_pw_%d_se_fc1"% block_id)(x)
x =Activation(K.relu, name="conv_pw_%d_se_relu"% block_id)(x)
x =Dense(input_channels, kernel_initializer='random_uniform', name="conv_pw_%d_se_fc2"% block_id)(x)
x =Activation(K.sigmoid, name="conv_pw_%d_se_sigmoid"% block_id)(x)
x =Reshape((1,1, input_channels), name="conv_pw_%d_se_reshape"% block_id)(x)
x =Multiply()([inputs, x])return x
def _depthwise_conv_block(inputs, sq_dw, sq_pw,pointwise_conv_filters, depth_multiplier=1, strides=(1,1), block_id=1):x=DepthwiseConv2D((3,3),
padding='same',
depth_multiplier=depth_multiplier,
strides=strides,
use_bias=False,
name='conv_dw_%d'% block_id)(inputs)
x =BatchNormalization(name='conv_dw_%d_bn'% block_id)(x)
x =Activation(hard_swish, name='conv_dw_%d_relu'% block_id)(x)# 引入注意力机制ifsq_dw:
x =squeeze_dw(x, block_id=block_id)# 点卷积
x =Conv2D(pointwise_conv_filters,(1,1),
padding='same',
use_bias=False,
strides=(1,1),
name='conv_pw_%d'% block_id)(x)
x =BatchNormalization(name='conv_pw_%d_bn'% block_id)(x)
x =Activation(hard_swish, name='conv_pw_%d_relu'% block_id)(x)# 引入注意力机制ifsq_pw:
x =squeeze_pw(x, block_id=block_id)return x
def MobileNet_V1(inputs, sq_dw, sq_pw, embedding_size=128, dropout_keep_prob=0.4, alpha=1.0, depth_multiplier=1):# 160,160,3 -> 80,80,32# 128,128,3 -> 64,64,32
x =_conv_block(inputs,32, strides=(2,2))# 80,80,32 -> 80,80,64# 64,64,32 -> 64,64,64
x =_depthwise_conv_block(x, sq_dw, sq_pw,64, depth_multiplier, strides=(1,1), block_id=1)# 80,80,64 -> 40,40,128# 64,64,64 -> 32,32,128
x =_depthwise_conv_block(x, sq_dw, sq_pw,128, depth_multiplier, strides=(2,2), block_id=2)
x =_depthwise_conv_block(x, sq_dw, sq_pw,128, depth_multiplier, block_id=3)# 40,40,128 -> 20,20,256# 32,32,128 -> 16,16,256
x =_depthwise_conv_block(x, sq_dw, sq_pw,256, depth_multiplier, strides=(2,2), block_id=4)
x =_depthwise_conv_block(x, sq_dw, sq_pw,256, depth_multiplier, block_id=5)# x3 = _depthwise_conv_block(x, sq_dw, sq_pw, 256, depth_multiplier, block_id=5)# 20,20,256 -> 10,10,512# 16,16,256 -> 8,8,512
x =_depthwise_conv_block(x, sq_dw, sq_pw,512, depth_multiplier, strides=(2,2), block_id=6)# x = _depthwise_conv_block(x3, sq_dw, sq_pw, 512, depth_multiplier, strides=(2, 2), block_id=6)
x =_depthwise_conv_block(x, sq_dw, sq_pw,512, depth_multiplier, block_id=7)
x =_depthwise_conv_block(x, sq_dw, sq_pw,512, depth_multiplier, block_id=8)
x =_depthwise_conv_block(x, sq_dw, sq_pw,512, depth_multiplier, block_id=9)
x =_depthwise_conv_block(x, sq_dw, sq_pw,512, depth_multiplier, block_id=10)
x =_depthwise_conv_block(x, sq_dw, sq_pw,512, depth_multiplier, block_id=11)# x2 = _depthwise_conv_block(x, sq_dw, sq_pw, 512, depth_multiplier, block_id=11)# 10,10,512 -> 5,5,1024# 8, 8, 512 -> 4, 4, 1024
x =_depthwise_conv_block(x, sq_dw, sq_pw,1024, depth_multiplier, strides=(2,2), block_id=12)# x = _depthwise_conv_block(x2, sq_dw, sq_pw, 1024, depth_multiplier, strides=(2, 2), block_id=12)
x =_depthwise_conv_block(x, sq_dw, sq_pw,1024, depth_multiplier, block_id=13)# x1 = _depthwise_conv_block(x, sq_dw, sq_pw, 1024, depth_multiplier, block_id=13)# 1024# 全局平局池化层# x = GlobalAveragePooling2D()(x)# x = Reshape((1, 1, 1024))(x)# dw替换gap
x =DepthwiseConv2D((5,5),
padding='valid',
depth_multiplier=1,
strides=(1,1),
use_bias=False,
name='conv_dw_14')(x)
x =Reshape((1024,), name="reshape_1024")(x)# 空间金字塔池化结构 spp# maxpool1 = MaxPooling2D(pool_size=(20, 20), strides=(1, 1), padding="same")(x3)# maxpool2 = MaxPooling2D(pool_size=(10, 10), strides=(1, 1), padding="same")(x2)# maxpool3 = MaxPooling2D(pool_size=(5, 5), strides=(1, 1), padding="same")(x1)# x = Concatenate()([maxpool1, maxpool2, maxpool3, x])# x = Reshape((2304,), name="reshape_1024")(x)# 空间金字塔池化结构 spp# maxpool1 = AveragePooling2D(pool_size=(20, 20), strides=(1, 1), padding="valid")(x3)# maxpool2 = AveragePooling2D(pool_size=(10, 10), strides=(1, 1), padding="valid")(x2)# maxpool3 = AveragePooling2D(pool_size=(5, 5), strides=(1, 1), padding="valid")(x1)# x = Concatenate()([maxpool1, maxpool2, maxpool3, x])# x = Reshape((2816,), name="reshape_1024")(x)# 防止网络过拟合,训练的时候起作用
x =Dropout(1.0- dropout_keep_prob, name='Dropout')(x)# 全连接层到128# 128
x =Dense(embedding_size, use_bias=False, name='Bottleneck')(x)
x =BatchNormalization(momentum=0.995, epsilon=0.001, scale=False,
name='BatchNorm_Bottleneck')(x)# 创建模型
model =Model(inputs, x, name='mobilenet_v1')return model
if __name__ =="__main__":
inputs =Input([160,160,3])# inputs = Input([128, 128, 3])
model =MobileNet_V1(inputs, sq_dw=False, sq_pw=True)
model.summary()