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://xiahunao.cn/news/2803978.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

多租户权限过滤查询-基于mybatisplus权限插件DataPermissionInterceptor实现

前言 因为业务需要对系统中的相关模块的权限通过不同的部门这种属性进行过滤,这边参考了开源项目ruoyi里面的权限过滤设计,然后结合自身的业务进行实现 优秀的开源项目地址:ruoyi-vue-pro 梳理了解了逻辑之后总结了一下实现原理,在需要进行…

Android 仿信号格子强度动画效果实现

效果图 在 Android 中,如果你想要绘制一个圆角矩形并使其居中显示,你可以使用 Canvas 类 drawRoundRect 方法。要使圆角矩形居中,你需要计算矩形的位置,这通常涉及到确定矩形左上角的位置(x, y)&#xff0…

Sora没用上!国产AI创作恐怖电影:《生化危机:重生》下

Sora没用上!国产AI创作恐怖电影:《生化危机:重生》下 丧尸围城,世界沦陷,爱丽丝是拯救这个世界的最后一剂解药,然而。。。 《生化危机:重生》(下):在战斗的最…

QT day2 组件

mywidget.cpp #include "mywidget.h"Mywidget::Mywidget(QWidget *parent): QMainWindow(parent) {this->setWindowTitle("qq");this->setWindowIcon(QIcon("C:\\Users\\41220\\Desktop\\华清\\pictrue\\qq.png"));this->setWindowFla…

微服务远程调用Feign

目录 RPC概述 什么是Feign? Ribbon&Feign对比 Feign的设计架构 Spring Cloud Alibaba快速整合Feign Spring Cloud Feign扩展 日志配置 契约配置 通过拦截器实现参数传递 自定义拦截器实现认证逻辑 超时时间配置 RPC概述 微服务之间如何方便优雅的实…

计算机设计大赛 深度学习卷积神经网络垃圾分类系统 - 深度学习 神经网络 图像识别 垃圾分类 算法 小程序

文章目录 0 简介1 背景意义2 数据集3 数据探索4 数据增广(数据集补充)5 垃圾图像分类5.1 迁移学习5.1.1 什么是迁移学习?5.1.2 为什么要迁移学习? 5.2 模型选择5.3 训练环境5.3.1 硬件配置5.3.2 软件配置 5.4 训练过程5.5 模型分类效果(PC端) 6 构建垃圾…

数字电路 第一章—第二节(逻辑代数的基本概念、公式和定理)

一、基本逻辑关系举例 1、电路图 (1)与逻辑关系: (2)或逻辑关系: (3)非逻辑关系: 2、真值表 (1)在上述三种电路中,经过设定变量和状…

Nginx知识笔记

一、前言 首先,我们来看一张关于正向代理和反向代理的图片 简单理解正向代理和反向代理的概念: 正向代理:在客户端配置代理服务器(和跳板机功能类似,比如公司很多机器需要通过跳板机才允许登录,正向代理的典型用途是…

开源模型应用落地-工具使用篇-向量数据库进阶(四)

一、前言 通过学习"开源模型应用落地"系列文章,我们成功地建立了一个完整可实施的AI交付流程。现在,我们要引入向量数据库,作为我们AI服务的二级缓存。本文将继续基于上一篇“开源模型应用落地-工具使用篇-向量数据库(三…

游泳耳机品牌排行榜前十名:十大爆款火热机型超高性价比

在当今这个科技日新月异的时代,游泳已经不再仅仅是一项简单的运动,而是一种生活方式的体现。随着人们对于健康生活的追求日益增强,游泳耳机也成为了许多游泳爱好者的必备装备之一。然而,市场上琳琅满目的游泳耳机品牌和型号让人眼…

网络安全8-11天笔记

内容安全: 攻击可能只是一个点,防御需要全方面进行。 IAE引擎: DFI和DPI技术:深度检测技术 DPI——深度包检测技术:主要针对完整的数据包(数据包分片,分段需要重组),之…

2024年阿里云服务器优惠价格表和活动整理

2024阿里云服务器优惠活动政策整理,轻量2核2G3M服务器61元一年、2核4G4M带宽165元1年,云服务器4核16G10M带宽26元1个月、149元半年,阿里云ECS云服务器2核2G3M新老用户均可99元一年续费不涨价,企业用户2核4G5M带宽199元一年&#x…

Excel之index、MATCH面试题、VLOOKUP函数,

VLOOKUP() 在表格的首列查找指定的数值,并返回表格当前行中指定列处的数值。 结构:VLOOKUP(查找值,查找区域,列序数,匹配条件) 解释:VLOOKUP(找谁,在哪里找,第几列,0或1) 1.目的:根据【产品】查找【销量】 公式:V…

C++从入门到精通 第十二章(C++流)

写在前面: 本系列专栏主要介绍C的相关知识,思路以下面的参考链接教程为主,大部分笔记也出自该教程,笔者的原创部分主要在示例代码的注释部分。除了参考下面的链接教程以外,笔者还参考了其它的一些C教材(比…

Vue 图片轮播第三方库 介绍

Vue图片轮播是一种在网页上以自动或手动方式展示图片的组件,常用于产品展示、网站banner等场景。有许多第三方库可以帮助Vue开发者轻松实现图片轮播功能。以下是一些流行的Vue图片轮播第三方库的介绍: 1. Vue-awesome-swiper - **简介**:V…

滚雪球学Java(70):深入理解Java中的PriorityQueue底层实现与源码分析

咦咦咦,各位小可爱,我是你们的好伙伴——bug菌,今天又来给大家普及Java SE相关知识点了,别躲起来啊,听我讲干货还不快点赞,赞多了我就有动力讲得更嗨啦!所以呀,养成先点赞后阅读的好…

Linux之ACL权限管理

文章目录 1.ACL权限介绍二、操作步骤1. 添加测试目录、用户、组,并将用户添加到组2. 修改目录的所有者和所属组3. 设定权限4. 为临时用户分配权限5. 验证acl权限6. 控制组的acl权限 1.ACL权限介绍 每个项目成员有一个自己的项目目录,对自己的目录有完全…

【Django】Django自定义后台表单——对一个关联外键对象同时添加多个内容

以官方文档为例: 一个投票问题包含多个选项,基本的表单设计只能一个选项一个选项添加,效率较低,如何在表单设计中一次性添加多个关联选项? 示例代码: from django.contrib import adminfrom .models impo…

森林安全新保障:智能高压应急消防泵的应用

随着城市化进程的加快,森林资源的保护和利用日益受到重视。然而,森林火灾时有发生,给生态环境带来严重破坏。为了有效应对森林火灾,保障森林资源安全,智能高压森林应急消防泵应运而生,成为守护绿色生命的钢…

Python列表:灵活多变的数据结构

文章目录 一、列表1.创建列表2.访问列表元素3.修改列表元素4.添加元素5.删除元素 二、列表脚本操作符1.连接运算符 2.重复运算符 * 三、列表函数&方法1.函数1.1 len() 函数1.2 max() 函数1.3 min() 函数1.4 sum() 函数1.5 list() 函数 2.方法2.1 append() 方法2.2 extend()…