MobileNetv3完整代码
时间: 2025-05-13 18:50:46 浏览: 29
### MobileNetV3 的完整实现代码
以下是基于 PyTorch 和 TensorFlow 的 MobileNetV3 完整实现代码示例:
#### 基于 PyTorch 的 MobileNetV3 实现
```python
import torch.nn as nn
import torch
class h_swish(nn.Module):
def forward(self, x):
return x * nn.functional.relu6(x + 3) / 6
class SEBlock(nn.Module):
def __init__(self, channel, reduction=4):
super(SEBlock, self).__init__()
self.avg_pool = nn.AdaptiveAvgPool2d(1)
self.fc = nn.Sequential(
nn.Linear(channel, channel // reduction),
nn.ReLU(inplace=True),
nn.Linear(channel // reduction, channel),
h_swish()
)
def forward(self, x):
b, c, _, _ = x.size()
y = self.avg_pool(x).view(b, c)
y = self.fc(y).view(b, c, 1, 1)
return x * y
def conv_bn(inp, oup, stride, activation=nn.ReLU):
return nn.Sequential(
nn.Conv2d(inp, oup, 3, stride, 1, bias=False),
nn.BatchNorm2d(oup),
activation()
)
def depthwise_conv(in_channels, out_channels, kernel_size=3, stride=1, padding=0, groups=None):
if not groups:
groups = in_channels
return nn.Conv2d(in_channels, out_channels, kernel_size, stride=stride, padding=padding, groups=groups)
class Bottleneck(nn.Module):
def __init__(self, inp, hidden_dim, oup, kernel_size, stride, use_se, use_hs):
super(Bottleneck, self).__init__()
assert stride in [1, 2]
layers = []
# Point-wise convolution (expand phase)
layers.append(conv_bn(inp, hidden_dim, 1))
# Depth-wise convolution
layers.append(depthwise_conv(hidden_dim, hidden_dim, kernel_size, stride))
if use_se:
layers.append(SEBlock(hidden_dim)) # Add Squeeze-and-Excitation block
if use_hs:
act_layer = h_swish
else:
act_layer = nn.ReLU
layers.append(act_layer())
# Linear point-wise projection
layers.append(nn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False))
layers.append(nn.BatchNorm2d(oup))
self.conv = nn.Sequential(*layers)
self.residual_connection = (stride == 1 and inp == oup)
def forward(self, x):
if self.residual_connection:
return x + self.conv(x)
else:
return self.conv(x)
class MobileNetV3_Large(nn.Module):
def __init__(self, num_classes=1000):
super(MobileNetV3_Large, self).__init__()
cfgs = [
# k, t, c, SE, HS, s
[3, 16, 16, False, True, 1],
[3, 64, 24, False, True, 2],
[3, 72, 24, False, True, 1],
[5, 72, 40, True, True, 2],
[5, 120, 40, True, True, 1],
[5, 120, 40, True, True, 1],
[3, 240, 80, False, True, 2],
[3, 200, 80, False, True, 1],
[3, 184, 80, False, True, 1],
[3, 184, 80, False, True, 1],
[3, 480, 112, True, True, 1],
[3, 672, 112, True, True, 1],
[5, 672, 160, True, True, 2],
[5, 960, 160, True, True, 1],
[5, 960, 160, True, True, 1]
]
input_channel = 16
last_channel = 1280
features = [conv_bn(3, input_channel, 2)]
for k, exp_size, c, use_se, use_hs, s in cfgs:
output_channel = c
features.append(Bottleneck(input_channel, exp_size, output_channel, k, s, use_se, use_hs))
input_channel = output_channel
features.append(conv_bn(input_channel, last_channel, 1))
self.features = nn.Sequential(*features)
self.classifier = nn.Sequential(
nn.Dropout(0.2),
nn.Linear(last_channel, num_classes)
)
def forward(self, x):
x = self.features(x)
x = nn.functional.adaptive_avg_pool2d(x, 1).reshape(x.shape[0], -1)
x = self.classifier(x)
return x
```
#### 基于 TensorFlow 的 MobileNetV3 实现
```python
import tensorflow as tf
from tensorflow.keras import layers, models
def hard_swish(x):
return x * tf.nn.relu6(x + 3) / 6
def se_block(inputs, filters, ratio=4):
init = inputs
pool = layers.GlobalAveragePooling2D()(inputs)
dense1 = layers.Dense(filters // ratio)(pool)
relu = layers.Activation('relu')(dense1)
dense2 = layers.Dense(filters)(relu)
sigm = layers.Activation('sigmoid')(dense2)
scale = layers.Reshape((1, 1, filters))(sigm)
mul = layers.Multiply()([scale, init])
return mul
def bottleneck(inputs, expansion, filters, kernel_size, strides, se_ratio, hs_activation):
channels_in = inputs.shape[-1]
expanded_filters = int(channels_in * expansion)
x = layers.Conv2D(expanded_filters, 1, padding='same', use_bias=False)(inputs)
x = layers.BatchNormalization()(x)
x = hard_swish(x) if hs_activation else layers.ReLU()(x)
x = layers.DepthwiseConv2D(kernel_size, strides=strides, padding='same', use_bias=False)(x)
x = layers.BatchNormalization()(x)
if se_ratio is not None:
x = se_block(x, expanded_filters, se_ratio)
x = layers.Conv2D(filters, 1, padding='same', use_bias=False)(x)
x = layers.BatchNormalization()(x)
if all(s == 1 for s in strides) and channels_in == filters:
x = layers.Add()([x, inputs])
return x
def mobilenet_v3_large(num_classes=1000):
inputs = layers.Input(shape=(224, 224, 3))
x = layers.Conv2D(16, 3, strides=2, padding='same', use_bias=False)(inputs)
x = layers.BatchNormalization()(x)
x = hard_swish(x)
config = [
(1, 16, 3, 1, None, False), # Expansion, Filters, Kernel Size, Strides, SE Ratio, Hard Swish
(4, 24, 3, 2, None, False),
(3, 24, 3, 1, None, False),
(3, 40, 5, 2, 4, True),
(3, 40, 5, 1, 4, True),
(3, 40, 5, 1, 4, True),
(6, 80, 3, 2, None, True),
(2.5, 80, 3, 1, None, True),
(2.3, 80, 3, 1, None, True),
(2.3, 80, 3, 1, None, True),
(6, 112, 3, 1, 4, True),
(6, 112, 3, 1, 4, True),
(6, 160, 5, 2, 4, True),
(6, 160, 5, 1, 4, True),
(6, 160, 5, 1, 4, True)
]
for expansion, filters, kernel_size, strides, se_ratio, hs_activation in config:
x = bottleneck(x, expansion, filters, kernel_size, strides, se_ratio, hs_activation)
x = layers.Conv2D(960, 1, padding='same', use_bias=False)(x)
x = layers.BatchNormalization()(x)
x = hard_swish(x)
x = layers.AveragePooling2D(pool_size=(7, 7))(x)
x = layers.Conv2D(1280, 1, padding='same')(x)
x = hard_swish(x)
outputs = layers.Conv2D(num_classes, 1, activation='softmax', padding='same')(x)
model = models.Model(inputs, outputs)
return model
```
上述代码实现了 MobileNetV3-Large 版本的架构,其中包含了轻量级注意力模块[^3]以及 h-swish 激活函数。
阅读全文
相关推荐

















