2.deeplabv3+的主干网络(mobilenet网络)

        deeplabv3的论文中用了resnet网络,在这里用轻量级网络mobilenet替换resnet,下面分别是两个网络的代码。

1.mobilenet网络

代码如下:

import math
import os
import cv2
import numpy as np
import torch
import torch.nn as nn
import torch.utils.model_zoo as model_zooBatchNorm2d = nn.BatchNorm2ddef conv_bn(inp, oup, stride):return nn.Sequential(nn.Conv2d(inp, oup, 3, stride, 1, bias=False),BatchNorm2d(oup),nn.ReLU6(inplace=True))def conv_1x1_bn(inp, oup):return nn.Sequential(nn.Conv2d(inp, oup, 1, 1, 0, bias=False),BatchNorm2d(oup),nn.ReLU6(inplace=True))class InvertedResidual(nn.Module):def __init__(self, inp, oup, stride, expand_ratio):super(InvertedResidual, self).__init__()self.stride = strideassert stride in [1, 2]hidden_dim = round(inp * expand_ratio)self.use_res_connect = self.stride == 1 and inp == oupif expand_ratio == 1:self.conv = nn.Sequential(#--------------------------------------------##   进行3x3的逐层卷积,进行跨特征点的特征提取#--------------------------------------------#nn.Conv2d(hidden_dim, hidden_dim, 3, stride, 1, groups=hidden_dim, bias=False),BatchNorm2d(hidden_dim),nn.ReLU6(inplace=True),#-----------------------------------##   利用1x1卷积进行通道数的调整#-----------------------------------#nn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False),BatchNorm2d(oup),)else:self.conv = nn.Sequential(#-----------------------------------##   利用1x1卷积进行通道数的上升#-----------------------------------#nn.Conv2d(inp, hidden_dim, 1, 1, 0, bias=False),BatchNorm2d(hidden_dim),nn.ReLU6(inplace=True),#--------------------------------------------##   进行3x3的逐层卷积,进行跨特征点的特征提取#--------------------------------------------#nn.Conv2d(hidden_dim, hidden_dim, 3, stride, 1, groups=hidden_dim, bias=False),BatchNorm2d(hidden_dim),nn.ReLU6(inplace=True),#-----------------------------------##   利用1x1卷积进行通道数的下降#-----------------------------------#nn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False),BatchNorm2d(oup),)def forward(self, x):if self.use_res_connect:#使用残差边return x + self.conv(x)else:return self.conv(x)#不使用残差边class MobileNetV2(nn.Module):def __init__(self, n_class=1000, input_size=224, width_mult=1.):super(MobileNetV2, self).__init__()block = InvertedResidualinput_channel = 32last_channel = 1280interverted_residual_setting = [# t, c, n, s[1, 16, 1, 1], # 256, 256, 32 -> 256, 256, 16[6, 24, 2, 2], # 256, 256, 16 -> 128, 128, 24   2[6, 32, 3, 2], # 128, 128, 24 -> 64, 64, 32     4[6, 64, 4, 2], # 64, 64, 32 -> 32, 32, 64       7[6, 96, 3, 1], # 32, 32, 64 -> 32, 32, 96[6, 160, 3, 2], # 32, 32, 96 -> 16, 16, 160     14[6, 320, 1, 1], # 16, 16, 160 -> 16, 16, 320]assert input_size % 32 == 0input_channel = int(input_channel * width_mult)self.last_channel = int(last_channel * width_mult) if width_mult > 1.0 else last_channel# 512, 512, 3 -> 256, 256, 32self.features = [conv_bn(3, input_channel, 2)]for t, c, n, s in interverted_residual_setting:output_channel = int(c * width_mult)for i in range(n):if i == 0:self.features.append(block(input_channel, output_channel, s, expand_ratio=t))else:self.features.append(block(input_channel, output_channel, 1, expand_ratio=t))input_channel = output_channelself.features.append(conv_1x1_bn(input_channel, self.last_channel))self.features = nn.Sequential(*self.features)self.classifier = nn.Sequential(nn.Dropout(0.2),nn.Linear(self.last_channel, n_class),)self._initialize_weights()def forward(self, x):x = self.features(x)x = x.mean(3).mean(2)x = self.classifier(x)return xdef _initialize_weights(self):for m in self.modules():if isinstance(m, nn.Conv2d):n = m.kernel_size[0] * m.kernel_size[1] * m.out_channelsm.weight.data.normal_(0, math.sqrt(2. / n))if m.bias is not None:m.bias.data.zero_()elif isinstance(m, BatchNorm2d):m.weight.data.fill_(1)m.bias.data.zero_()elif isinstance(m, nn.Linear):n = m.weight.size(1)m.weight.data.normal_(0, 0.01)m.bias.data.zero_()def load_url(url, model_dir='./model_data', map_location=None):if not os.path.exists(model_dir):os.makedirs(model_dir)filename = url.split('/')[-1]cached_file = os.path.join(model_dir, filename)if os.path.exists(cached_file):return torch.load(cached_file, map_location=map_location)else:return model_zoo.load_url(url,model_dir=model_dir)def mobilenetv2(pretrained=False, **kwargs):model = MobileNetV2(n_class=1000, **kwargs)if pretrained:model.load_state_dict(load_url('https://github.com/bubbliiiing/deeplabv3-plus-pytorch/releases/download/v1.0/mobilenet_v2.pth.tar'), strict=False)return modelif __name__ == '__main__':img_paths = r"img\000001.jpg"img = cv2.imread(img_paths)img = cv2.resize(img, (512, 512))images = img.reshape(1, 3, 512, 512)#images=img.reshape(1,3,1080,1920)data=torch.tensor(images,dtype=torch.float32)#print(data.sum())model=MobileNetV2()for i,layer in enumerate(model.features):print(i,layer)# output=model(data)# print(output)

代码运行结构如下:

        结果从0到17共18层卷积网络。在该网络结构中,输入的数据大小是1X3X512X512,网络结构共有18层,在这里对下面的部分代码做一些解释:

解释1:  

        以上是网络结构,t表示是否需要升维,1表示不需要升维,6表示需要;c表示该网络结构输出的通道数;n表示该网络结构重复次数;s表示该网络结构的步长。如[6,24,2,2]表示不需要下采样,输出通道数为24,重复两次网络结构,步长是2,该层的网络输出结果如下:

        我们对以上的n的所有值相加得1+2+3+4+3+3+1=17,再加上刚输入进来的一层网络结构刚好等于18层.

解释2:InvertedResidual类

如下图所示,mobilenetv2网络结构的最基本单元(InvertedResidual)就是下图结构:

        上图中用了1X1卷积+3X3卷积+1X1卷积共3层网络构成,第一个1X1卷积起到升维的作用,可以使得获取的信息更丰富,第二个3X3卷积进行跨特征点信息提取,第3个1X1卷积进行降维,是为了减少计算量,也为了获取卷积的主要信息。从上面构建卷积网络的循环代码中可以看到,每个单元网络都是由InvertedResidual构成的,而不是简单的 卷积+BN+激活函数 的结构。

注意,这个类最后返回两种结果:一种是返回残差结果,一种是不使用残差边的结果。

解释3:代码中的self.features

如下图所示:self.features是一个列表变量,里面的conv_bn是代码中最上面的函数,其实就是定义的一个Conv2d+BN+ReLU6的一个卷积层。

        在这里定义了self.features后,它又在第二个图片的for循环里不断的添加(append)新的卷积层,这个for循环添加了17个卷积层,加上定义时的一个卷积层,总共刚好18个卷积层。

        在这里,我们就对mobilenetv2的网络结构解释完了。

2.deeplabv3+对mobilenetv2的运用

           在deeplabv3+里,我们首先写入上面的代码,文件名称为mobilenetv2.py,然后再写一个deeplabv3_plus.py文件对先前写的代码进行引用,代码如下:

class MobileNetV2(nn.Module):def __init__(self, downsample_factor=8, pretrained=True):super(MobileNetV2, self).__init__()from functools import partialmodel           = mobilenetv2(pretrained)self.features   = model.features[:-1]self.total_idx  = len(self.features)self.down_idx   = [2, 4, 7, 14]if downsample_factor == 8:for i in range(self.down_idx[-2], self.down_idx[-1]):self.features[i].apply(partial(self._nostride_dilate, dilate=2))for i in range(self.down_idx[-1], self.total_idx):self.features[i].apply(partial(self._nostride_dilate, dilate=4))elif downsample_factor == 16:for i in range(self.down_idx[-1], self.total_idx):self.features[i].apply(partial(self._nostride_dilate, dilate=2))def _nostride_dilate(self, m, dilate):classname = m.__class__.__name__if classname.find('Conv') != -1:if m.stride == (2, 2):m.stride = (1, 1)if m.kernel_size == (3, 3):m.dilation = (dilate//2, dilate//2)m.padding = (dilate//2, dilate//2)else:if m.kernel_size == (3, 3):m.dilation = (dilate, dilate)m.padding = (dilate, dilate)def forward(self, x):low_level_features = self.features[:4](x)x = self.features[4:](low_level_features)return low_level_features, x 

        对于以上代码的主要部分,在这里做部分解释如下:

解释一:self.features = model.features[:-1]

        这个代码就是提取mobilenetv2代码的self.features,那这里为什么加了[:-1]呢?因为mobilenetv2最后加了一层卷积self.features.append(conv_1x1_bn(input_channel, self.last_channel)),这个卷积层其实就是mobilenetv2自身分类用的,而在deeplabv3+里不需要这一层卷积,所以下面的代码调用的是model.features[:-1]。

解释二:代码中的self.down_idx = [2, 4, 7, 14]

这行代码是与mobilenetv2代码的卷积层对应的,mobilenetv2代码有下图的几行代码:

        其实,[2, 4, 7, 14]中的几个数对应的是图片中s=2的卷积层的位置。

  • 图片中的第二行的s=2对应卷积层的第3层(前两层是 1+1)位置(对应的坐标位置就是2),最前面有一层初始定义的卷积层(前面已经解释过);
  • 图片中第3行的2对应第5层(前4层是1+1+2)位置(对应的坐标位置就是4);
  • 图片中第4行的2对应第8层(前7层是1+1+2+3)位置(对应的坐标位置就是7);
  • 图片中第6行的2对应第15层(前14层是1+1+2+3+4+3)位置(对应的坐标位置就是14);

解释3:downsample_factor == 8或者downsample_factor == 16

       这两行代码表示如果downsample_factor == 8,表示我们只需要3次下采用,那么我们需要将[2, 4, 7, 14]的后两次采样的参数做一个修改(对第7和第14层的参数作一个修改),即将步长s修改为1.

        前3次下采样的地方是:第0层到第1层之间做了一次下采样;第2层到第3层之间做了一次下采样;第4层到第5层之间做了一次下采样.

        如果downsample_factor == 16,表示我们只需要4次下采用,那么我们需要将[2, 4, 7, 14]的后一次采样的参数做一个修改(第14层的参数作一个修改),即将步长s修改为1.

        前4次下采样的地方是:第0层到第1层之间做了一次下采样;第2层到第3层之间做了一次下采样;第4层到第5层之间做了一次下采样;第7层到第8层之间做了一次下采样。

        在这里,我们就对deeplabv3+中的mobilenet2模型的运用解释完了!!!

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

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

相关文章

基于YOLOv8深度学习+Pyqt5的电动车头盔佩戴检测系统

wx供重浩:创享日记 对话框发送:225头盔 获取完整源码源文件已标注的数据集(1463张)源码各文件说明配置跑通说明文档 若需要一对一远程操作在你电脑跑通,有偿89yuan 效果展示 基于YOLOv8深度学习PyQT5的电动车头盔佩戴检…

网络防御-内容安全

目录 内容安全IAE引擎DFI和DPI技术 --- 深度检测技术DPI --- 深度包检测技术DFI --- 深度流检测技术 入侵防御(IPS)入侵检测的方法异常检测误用检测 签名ID --- 签名的标识检测范围 内容安全 攻击可能只是一个点,防御需要全方面进行 IAE引擎 …

2 easy 27. 移除元素

双指针法 复杂度: //给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。 // // 不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。 // // 元素的顺…

【大数据】Flink SQL 语法篇(四):Group 聚合

Flink SQL 语法篇(四):Group 聚合 1.基础概念2.窗口聚合和 Group 聚合3.SQL 语义4.Group 聚合支持 Grouping sets、Rollup、Cube 1.基础概念 Group 聚合定义(支持 Batch / Streaming 任务):Flink 也支持 G…

RCE (Remote ????? execution) --->CTF

看这个标题就知道今天的内容不简单!!!! 那么就来讲一下我们的RCE吧 目录 ​编辑 1. &? |? ||? &&? 2.PHP命令执行函数&& ||"" 1."" &…

6、进程、服务管理

一、进程管理 1.概述 进程是正在执行的程序或命令,每一个进程都独立运行,都有自己的地址空间,并占用一定的系统资源以后开发会遇见: 端口占用出现程序假死、卡死 2.查看系统运行进程 语法 ps 参数ps –a:显示当前终端下的所有…

智能SQL生成:后端技术与LLM的完美结合

文章目录 引言一、什么是大模型二、为什么选择LLM三、开发技术说明四、系统架构说明五、编码实战1. Maven2. 讯飞大模型配置类3. LLM相关的封装4. 编写LLM的service5. 编写controller6. 运行测试 六、总结 引言 本篇文章主要是关于实现一个类似Chat2DB的根据自然语言生成SQL的…

开源工具和框架

目录 开源工具和框架 一、 开源工具和框架 二、开源工具和框架在现代软件开发中的角色 1、基础设施建设: 2、开发效率提升: 3、代码质量保障: 4、技术创新: 三、广泛使用的开源项目分析 3.1、Linux 3.2、Git 3.3、Docke…

【Java程序设计】【C00313】基于Springboot的物业管理系统(有论文)

基于Springboot的物业管理系统(有论文) 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的物业管理系统,本系统有管理员、物业、业主以及维修员四种角色权限; 管理员进入主页面,主要功能包…

mybatis总结传参三

十、(不推荐)多个参数-按位置传参 参数位置从 0 开始, 引用参数语法 #{ arg 位置 } , 第一个参数是 #{arg0}, 第二个是 #{arg1} 注意: mybatis-3.3 版本和之前的版本使用 #{0},#{1} 方式, 从 myba…

stream流-> 判定 + 过滤 + 收集

List<HotArticleVo> hotArticleVos hotArticleVoList .stream() .filter(x -> x.getChannelId().equals(wmChannel.getId())).collect(Collectors.toList()); 使用Java 8中的Stream API对一个名为hotArticleVoList的列表进行过滤操作&#xff0c;筛选出符合指定条件…

SQL进阶(三):Join 小技巧:提升数据的处理速度

复杂数据结构处理&#xff1a;Join 小技巧&#xff1a;提升数据的处理速度 本文是在原本sql闯关的基础上总结得来&#xff0c;加入了自己的理解以及疑问解答&#xff08;by GPT4&#xff09; 原活动链接 用到的数据&#xff1a;链接 提取码&#xff1a;l03e 目录 1. 课前小问…

stable-diffusion-webui+sadTalker开启GFPGAN as Face enhancer

接上一篇&#xff1a;在autodl搭建stable-diffusion-webuisadTalker-CSDN博客 要开启sadTalker gfpgan as face enhancer&#xff0c; 需要将 1. stable-diffusion-webui/extensions/SadTalker/gfpgan/weights 目录下的文件拷贝到 :~/autodl-tmp/models/GFPGAN/目录下 2.将G…

Spring Boot Profiles简单介绍

Spring Boot application.properties和application.yml文件的配置 阅读本文之前&#xff0c;请先阅读上面的配置文件介绍。 Spring Boot Profiles是一个用于区分不同环境下配置的强大功能。以下是如何在Spring Boot应用程序中使用Profiles的详细步骤和代码示例。 1. 创…

【openGL教程08】基于C++的着色器(02)

LearnOpenGL - Shaders 一、说明 着色器是openGL渲染的重要内容&#xff0c;客户如果想自我实现渲染灵活性&#xff0c;可以用着色器进行编程&#xff0c;这种程序小脚本被传送到GPU的显卡内部&#xff0c;起到动态灵活的着色作用。 二、着色器简述 正如“Hello Triangle”一章…

鸿蒙开发-UI-图形-绘制几何图形

鸿蒙开发-UI-组件 鸿蒙开发-UI-组件2 鸿蒙开发-UI-组件3 鸿蒙开发-UI-气泡/菜单 鸿蒙开发-UI-页面路由 鸿蒙开发-UI-组件导航-Navigation 鸿蒙开发-UI-组件导航-Tabs 鸿蒙开发-UI-图形-图片 文章目录 前言 一、绘制组件 二、形状视口 三、自定义样式 四、使用场景 总结 前…

贪心算法学习

贪心算法&#xff08;Greedy Algorithm&#xff09;是一种在每一步选择中都采取在当前状态下最好或最优&#xff08;即最有利&#xff09;的选择&#xff0c;从而希望导致结果是全局最好或最优的算法。贪心算法在有最优子结构的问题中尤为有效。然而&#xff0c;要注意的是贪心…

【C++进阶】STL容器--list底层剖析(迭代器封装)

目录 前言 list的结构与框架 list迭代器 list的插入和删除 insert erase list析构函数和拷贝构造 析构函数 拷贝构造 赋值重载 迭代器拷贝构造、析构函数实现问题 const迭代器 思考 总结 前言 前边我们了解了list的一些使用及其注意事项&#xff0c;今天我们进一步深入…

2024年2月16日优雅草蜻蜓API大数据服务中心v1.1.1大更新-UI全新大改版采用最新设计ui·增加心率计算器·退休储蓄计算·贷款还款计算器等数接口

2024年2月16日优雅草蜻蜓API大数据服务中心v1.1.1大更新-UI全新大改版采用最新设计ui增加心率计算器退休储蓄计算贷款还款计算器等数接口 更新日志 前言&#xff1a;本次更新中途跨越了很多个版本&#xff0c;其次本次ui大改版-同步实时发布教程《带9.7k预算的实战项目layuiph…

JavaWeb——006MYSQL(DDLDML)

这里写目录标题 数据库开发-MySQL首先来了解一下什么是数据库。1. MySQL概述1.1 安装1.1.1 版本1.1.2 安装1.1.3 连接1.1.4 企业使用方式(了解) 1.2 数据模型1.3 SQL简介1.3.1 SQL通用语法1.3.2 分类 2. 数据库设计-DDL2.1 项目开发流程2.2 数据库操作2.2.1 查询数据库2.2.2 创…