文章目录

  • 1. 概述
    • 1.1 论文下载
    • 1.2 论文解读
  • 2.性能对比
  • 3. 网络backbone
    • 3.1 MBcov模块
    • 3.2 SE模块
  • 4. 代码实现

1. 概述

1.1 论文下载

EfficientNet: Rethinking Model Scaling for Convolutional Neural Networks

  1. 原址下载
  2. 百度云下载,提取码

1.2 论文解读


参考:https://blog.csdn.net/qq_37541097/article/details/114434046

2.性能对比

3. 网络backbone

Model input_size width_coefficient depth_coefficient drop_connect_rate dropout_rate
EfficientNetB0 224x224 1.0 1.0 0.2 0.2
EfficientNetB1 240x240 1.0 1.1 0.2 0.2
EfficientNetB2 260x260 1.1 1.2 0.2 0.3
EfficientNetB3 300x300 1.2 1.4 0.2 0.3
EfficientNetB4 380x380 1.4 1.8 0.2 0.4
EfficientNetB5 456x456 1.6 2.2 0.2 0.4
EfficientNetB6 528x528 1.8 2.6 0.2 0.5
EfficientNetB7 600x600 2.0 3.1 0.2 0.5

3.1 MBcov模块

3.2 SE模块

4. 代码实现

import math
import copy
from functools import partial
from collections import OrderedDict
from typing import Optional, Callableimport torch
import torch.nn as nn
from torch import Tensor
from torch.nn import functional as F"""
该方法就是将传入的channel的个数调整到8的整数倍,使得对硬件友好
"""
def _make_divisible(ch, divisor=8, min_ch=None):"""This function is taken from the original tf repo.It ensures that all layers have a channel number that is divisible by 8It can be seen here:https://github.com/tensorflow/models/blob/master/research/slim/nets/mobilenet/mobilenet.py"""if min_ch is None:min_ch = divisornew_ch = max(min_ch, int(ch + divisor / 2) // divisor * divisor)# Make sure that round down does not go down by more than 10%.if new_ch < 0.9 * ch:new_ch += divisorreturn new_ch""""""
def drop_path(x, drop_prob: float = 0., training: bool = False):"""Drop paths (Stochastic Depth) per sample (when applied in main path of residual blocks)."Deep Networks with Stochastic Depth", https://arxiv.org/pdf/1603.09382.pdfThis function is taken from the rwightman.It can be seen here:https://github.com/rwightman/pytorch-image-models/blob/master/timm/models/layers/drop.py#L140"""if drop_prob == 0. or not training:return xkeep_prob = 1 - drop_probshape = (x.shape[0],) + (1,) * (x.ndim - 1)  # work with diff dim tensors, not just 2D ConvNetsrandom_tensor = keep_prob + torch.rand(shape, dtype=x.dtype, device=x.device)random_tensor.floor_()  # binarizeoutput = x.div(keep_prob) * random_tensorreturn output""""""
class DropPath(nn.Module):"""Drop paths (Stochastic Depth) per sample  (when applied in main path of residual blocks)."Deep Networks with Stochastic Depth", https://arxiv.org/pdf/1603.09382.pdf"""def __init__(self, drop_prob=None):super(DropPath, self).__init__()self.drop_prob = drop_probdef forward(self, x):return drop_path(x, self.drop_prob, self.training)"""
定义BN和激活函数
"""
class ConvBNActivation(nn.Sequential):def __init__(self,in_planes: int,out_planes: int,kernel_size: int = 3,stride: int = 1,groups: int = 1,norm_layer: Optional[Callable[..., nn.Module]] = None, #BN结构,默认为Noneactivation_layer: Optional[Callable[..., nn.Module]] = None): #ac结构,默认为Nonepadding = (kernel_size - 1) // 2if norm_layer is None:"""不指定norm的话,默认BN结构"""norm_layer = nn.BatchNorm2dif activation_layer is None:"""如果不指定激活函数,则默认SiLU激活函数"""activation_layer = nn.SiLU  # alias Swish  (torch>=1.7)激活函数使用的是SiLU,在版本1.70以上才有,建议1.7.1版本#定义层结构[in_channels,out_channels,kernel_size,stride,padding,groups,bias=False],-->BN-->acsuper(ConvBNActivation, self).__init__(nn.Conv2d(in_channels=in_planes,out_channels=out_planes,kernel_size=kernel_size,stride=stride,padding=padding,groups=groups,bias=False),norm_layer(out_planes),activation_layer())"""
定义SE模块
"""
class SqueezeExcitation(nn.Module):def __init__(self,input_c: int,   # block input channelexpand_c: int,  # block expand channelsqueeze_factor: int = 4):super(SqueezeExcitation, self).__init__()squeeze_c = input_c // squeeze_factorself.fc1 = nn.Conv2d(expand_c, squeeze_c, 1)self.ac1 = nn.SiLU()  # alias Swishself.fc2 = nn.Conv2d(squeeze_c, expand_c, 1)self.ac2 = nn.Sigmoid()def forward(self, x: Tensor) -> Tensor:scale = F.adaptive_avg_pool2d(x, output_size=(1, 1))scale = self.fc1(scale)scale = self.ac1(scale)scale = self.fc2(scale)scale = self.ac2(scale)return scale * x""""""
class InvertedResidualConfig:# kernel_size, in_channel, out_channel, exp_ratio, strides, use_SE, drop_connect_ratedef __init__(self,kernel: int,          # 3 or 5input_c: int,out_c: int,expanded_ratio: int,  # 1 or 6stride: int,          # 1 or 2use_se: bool,         # Truedrop_rate: float,index: str,           # 1a, 2a, 2b, ...width_coefficient: float):self.input_c = self.adjust_channels(input_c, width_coefficient)self.kernel = kernelself.expanded_c = self.input_c * expanded_ratioself.out_c = self.adjust_channels(out_c, width_coefficient)self.use_se = use_seself.stride = strideself.drop_rate = drop_rateself.index = index@staticmethoddef adjust_channels(channels: int, width_coefficient: float):return _make_divisible(channels * width_coefficient, 8)""""""
class InvertedResidual(nn.Module):def __init__(self,cnf: InvertedResidualConfig,norm_layer: Callable[..., nn.Module]):super(InvertedResidual, self).__init__()if cnf.stride not in [1, 2]:raise ValueError("illegal stride value.")self.use_res_connect = (cnf.stride == 1 and cnf.input_c == cnf.out_c)layers = OrderedDict()activation_layer = nn.SiLU  # alias Swish# expandif cnf.expanded_c != cnf.input_c:layers.update({"expand_conv": ConvBNActivation(cnf.input_c,cnf.expanded_c,kernel_size=1,norm_layer=norm_layer,activation_layer=activation_layer)})# depthwiselayers.update({"dwconv": ConvBNActivation(cnf.expanded_c,cnf.expanded_c,kernel_size=cnf.kernel,stride=cnf.stride,groups=cnf.expanded_c,norm_layer=norm_layer,activation_layer=activation_layer)})if cnf.use_se:layers.update({"se": SqueezeExcitation(cnf.input_c,cnf.expanded_c)})# projectlayers.update({"project_conv": ConvBNActivation(cnf.expanded_c,cnf.out_c,kernel_size=1,norm_layer=norm_layer,activation_layer=nn.Identity)})self.block = nn.Sequential(layers)self.out_channels = cnf.out_cself.is_strided = cnf.stride > 1# 只有在使用shortcut连接时才使用dropout层if self.use_res_connect and cnf.drop_rate > 0:self.dropout = DropPath(cnf.drop_rate)else:self.dropout = nn.Identity()def forward(self, x: Tensor) -> Tensor:result = self.block(x)result = self.dropout(result)if self.use_res_connect:result += xreturn result""""""
class EfficientNet(nn.Module):def __init__(self,width_coefficient: float,depth_coefficient: float,num_classes: int = 1000,dropout_rate: float = 0.2,drop_connect_rate: float = 0.2,block: Optional[Callable[..., nn.Module]] = None,norm_layer: Optional[Callable[..., nn.Module]] = None):super(EfficientNet, self).__init__()# kernel_size, in_channel, out_channel, exp_ratio, strides, use_SE, drop_connect_rate, repeatsdefault_cnf = [[3, 32, 16, 1, 1, True, drop_connect_rate, 1],[3, 16, 24, 6, 2, True, drop_connect_rate, 2],[5, 24, 40, 6, 2, True, drop_connect_rate, 2],[3, 40, 80, 6, 2, True, drop_connect_rate, 3],[5, 80, 112, 6, 1, True, drop_connect_rate, 3],[5, 112, 192, 6, 2, True, drop_connect_rate, 4],[3, 192, 320, 6, 1, True, drop_connect_rate, 1]]def round_repeats(repeats):"""Round number of repeats based on depth multiplier."""return int(math.ceil(depth_coefficient * repeats))if block is None:block = InvertedResidualif norm_layer is None:norm_layer = partial(nn.BatchNorm2d, eps=1e-3, momentum=0.1)adjust_channels = partial(InvertedResidualConfig.adjust_channels,width_coefficient=width_coefficient)# build inverted_residual_settingbneck_conf = partial(InvertedResidualConfig,width_coefficient=width_coefficient)b = 0num_blocks = float(sum(round_repeats(i[-1]) for i in default_cnf))inverted_residual_setting = []for stage, args in enumerate(default_cnf):cnf = copy.copy(args)for i in range(round_repeats(cnf.pop(-1))):if i > 0:# strides equal 1 except first cnfcnf[-3] = 1  # stridescnf[1] = cnf[2]  # input_channel equal output_channelcnf[-1] = args[-2] * b / num_blocks  # update dropout ratioindex = str(stage + 1) + chr(i + 97)  # 1a, 2a, 2b, ...inverted_residual_setting.append(bneck_conf(*cnf, index))b += 1# create layerslayers = OrderedDict()# first convlayers.update({"stem_conv": ConvBNActivation(in_planes=3,out_planes=adjust_channels(32),kernel_size=3,stride=2,norm_layer=norm_layer)})# building inverted residual blocksfor cnf in inverted_residual_setting:layers.update({cnf.index: block(cnf, norm_layer)})# build toplast_conv_input_c = inverted_residual_setting[-1].out_clast_conv_output_c = adjust_channels(1280)layers.update({"top": ConvBNActivation(in_planes=last_conv_input_c,out_planes=last_conv_output_c,kernel_size=1,norm_layer=norm_layer)})self.features = nn.Sequential(layers)self.avgpool = nn.AdaptiveAvgPool2d(1)classifier = []if dropout_rate > 0:classifier.append(nn.Dropout(p=dropout_rate, inplace=True))classifier.append(nn.Linear(last_conv_output_c, num_classes))self.classifier = nn.Sequential(*classifier)# initial weightsfor m in self.modules():if isinstance(m, nn.Conv2d):nn.init.kaiming_normal_(m.weight, mode="fan_out")if m.bias is not None:nn.init.zeros_(m.bias)elif isinstance(m, nn.BatchNorm2d):nn.init.ones_(m.weight)nn.init.zeros_(m.bias)elif isinstance(m, nn.Linear):nn.init.normal_(m.weight, 0, 0.01)nn.init.zeros_(m.bias)def _forward_impl(self, x: Tensor) -> Tensor:x = self.features(x)x = self.avgpool(x)x = torch.flatten(x, 1)x = self.classifier(x)return xdef forward(self, x: Tensor) -> Tensor:return self._forward_impl(x)""""""
def efficientnet_b0(num_classes=1000):# input image size 224x224return EfficientNet(width_coefficient=1.0,depth_coefficient=1.0,dropout_rate=0.2,num_classes=num_classes)""""""
def efficientnet_b1(num_classes=1000):# input image size 240x240return EfficientNet(width_coefficient=1.0,depth_coefficient=1.1,dropout_rate=0.2,num_classes=num_classes)
""""""
def efficientnet_b2(num_classes=1000):# input image size 260x260return EfficientNet(width_coefficient=1.1,depth_coefficient=1.2,dropout_rate=0.3,num_classes=num_classes)""""""
def efficientnet_b3(num_classes=1000):# input image size 300x300return EfficientNet(width_coefficient=1.2,depth_coefficient=1.4,dropout_rate=0.3,num_classes=num_classes)""""""
def efficientnet_b4(num_classes=1000):# input image size 380x380return EfficientNet(width_coefficient=1.4,depth_coefficient=1.8,dropout_rate=0.4,num_classes=num_classes)""""""
def efficientnet_b5(num_classes=1000):# input image size 456x456return EfficientNet(width_coefficient=1.6,depth_coefficient=2.2,dropout_rate=0.4,num_classes=num_classes)""""""
def efficientnet_b6(num_classes=1000):# input image size 528x528return EfficientNet(width_coefficient=1.8,depth_coefficient=2.6,dropout_rate=0.5,num_classes=num_classes)""""""
def efficientnet_b7(num_classes=1000):# input image size 600x600return EfficientNet(width_coefficient=2.0,depth_coefficient=3.1,dropout_rate=0.5,num_classes=num_classes)

Pytorch实现EfficientNet相关推荐

  1. 神经网络学习小记录50——Pytorch 利用efficientnet系列模型搭建yolov3目标检测平台

    神经网络学习小记录50--Pytorch 利用efficientnet系列模型搭建yolov3目标检测平台 学习前言 什么是EfficientNet模型 源码下载 EfficientNet模型的实现思 ...

  2. 【项目实战课】基于Pytorch的EfficientNet血红细胞分类竞赛实战

    欢迎大家来到我们的项目实战课,本期内容是<基于Pytorch的EfficientNet血红细胞分类竞赛实战>.所谓项目课,就是以简单的原理回顾+详细的项目实战的模式,针对具体的某一个主题, ...

  3. 【小白学PyTorch】13.EfficientNet详解及PyTorch实现

    <<小白学PyTorch>> 小白学PyTorch | 12 SENet详解及PyTorch实现 小白学PyTorch | 11 MobileNet详解及PyTorch实现 小 ...

  4. 【小白学PyTorch】扩展之Tensorflow2.0 | 21 Keras的API详解(下)池化、Normalization

    <<小白学PyTorch>> 扩展之Tensorflow2.0 | 21 Keras的API详解(上)卷积.激活.初始化.正则 扩展之Tensorflow2.0 | 20 TF ...

  5. 【小白学PyTorch】扩展之Tensorflow2.0 | 21 Keras的API详解(上)卷积、激活、初始化、正则...

    [机器学习炼丹术]的学习笔记分享 <<小白学PyTorch>> 扩展之Tensorflow2.0 | 20 TF2的eager模式与求导 扩展之Tensorflow2.0 | ...

  6. 【小白学PyTorch】扩展之Tensorflow2.0 | 20 TF2的eager模式与求导

    [机器学习炼丹术]的学习笔记分享 <<小白学PyTorch>> 扩展之Tensorflow2.0 | 19 TF2模型的存储与载入 扩展之Tensorflow2.0 | 18 ...

  7. 【小白学PyTorch】18.TF2构建自定义模型

    [机器学习炼丹术]的学习笔记分享 <<小白学PyTorch>> 扩展之Tensorflow2.0 | 17 TFrec文件的创建与读取 扩展之Tensorflow2.0 | 1 ...

  8. 【小白学PyTorch】17.TFrec文件的创建与读取

    [机器学习炼丹术]的学习笔记分享 <<小白学PyTorch>> 小白学PyTorch | 16 TF2读取图片的方法 小白学PyTorch | 15 TF2实现一个简单的服装分 ...

  9. 【小白学PyTorch】16.TF2读取图片的方法

    <<小白学PyTorch>> 扩展之tensorflow2.0 | 15 TF2实现一个简单的服装分类任务 小白学PyTorch | 14 tensorboardX可视化教程 ...

  10. 【小白学PyTorch】15.TF2实现一个简单的服装分类任务

    <<小白学PyTorch>> 小白学PyTorch | 14 tensorboardX可视化教程 小白学PyTorch | 13 EfficientNet详解及PyTorch实 ...

最新文章

  1. ORA-01855: AM/A.M. or PM/P.M. required错误解决
  2. bat入门-----依据ping状态判断ip【第一天】
  3. 连环卡通漫画《转学第一天》
  4. 【开源项目----Android OPenGLES渲染YUV视频文件】
  5. 微型计算机指令系统例题,微机原理复习题(指令系统)
  6. 问题 D: 自动拨出电话的程序
  7. 大数据Python学习大纲
  8. mysql主从简明配置
  9. HDU 6185 2017广西邀请赛:Covering(矩阵快速幂)
  10. 【WP开发】JSON数据的读与写
  11. Go语言入门之指针的使用
  12. c语言word类型的题库,可下载c语言上机题库word版
  13. 基于Easyui框架的datagrid绑定数据,新增,修改,删除方法(一)
  14. 如何从PDF文件中提取几页为一个PDF文件?
  15. 使用F021_API_F2837xD_FPU32.lib 库函数遇到的问题 warning #10068-D: no matching section
  16. 基于Python+网络爬虫的兼职招聘就业信息数据可视化分析
  17. 官方:2056名广西考生未按规定上传“软考报考材料”,逾期将取消资格
  18. linux程序卸载失败怎么办,在Deepin下卸载LibreOffice等软件的方法,附卸载失败的原因...
  19. 操作系统怎样控制硬件
  20. Cir 和 IBIS模型的使用

热门文章

  1. 系统内存地址PEEK值大全
  2. 小米和美的互投,大明湖畔的董明珠怎么办?
  3. light oj 1224
  4. Hi3861网络通信——UDP收发
  5. html5 audio duration,记一次vue中获取audio媒体总时长duration遇到的问题
  6. Oracle 文字排序,按照拼音,姓氏笔画等
  7. javascript 获取汉字笔画拼音,使用笔画排序
  8. 水滴模式能否解惑10亿人口下沉市场?
  9. pythonarray去除inf_Python中的inf与nan
  10. 天下武功唯快不破 实验吧(小结)