EXPERIMENT / 配套代码

main.py

← 返回文章
下载代码

在项目根目录执行;下载包解压后,在解压目录执行 python3 main.py。

cd 'content/posts/AI-深度学习/嵌入式视觉模型进阶/05-ShuffleNet/code' && python3 main.py
"""通过通道编号追踪 shuffle 的作用,观察分组之间的信息交换与复制成本。"""

import torch
from torch import nn


def shuffle(x, groups):
    n, c, h, w = x.shape
    if c % groups:
        raise ValueError("channels must be divisible by groups")
    return (
        x.reshape(n, groups, c // groups, h, w)
        .transpose(1, 2)
        .contiguous()
        .reshape(n, c, h, w)
    )


class SplitBlock(nn.Module):
    def __init__(self, c):
        super().__init__()
        if c % 2:
            raise ValueError("even channels required")
        half = c // 2
        self.branch = nn.Sequential(
            nn.Conv2d(half, half, 1),
            nn.ReLU(),
            nn.Conv2d(half, half, 3, padding=1, groups=half),
            nn.Conv2d(half, half, 1),
            nn.ReLU(),
        )

    def forward(self, x):
        a, b = x.chunk(2, dim=1)
        return shuffle(torch.cat([a, self.branch(b)], 1), 2)


def main():
    torch.manual_seed(7)
    torch.set_num_threads(2)
    ids = torch.arange(8).reshape(1, 8, 1, 1)
    assert shuffle(ids, 2).flatten().tolist() == [0, 4, 1, 5, 2, 6, 3, 7]
    print(
        "groups2:",
        shuffle(ids, 2).flatten().tolist(),
        "groups4:",
        shuffle(ids, 4).flatten().tolist(),
    )
    x = torch.randn(1, 8, 16, 16)
    y = SplitBlock(8)(x)
    assert y.shape == x.shape
    print("output", list(y.shape))


if __name__ == "__main__":
    main()