EXPERIMENT / 配套代码
main.py
← 返回文章在项目根目录执行;下载包解压后,在解压目录执行 python3 main.py。
cd 'content/posts/AI-深度学习/嵌入式视觉模型进阶/03-MobileNet/code' && python3 main.py
"""实现 MobileNetV1 与 V2 的代表模块,理解扩展、深度卷积和线性投影。"""
import torch
from torch import nn
class V1(nn.Sequential):
def __init__(self, cin, cout):
super().__init__(
nn.Conv2d(cin, cin, 3, padding=1, groups=cin, bias=False),
nn.BatchNorm2d(cin),
nn.ReLU(),
nn.Conv2d(cin, cout, 1, bias=False),
nn.BatchNorm2d(cout),
nn.ReLU(),
)
class InvertedResidual(nn.Module):
def __init__(self, cin, cout, stride=1, expand=6):
super().__init__()
hidden = cin * expand
self.use_skip = stride == 1 and cin == cout
self.layers = nn.Sequential(
nn.Conv2d(cin, hidden, 1, bias=False),
nn.BatchNorm2d(hidden),
nn.ReLU6(),
nn.Conv2d(hidden, hidden, 3, stride, 1, groups=hidden, bias=False),
nn.BatchNorm2d(hidden),
nn.ReLU6(),
nn.Conv2d(hidden, cout, 1, bias=False),
nn.BatchNorm2d(cout),
)
def forward(self, x):
y = self.layers(x)
return x + y if self.use_skip else y
def main():
torch.manual_seed(7)
torch.set_num_threads(2)
x = torch.randn(2, 16, 24, 24)
for net, shape in [
(V1(16, 24), (2, 24, 24, 24)),
(InvertedResidual(16, 16), (2, 16, 24, 24)),
(InvertedResidual(16, 24, 2), (2, 24, 12, 12)),
]:
y = net.eval()(x)
assert tuple(y.shape) == shape
y.square().mean().backward()
print(
type(net).__name__, list(y.shape), sum(p.numel() for p in net.parameters())
)
if __name__ == "__main__":
main()