轻量化模块整理,即插即用

轻量化模块整理,即插即用(持续更新)

整理一些轻量化的结构,作为知识储备,可以用到后续的项目和研究中

Mobilenetv3 深度可分离卷积

MobileNetV3 是一个轻量级的深度学习模型,专为移动和边缘设备上的高效推理而设计。MobileNetV3 是在 MobileNetV1 和 MobileNetV2 的基础上进行了进一步的优化,主要包括了网络架构的搜索和修改、硬件感知网络优化、以及使用了轻量级的注意力模块 SE(Squeeze-and-Excitation)和 h-swish 激活函数等

import torch  
import torch.nn as nn  
import torch.nn.functional as F  
  
class h_swish(nn.Module):  
    def forward(self, x):  
        return x * torch.sigmoid(x + 3) / 6  
  
class SEBlock(nn.Module):  
    def __init__(self, in_channels, reduction=4):  
        super(SEBlock, self).__init__()  
        self.avg_pool = nn.AdaptiveAvgPool2d(1)  
        self.fc = nn.Sequential(  
            nn.Linear(in_channels, in_channels // reduction, bias=False),  
            nn.ReLU(inplace=True),  
            nn.Linear(in_channels // reduction, in_channels, bias=False),  
            nn.Sigmoid()  
        )  
  
    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.expand_as(x)  
  
class InvertedResidual(nn.Module):  
    def __init__(self, inp, oup, stride, expand_ratio, use_se=False):  
        super(InvertedResidual, self).__init__()  
        assert stride in [1, 2]  
  
        hidden_dim = int(round(inp * expand_ratio))  
        self.use_res_connect = stride == 1 and inp == oup  
  
        layers = []  
        if expand_ratio != 1:  
            # pw  
            layers.append(nn.Conv2d(inp, hidden_dim, 1, 1, 0, bias=False))  
            layers.append(nn.BatchNorm2d(hidden_dim))  
            layers.append(h_swish())  
  
        # dw  
        layers.append(nn.Conv2d(hidden_dim, hidden_dim, 3, stride, 1, groups=hidden_dim, bias=False))  
        layers.append(nn.BatchNorm2d(hidden_dim))  
        layers.append(h_swish())  
  
        if use_se:  
            layers.append(SEBlock(hidden_dim))  
  
        # pw-linear  
        layers.append(nn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False))  
        layers.append(nn.BatchNorm2d(oup))  
  
        self.conv = nn.Sequential(*layers)  
  
    def forward(self, x):  
        if self.use_res_connect:  
            return x + self.conv(x)  
        else:  
            return self.conv(x)  
  
# 使用示例  
# 输入通道数、输出通道数、步长、扩展比例、是否使用 SE 模块  
block = InvertedResidual(inp=32, oup=16, stride=2, expand_ratio=6, use_se=True)  
input_tensor = torch.randn(1, 32, 224, 224)  
output_tensor = block(input_tensor)  
print(output_tensor.shape)  # 输出张量的形状

上述代码定义了一个简化的 MobileNetV3 基础模块,包括一个 InvertedResidual(倒置残差)块和一个可选的 SE(Squeeze-and-Excitation)块。InvertedResidual 块是 MobileNetV3 的核心组件,它首先通过 1x1 卷积进行通道扩展,然后通过 3x3 深度可分离卷积进行空间卷积,最后通过 1x1 卷积恢复到目标通道数。SE 块则用于对特征进行自适应的重新加权。h_swish 是一种轻量级的激活函数,用于替换标准的 ReLU 或 swish 激活函数。

在pytorch中简单实现dw卷积

在PyTorch中实现深度可分离卷积(Depthwise Separable Convolution)可以通过两个步骤来完成:首先执行深度卷积(Depthwise Convolution),然后执行逐点卷积(Pointwise Convolution)。

深度卷积对输入的每个通道单独应用一个卷积核,因此输出的通道数与输入的通道数相同。而逐点卷积(也被称为1x1卷积)是对深度卷积的输出进行线性组合,以改变通道数。

以下是一个简单的PyTorch实现示例:

import torch  
import torch.nn as nn  
import torch.nn.functional as F  
  
class DepthwiseSeparableConv(nn.Module):  
    def __init__(self, in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, bias=False):  
        super(DepthwiseSeparableConv, self).__init__()  
        self.depthwise = nn.Conv2d(in_channels, in_channels, kernel_size, stride, padding, dilation, groups=in_channels, bias=bias)  
        self.pointwise = nn.Conv2d(in_channels, out_channels, 1, 1, 0, bias=bias)  
  
    def forward(self, x):  
        out = self.depthwise(x)  
        out = self.pointwise(out)  
        return out  
  
# 使用示例  
# 输入通道数、输出通道数、卷积核大小  
in_channels = 3  
out_channels = 16  
kernel_size = 3  
  
# 实例化深度可分离卷积层  
depthwise_separable_conv = DepthwiseSeparableConv(in_channels, out_channels, kernel_size)  
  
# 创建一个随机的输入张量  
input_tensor = torch.randn(1, in_channels, 32, 32)  
  
# 前向传播  
output_tensor = depthwise_separable_conv(input_tensor)  
  
# 打印输出张量的形状  
print(output_tensor.shape)  # 应该是 [1, out_channels, 32, 32]

在这个例子中,DepthwiseSeparableConv 类包含两个卷积层:depthwise(深度卷积层)和 pointwise(逐点卷积层)。在 forward 方法中,输入 x 首先通过深度卷积层,然后通过逐点卷积层。

注意,nn.Conv2d 在定义深度卷积层时使用了 groups=in_channels 参数,这表示每个输入通道都有一个独立的卷积核。这确保了深度卷积只在其自己的输入通道上进行操作。

然后,逐点卷积层(即1x1卷积)将深度卷积的输出作为输入,并输出具有所需通道数的特征图。

这种实现方法相比标准卷积更加高效,因为它减少了参数数量和计算量,特别适合在移动和嵌入式设备上使用。

在dw卷积中,增加膨胀了

在深度卷积中再实现扩张卷积(也称为空洞卷积或 Atrous Convolution)需要调整卷积层的参数来包含扩张率(dilation rate)。扩张卷积允许卷积核在输入特征图上以指定的间隔进行采样,从而在不增加参数数量的情况下增大卷积核的感受野。

在 PyTorch 中,你可以在 nn.Conv2d 中通过 dilation 参数来指定扩张率。因此,要在 DWConv 类中实现扩张卷积,你需要在初始化 nn.Conv2d 时传入一个 dilation 参数。

下面是一个修改后的 DWConv 类,参考了YOLOv5中的DWconv,另外,实现了深度卷积并带有扩张率:

import torch  
import torch.nn as nn  
import torch.nn.functional as F  
  
class Conv(nn.Module):  
    # Standard convolution  
    def __init__(self, c1, c2, k, s=1, p=None, g=1, act=True, dilation=1):  
        super(Conv, self).__init__()  
        self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p), groups=g, bias=False, dilation=dilation)  
        self.bn = nn.BatchNorm2d(c2)  
        self.act = nn.Hardswish() if act else nn.Identity()  
  
    def forward(self, x):  
        return self.act(self.bn(self.conv(x)))  
  
def autopad(k, p=None):  
    # Compute padding  
    if p is None:  
        p = k // 2  
    return p  
  
class DWConv(nn.Module):  
    # Depthwise Separable Convolution with dilation and pointwise convolution  
    def __init__(self, c1, c2, k=1, s=1, act=True, dilation=1):  
        super(DWConv, self).__init__()  
          
        # Depthwise Convolution  
        self.depthwise = Conv(c1, c1, k, s, act=False, g=c1, dilation=dilation)  
          
        # Pointwise Convolution (1x1 Convolution)  
        self.pointwise = Conv(c1, c2, 1)  
          
        # Activation function for the final output  
        self.act = nn.Hardswish() if act else nn.Identity()  
          
    def forward(self, x):  
        # Apply depthwise convolution  
        x = self.depthwise(x)  
        # Apply pointwise convolution  
        x = self.pointwise(x)  
        # Apply activation function  
        return self.act(x)  
  
# Example usage:  
# Create a depthwise separable convolution layer with dilation and pointwise convolution  
dw_separable_conv = DWConv(c1=64, c2=128, k=3, s=1, act=True, dilation=2)  
  
# Create an input tensor  
input_tensor = torch.randn(1, 64, 32, 32)  
  
# Forward pass through the layer  
output_tensor = dw_separable_conv(input_tensor)

在这个例子中,dw_conv_layer 是一个深度卷积层,它使用 3x3 的卷积核,步长为 1,并且有一个扩张率为 2,这意味着卷积核在输入特征图上的采样间隔为 2,从而增大了感受野。同时,由于 groups=c1,它仍然是一个深度卷积层,每个输入通道有一个独立的卷积核。

与普通卷积的对比

直接上代码

import torch  
import torch.nn as nn  
import torch.nn.functional as F  
  
class Conv(nn.Module):  
    # Standard convolution  
    def __init__(self, c1, c2, k, s=1, p=None, g=1, act=True, dilation=1):  
        super(Conv, self).__init__()  
        self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p), groups=g, bias=False, dilation=dilation)  
        self.bn = nn.BatchNorm2d(c2)  
        self.act = nn.Hardswish() if act else nn.Identity()  
  
    def forward(self, x):  
        return self.act(self.bn(self.conv(x)))  
  
def autopad(k, p=None):  
    # Compute padding  
    if p is None:  
        p = k // 2  
    return p  
  
class DWConv(nn.Module):  
    # Depthwise Separable Convolution with dilation and pointwise convolution  
    def __init__(self, c1, c2, k=1, s=1, act=True, dilation=1):  
        super(DWConv, self).__init__()  
          
        # Depthwise Convolution  
        self.depthwise = Conv(c1, c1, k, s, act=False, g=c1, dilation=dilation)  
          
        # Pointwise Convolution (1x1 Convolution)  
        self.pointwise = Conv(c1, c2, 1)  
          
        # Activation function for the final output  
        self.act = nn.Hardswish() if act else nn.Identity()  
          
    def forward(self, x):  
        # Apply depthwise convolution  
        x = self.depthwise(x)  
        # Apply pointwise convolution  
        x = self.pointwise(x)  
        # Apply activation function  
        return self.act(x)  
  
# Example usage:  
# Create a depthwise separable convolution layer with dilation and pointwise convolution  
dw_separable_conv = DWConv(c1=64, c2=128, k=3, s=1, act=True, dilation=2)  

normal_conv = Conv(c1=64, c2=128, k=3, s=1, act=True, dilation=2)

# Create an input tensor  
input_tensor = torch.randn(1, 64, 32, 32)  
print(input_tensor.shape)

# Forward pass through the layer  
output_tensor = dw_separable_conv(input_tensor)
print(output_tensor.shape)

print("Normal Convolution")
output_tensor = normal_conv(input_tensor)
print(output_tensor.shape)

# 计算参数量和计算量
from ptflops import get_model_complexity_info

flops,params = get_model_complexity_info(normal_conv,(64,640,640),as_strings=True,print_per_layer_stat=True)

print(" |flops: %s |params: %s" % (flops, params))
from fvcore.nn import FlopCountAnalysis
input_ = torch.randn((1, 64, 256, 256))
flops = FlopCountAnalysis(normal_conv, input_)
print("flops: ", flops.total() / 1e9)

print("DW Convolution")
# 计算参数量和计算量
from ptflops import get_model_complexity_info

flops,params = get_model_complexity_info(dw_separable_conv,(64,640,640),as_strings=True,print_per_layer_stat=True)

print(" |flops: %s |params: %s" % (flops, params))
from fvcore.nn import FlopCountAnalysis
input_ = torch.randn((1, 64, 256, 256))
flops = FlopCountAnalysis(dw_separable_conv, input_)
print("flops: ", flops.total() / 1e9)

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/555254.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

conda配置多版本python

安装conda 以下任选下载 Anaconda Miniconda 配置conda环境变量 比如windows,在配置我的电脑中的环境变量,在系统变量的Path中新增下面内容 需要根据实际目录进行更改 D:\soft\miniconda3 D:\soft\miniconda3\Scripts D:\soft\miniconda3\Library\bi…

windows与linux双系统下,为linux系统/boot独立分区扩容

问题 安装ubuntu系统时,采用手动分区: 1. /boot :一般分配1G,电脑空间大可以分配4G 2. / :分配150-200G,类似windows C盘,存放系统环境:如ROS,python等 3. swap :…

PE文件(一)PE结构概述

PE结构简述 Windows操作系统是只能运行以内存4D 5A开头,翻译是MZ的可执行文件,也叫做PE结构文件,是以exe,.sys,.dll等等作为后缀的文件。而不同的操作系统能运行的可执行文件都是各自特有的,比如Linux可运…

图与图搜索算法

图搜索算法是一个非常重要的概念,它是计算机科学中图论和算法设计的基础部分。在开始讨论图搜索算法之前,我们需要先理解什么是图以及图的基本结构。 什么是图? 图(Graph)是一种非线性数据结构,它由一组点…

算法训练营第25天回溯(分割)

回溯算法(分割) 131.分割回文串 力扣题目链接(opens new window) 题目 给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串。 返回 s 所有可能的分割方案。 示例: 输入: “aab” 输出: [ [“aa”,“b”], [“a”,“…

3D模型查看器开发实战【WebGL】

本文介绍如何从头开发一个包含3D 模型查看器的页面 - 尽管它非常简单,但你将学习的步骤也应该有助于构建其他类型的 Web 应用程序。 在自己的网站或博客里展示3D模型更简单的方式是使用NSDT 3DConvert提供的在线服务,无需任何开发工作,5分钟…

简单3步制作纸质英语绘本的mp3英语朗读音频

孩子学英语,需要看很多英语绘本,而且要听配套的音频。但有些英语绘本是没有对应音频的,下面简单三步,就可以将任意英语绘本制作出对应的英语朗读音频。 第一步,手机拍照做成PDF文件: 绘本每一页拍照后&…

模拟量化面试20问回答

原文链接 参考链接 量化的基本公式 对称均匀量化(symmetric uniform quantization) 对称量化将零点z限制为真实的0。注意对称均匀量化并不是关于零点对称。它还分为有符号和无符号。 signed量化公式 signed量化范围 8bit量化范围[-128, 127] signe…

使用python进行网站答题操作

介绍: 使用Python和DrissionPage模块编写自动化脚本,以模拟人的行为访问网站并获取题目答案进行自动答题。这个脚本似乎是为答题网站设计的,通过监控特定数据包地址来获取题目答案,并模拟点击正确答案进行答题。 代码中的逻辑包…

List实现(2)| LinkedList

参考:LinkedList 源码分析 在Java中,LinkedList是一个双向链表,实现了List和Deque接口,可以被当作列表(List)、队列(Queue)或者双端队列(Deque)使用。它允许…

[渗透测试学习] TwoMillion-HackTheBox

TwoMillion-HackTheBox 信息搜集 nmap扫描一下 nmap -sV -v 10.10.11.221扫描结果 PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0) 80/tcp open http nginx 3851/tcp f…

LeetCode第797题: 所有可能的路径

目录 1.问题描述 2.问题分析 1.问题描述 给你一个有 n 个节点的有向无环图(DAG),请你找出所有从节点 0 到节点 n-1 的路径并输出(不要求按特定顺序)。 graph[i] 是一个从节点 i 可以访问的所有节点的列表&#xff08…

解决IDEA https://start.spring.io/连接不上

1.换成下边这个地址试试 https://start.springboot.io/2.换成阿里云试试,绝对可行,但是版本有点低 https://start.aliyun.com

使用Java调用音乐开放API,并进行播放

使用Java调用音乐开放API,并进行播放 背景描述 电脑没有下载音乐软件,使用网页播放又不太方便,所有就想着使用Java语言直接调用音乐开放API,然后进行播放音乐。 具体代码如下,包含了注释 package com.lowkey.comple…

python学习笔记B-06:序列结构之列表--列表的创建和删除

序列结构主要有列表、元组、字典、集合和字符串,列表是要学习的第一种序列结构。下面是列表的创建和删除方法。 import random #导入一个随机数发生器 print("创建列表方法1:直接列表名,等号,方括号中间内容用逗号隔开&quo…

基于小程序实现的精准扶贫数据收集系统

作者主页:Java码库 主营内容:SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app等设计与开发。 收藏点赞不迷路 关注作者有好处 文末获取源码 技术选型 【后端】:Java 【框架】:ssm 【…

python将xml格式文件转成png或者pdf格式

本文主要介绍运行NCCL代码时输出的xml文件该如何转成更加容易观看的图格式 如下是举例&#xff0c;服务器上的PCIE相关的topo xml 文件 <system version"1"><cpu numaid"1" affinity"ffffff00,0000ffff,ff000000" arch"x86_64&q…

AWB学习记录

主要参考食鱼者博客&#xff1a;https://blog.csdn.net/wtzhu_13/article/details/119301096&#xff0c;以及相关的论文&#xff0c;感谢食鱼者老师整理分享。 灰度世界和完全反射 灰度世界法和完全反射法分别是基于(Rmean, Gmean, Bmean)和(Rmax, Gmax, Bmax)来进行白平衡校…

内部类

一.概念 当一个事物内部&#xff0c;还有一个部分需要一个完整的结构进行描述&#xff0c;而这个内部的完整的结构又只为外部事物提供服务&#xff0c;那么将这个内部的完整结构最好使用内部类。在Java中&#xff0c;可以将一个类定义在另一个类或者一个方法内部&#xff0c;前…

第46篇:随机存取存储器(RAM)模块<五>

Q&#xff1a;本期我们使用Quartus软件的IP Catalog工具创建双端口RAM。 A&#xff1a;前期创建的RAM存储模块只有一个端口&#xff0c;同时为读/写操作提供地址。我们将再创建一个具有两个地址输入端口的RAM模块&#xff0c;分别为读操作和写操作提供地址。选择Basic Functio…