EfficientNetV2代码解读笔记

更新时间:2023-06-09 11:04:32 阅读: 评论:0

EfficientNetV2代码解读笔记EfficientNetV2
与EfficientNet相⽐,V2进⾏了精简。⽅便理解搭建的过程。
1、drop_path⽅法
与之前的相同。
def drop_path(x, drop_prob: float = 0., training: bool = Fal):
if drop_prob == 0. or not training:
山茶油可以炒菜吗return x调查员
keep_prob = 1 - drop_prob
shape = (x.shape[0],) + (1,) * (x.ndim - 1)  # work with diff dim tensors, not just 2D ConvNets
random_tensor = keep_prob + torch.rand(shape, dtype=x.dtype, device=x.device)
random_tensor.floor_()  # binarize
output = x.div(keep_prob) * random_tensor
return output
2、DropPath类
在DropPath类中,正向传递过程,输出直接调⽤drop_path⽅法。
class DropPath(nn.Module):
def __init__(lf, drop_prob=None):
super(DropPath, lf).__init__()
lf.drop_prob = drop_prob
汪能科def forward(lf, x):
return drop_path(x, lf.drop_prob, lf.training)
3、ConvBNAct类
卷积+BN+激活放在⼀起,groups判断是卷积还是DW卷积。
class ConvBNAct(nn.Module):
def __init__(lf,
in_planes: int,
out_planes: int,
kernel_size: int = 3,
stride: int = 1,
groups: int = 1,
norm_layer: Optional[Callable[..., nn.Module]] = None,
activation_layer: Optional[Callable[..., nn.Module]] = None):
super(ConvBNAct, lf).__init__()
padding = (kernel_size - 1) // 2
if norm_layer is None:
norm_layer = nn.BatchNorm2d
if activation_layer is None:
activation_layer = nn.SiLU  # alias Swish  (torch>=1.7)
out_channels=out_planes,
kernel_size=kernel_size,
stride=stride,
padding=padding,
groups=groups,
bias=Fal)
lf.bn = norm_layer(out_planes)
lf.act = activation_layer()
def forward(lf, x):
result = lf.conv(x)
result = lf.bn(result)
result = lf.act(result)
return result
4、SE类
SE模块:⾸先,全局平均池化,将每⼀个channel求⼀个均值;再⼀次通过两个全连接层,得到输出。
注意:第⼀个全连接层节点个数等于输⼊MBConv矩阵channel的1/4,第⼆个全连接层节点个数等于输⼊SE模块的channel。class SqueezeExcite(nn.Module):
def __init__(lf,
input_c: int,  # block input channel
expand_c: int,  # block expand channel
_ratio: float = 0.25):
super(SqueezeExcite, lf).__init__()
squeeze_c = int(input_c * _ratio)
lf.act1 = nn.SiLU()  # alias Swish
lf.act2 = nn.Sigmoid()
def forward(lf, x: Tensor) -> Tensor:
scale = x.mean((2, 3), keepdim=True)
scale = lf.conv_reduce(scale)
scale = lf.act1(scale)
scale = lf.conv_expand(scale)
scale = lf.act2(scale)
return scale * x
5、MBConv类
⾸先,进⾏⼀个判断,如果stride不在1,2中,报错。然后,判断是否有捷径分⽀。各种参数的设置,类似于EfficientNet。搭建各个模块,1*1卷积。DW卷积,SE模块,最后⼀个1*1⽆激活函数的卷积层,最后Dropout。
书柜英语class MBConv(nn.Module):
def __init__(lf,
kernel_size: int,
input_c: int,
out_c: int,
expand_ratio: int,
stride: int,
_ratio: float,
drop_rate: float,
norm_layer: Callable[..., nn.Module]):
super(MBConv, lf).__init__()
if stride not in [1, 2]:
rai ValueError("illegal stride value.")
lf.has_shortcut = (stride == 1 and input_c == out_c)
activation_layer = nn.SiLU  # alias Swish
expanded_c = input_c * expand_ratio
# 在EfficientNetV2中,MBConv中不存在expansion=1的情况所以conv_pw肯定存在
asrt expand_ratio != 1
# Point-wi expansion
expanded_c,
kernel_size=1,
norm_layer=norm_layer,
activation_layer=activation_layer)
# Depth-wi convolution
lf.dwconv = ConvBNAct(expanded_c,
expanded_c,
kernel_size=kernel_size,
stride=stride,
groups=expanded_c,
norm_layer=norm_layer,
activation_layer=activation_layer)
lf. = SqueezeExcite(input_c, expanded_c, _ratio) if _ratio > 0 el nn.Identity()
# Point-wi linear projection
lf.project_conv = ConvBNAct(expanded_c,
out_planes=out_c,
kernel_size=1,
norm_layer=norm_layer,
activation_layer=nn.Identity)  # 注意这⾥没有激活函数,所有传⼊Identity
lf.out_channels = out_c
# 只有在使⽤shortcut连接时才使⽤dropout层
lf.drop_rate = drop_rate
if lf.has_shortcut and drop_rate > 0:
lf.dropout = DropPath(drop_rate)
def forward(lf, x: Tensor) -> Tensor:
result = lf.expand_conv(x)
result = lf.dwconv(result)
result = lf.(result)
result = lf.project_conv(result)
if lf.has_shortcut:
if lf.drop_rate > 0:
result = lf.dropout(result)
result += x
周树人简介return result
6、FudMBConv模块
分两种情况expansion=1和不等1。
等于1,只有3*3卷积+BN+SiLU+Dropout。不等于1的话,3*3的卷积+BN+SiLU,1*1的卷积+BN,Dropout。在代码中,先判断
class FudMBConv(nn.Module):
def __init__(lf,
kernel_size: int,
input_c: int,
out_c: int,
expand_ratio: int,
stride: int,
_ratio: float,
drop_rate: float,
norm_layer: Callable[..., nn.Module]):
super(FudMBConv, lf).__init__()
asrt stride in [1, 2]
asrt _ratio == 0
lf.has_shortcut = stride == 1 and input_c == out_c
lf.drop_rate = drop_rate
lf.has_expansion = expand_ratio != 1
activation_layer = nn.SiLU  # alias Swish
expanded_c = input_c * expand_ratio
# 只有当expand ratio不等于1时才有expand conv
if lf.has_expansion:
我的老师韩国
# Expansion convolution
expanded_c,
kernel_size=kernel_size,
stride=stride,
norm_layer=norm_layer,
activation_layer=activation_layer)
lf.project_conv = ConvBNAct(expanded_c,
out_c,
最美诗句kernel_size=1,
norm_layer=norm_layer,
activation_layer=nn.Identity)  # 注意没有激活函数        el:
# 当只有project_conv时的情况
lf.project_conv = ConvBNAct(input_c,
out_c,
kernel_size=kernel_size,
stride=stride,
norm_layer=norm_layer,
activation_layer=activation_layer)  # 注意有激活函数        lf.out_channels = out_c
# 只有在使⽤shortcut连接时才使⽤dropout层
lf.drop_rate = drop_rate
if lf.has_shortcut and drop_rate > 0:
lf.dropout = DropPath(drop_rate)
def forward(lf, x: Tensor) -> Tensor:
if lf.has_expansion:
result = lf.expand_conv(x)
result = lf.project_conv(result)
el:
result = lf.project_conv(x)
if lf.has_shortcut:
if lf.drop_rate > 0:
result = lf.dropout(result)
result += x
return result
7、EfficientNetV2
class EfficientNetV2(nn.Module):
def __init__(lf,
model_cnf: list,
num_class: int = 1000,
num_features: int = 1280,
dropout_rate: float = 0.2,
drop_connect_rate: float = 0.2):
super(EfficientNetV2, lf).__init__()
for cnf in model_cnf:
asrt len(cnf) == 8
norm_layer = partial(nn.BatchNorm2d, eps=1e-3, momentum=0.1)
stem_filter_num = model_cnf[0][4]
lf.stem = ConvBNAct(3,
stem_filter_num,
kernel_size=3,
stride=2,
norm_layer=norm_layer)  # 激活函数默认是SiLU
total_blocks = sum([i[0] for i in model_cnf])
block_id = 0
blocks = []
for cnf in model_cnf:
repeats = cnf[0]
op = FudMBConv if cnf[-2] == 0 el MBConv
for i in range(repeats):
blocks.append(op(kernel_size=cnf[1],
input_c=cnf[4] if i == 0 el cnf[5],
out_c=cnf[5],
expand_ratio=cnf[3],
stride=cnf[2] if i == 0 el 1,
_ratio=cnf[-1],
drop_rate=drop_connect_rate * block_id / total_blocks,
norm_layer=norm_layer))
block_id += 1
lf.blocks = nn.Sequential(*blocks)
head_input_c = model_cnf[-1][-3]
head = OrderedDict()
head.update({"project_conv": ConvBNAct(head_input_c,
num_features,
kernel_size=1,
norm_layer=norm_layer)})  # 激活函数默认是SiLU        head.update({"avgpool": nn.AdaptiveAvgPool2d(1)})
head.update({"flatten": nn.Flatten()})
if dropout_rate > 0:
head.update({"dropout": nn.Dropout(p=dropout_rate, inplace=True)})
head.update({"classifier": nn.Linear(num_features, num_class)})
lf.head = nn.Sequential(head)
# initial weights
for m dules():
人参养灵芝
if isinstance(m, nn.Conv2d):
nn.init.kaiming_normal_(m.weight, mode="fan_out")
if m.bias is not None:
s_(m.bias)
elif isinstance(m, nn.BatchNorm2d):
s_(m.weight)
s_(m.bias)
elif isinstance(m, nn.Linear):
al_(m.weight, 0, 0.01)
s_(m.bias)
def forward(lf, x: Tensor) -> Tensor:
x = lf.stem(x)
x = lf.blocks(x)
x = lf.head(x)
return x

本文发布于:2023-06-09 11:04:32,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/89/1030521.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:判断   等于   连接   卷积   函数   搭建
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图