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

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

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

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_infoflops,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_infoflops,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)

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

力扣HOT100 - 56. 合并区间

解题思路: class Solution {public int[][] merge(int[][] intervals) {// 先按照区间起始位置排序Arrays.sort(intervals, (v1, v2) -> v1[0] - v2[0]);int[][] res new int[intervals.length][2];int idx -1;for (int[] interval : intervals) {//直接加入的…

CSS基础之伪类选择器(如果想知道CSS的伪类选择器知识点,那么只看这一篇就足够了!)

前言:学习CSS就必须要学习选择器,在之前我们已经学习了基本选择器和复合选择器,但是还有几个选择器没有学习,这篇文章主要讲解伪类选择器。 ✨✨✨这里是秋刀鱼不做梦的BLOG ✨✨✨想要了解更多内容可以访问我的主页秋刀鱼不做梦-…

基于springboot实现视频网站管理系统【项目源码+论文说明】计算机毕业设计

基于springboot实现视频网站管理系统演示 摘要 使用旧方法对视频信息进行系统化管理已经不再让人们信赖了,把现在的网络信息技术运用在视频信息的管理上面可以解决许多信息管理上面的难题,比如处理数据时间很长,数据存在错误不能及时纠正等问…

顶顶通呼叫中心中间件(mod_cti基于FreeSWITCH)-回铃音补偿

文章目录 前言联系我们解决问题操作步骤 前言 回铃音: 当别人打电话给你时,你的电话响铃了,而他听到的声音叫做回铃音。回铃音是被叫方向主叫方传送,也是彩铃功能的基础。我们平时打电话听到的“嘟 嘟 嘟 嘟”的声音,就…

asp.net core 网页接入微信扫码登录

创建微信开放平台账号&#xff0c;然后创建网页应用 获取appid和appsecret 前端使用的vue&#xff0c;安装插件vue-wxlogin 调用代码 <wxlogin :appid"appId" :scope"scope" :redirect_uri"redirect_uri"></wxlogin> <scri…

机器学习和深度学习 --李宏毅(笔记与个人理解)Day 18

Day 18 Spatial Transformer Layer 因为单纯的cNN无法做到scaling&#xff08;放大&#xff09;and rotation&#xff08;转&#xff09;&#xff0c;所以我们引入&#xff1b; 实战中也许我们可以做到 是因为 我们的training data 中包含了对data 的augmentation&#xff1b; …

解锁智能未来:用Ollama开启你的本地AI之旅

Ollama是一个用于在本地运行大型语言模型&#xff08;LLM&#xff09;的开源框架。它旨在简化在Docker容器中部署LLM的过程&#xff0c;使得管理和运行这些模型变得更加容易。Ollama提供了类似OpenAI的API接口和聊天界面&#xff0c;可以非常方便地部署最新版本的GPT模型并通过…

企业邮箱价格调查:找到适合你的最佳选择

企业邮箱价格从免费到几百元的都有&#xff0c;价格不同获得的功能和服务也不同&#xff0c;按需购买。企业邮箱多少钱一年&#xff1f;企业邮箱价格。Zoho Mail企业邮箱轻量版300元/5用户/年&#xff0c;高级版200元/用户/年&#xff0c;套件版150元/用户/元。具体的价格取决于…

《HF经理》:一、管理误区

1、不善授权: 原因&#xff1a;不信任下属&#xff0c;惯性思维&#xff08;任务一来自己冲到最前面&#xff09; 对策&#xff1a;从个人成功到带领团队成功。培养并信任下属。 2、不主动寻求上级支持: 原因&#xff1a;上级不仅仅是你的监督和考核者&#xff0c;还是你的支…

计算机网络 Cisco静态路由实验

一、实验要求与内容 1、路由器的基本配置 &#xff08;1&#xff09;命名 &#xff08;2&#xff09;关闭域名解析 &#xff08;3&#xff09;设置路由接口IP地址 2、配置静态路由以实现所有客户机都能互相通信 3、配置默认路由 4、了解ping命令和trace&#xff08;跟踪…

基于SpringBoot的“外卖点餐系统”的设计与实现(源码+数据库+文档+PPT)

基于SpringBoot的“外卖点餐系统”的设计与实现&#xff08;源码数据库文档PPT) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 系统功能图 用户功能界面 订单管理界面 配送单管…

设计模式——迭代器模式15

迭代器模式提供一种方法访问一个容器对象中各个元素&#xff0c;而又不需暴露该对象的内部细节。 设计模式&#xff0c;一定要敲代码理解 抽象迭代器 /*** 迭代抽象* */ public interface Iterator<A> {A next();boolean hasNext(); }迭代器实现 /*** author ggbond*…

极市平台 | 卫星图像公开数据集资源汇总

本文来源公众号“极市平台”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;卫星图像公开数据集资源汇总 本文收集整理了卫星图像的开源数据集&#xff0c;多用于图像分割方向&#xff0c;希望能给大家的学习带来帮助。 1 水体卫…

DHCP是什么意思 路由器中DHCP服务器怎么设置?

概述 DHCP是什么意思&#xff1f;很多朋友在路由器设置中&#xff0c;都会看到有一项“DHCP服务器”设置功能&#xff0c;而很多朋友对这个功能不太了解&#xff0c;也不知道怎么设置。其实&#xff0c;对于普通用户来说&#xff0c;无需去单独设置路由器DHCP服务器功能&#…

CMake快速入门

文章目录 目的环境准备快速入门总结 目的 C/C的代码可以直接使用编译工具链进行编译&#xff0c;这种方式文件一多就不方便了。也可以编写 Makefile 然后使用 make 进行编译&#xff0c;当然写 Makefile 其实也挺繁琐。对于大型项目比较流行的是编写 CMakeLists.txt 然后使用 …

SpringBoot中注册Bean的方式汇总

文章目录 ComponentScan Componet相关注解BeanImportspring.factories总结Configuration和Component的主要区别&#xff1f;Bean是不是必须和Configuration一起使用&#xff1f;Import导入配置类有意义&#xff1f;出现异常&#xff1a;java.lang.NoClassDefFoundError: Could…

大语言模型总结整理(不定期更新)

《【快捷部署】016_Ollama&#xff08;CPU only版&#xff09;》 介绍了如何一键快捷部署Ollama&#xff0c;今天就来看一下受欢迎的模型。 模型简介gemmaGemma是由谷歌及其DeepMind团队开发的一个新的开放模型。参数&#xff1a;2B&#xff08;1.6GB&#xff09;、7B&#xff…

文心一言 VS 讯飞星火 VS chatgpt (236)-- 算法导论17.3 2题

二、使用势能法重做练习17.1-3。练习17.1-3的内容是&#xff1a;假定我们对一个数据结构执行一个由 n 个操作组成的操作序列&#xff0c;当 i 严格为 2 的幂时第 i 个操作的代价为 i &#xff0c;否则代价为1。使用聚合分析确定每个操作的摊还代价。如果要写代码&#xff0c;请…

JAVA实现人工智能,采用框架SpringAI

Spring AI介绍 Spring AI是AI工程师的一个应用框架&#xff0c;它提供了一个友好的API和开发AI应用的抽象&#xff0c;旨在简化AI应用的开发工序&#xff0c;例如开发一款基于ChatGPT的对话应用程序。 项目地址&#xff1a;https://github.com/spring-projects-experimental/sp…

AGV小车导航避障雷达SE-0533(CNS-LS05C)激光传感器RS232|RS485|CAN BUS连线说明

AGV小车导航避障雷达SE-0533(CNS-LS05C)激光传感器广泛应用到AGV小车&#xff0c;RGV小车&#xff0c;无人叉车、搬运机器人等领域。本文重点介绍AGV小车导航避障雷达SE-0533(CNS-LS05C)激光传感器RS232|RS485|CAN BUS连线说明。 一、线序定义 1、传感器线缆线序定义 SE-053…