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_zoo


BatchNorm2d = nn.BatchNorm2d

def 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 = stride
        assert stride in [1, 2]

        hidden_dim = round(inp * expand_ratio)
        self.use_res_connect = self.stride == 1 and inp == oup

        if 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 = InvertedResidual
        input_channel = 32
        last_channel = 1280
        interverted_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 == 0
        input_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, 32
        self.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_channel

        self.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 x

    def _initialize_weights(self):
        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
                m.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 model



if __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 partial
        
        model           = 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.mfbz.cn/a/407505.html

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

相关文章

STM32_DS18B20_1_芯片简介及初始化配置

DS18B20介绍 DS18B20数字温度计提供9位到12位摄氏度的温度测量,并具有非易失性,用户可编程的上下触发点的报警功能。DS18B20通过1线总线进行通信,根据定义,该总线只需要一条数据线,即可与中央微处理器进行通信…

NestJS入门7:增加异常过滤器

前文参考: NestJS入门1 NestJS入门2:创建模块 NestJS入门3:不同请求方式前后端写法 NestJS入门4:MySQL typeorm 增删改查 NestJS入门5:加入Swagger NestJS入门6:日志中间件 本文代码基于上一篇文章《…

Flink join详解(含两类API及coGroup、connect详解)

Flink SQL支持对动态表进行复杂而灵活的连接操作。 为了处理不同的场景,需要多种查询语义,因此有几种不同类型的 Join。 默认情况下,joins 的顺序是没有优化的。表的 join 顺序是在 FROM 从句指定的。可以通过把更新频率最低的表放在第一个、…

Redis可视化工具——RedisInsight

文章目录 1. 下载2. 安装3. RedisInsight 添加 Redis 数据库4. RedisInsight 使用 RedisInsight 是 Redis 官方出品的可视化管理工具,支持 String、Hash、Set、List、JSON 等多种数据类型的管理,同时集成了 RedisCli,可进行终端交互。 1. 下载…

【数据结构和算法初阶(C语言)】时间复杂度(衡量算法快慢的高端玩家,搭配例题详细剖析)

目录 1.算法效率 1.1如何衡量一个算法的好坏 1.2 算法的复杂度 2.主菜-时间复杂度 2.1 时间复杂度的概念 2.2 大O的渐进表示法 2.2.1算法的最好,最坏和平均的情况 3.经典时间复杂度计算举例 3.1计算冒泡排序的时间复杂度 3.2计算折半查找的时间复杂度 3.…

思维导图教你如何学会计算机组成原理

02 给你一张知识地图,计算机组成原理应该这么学 了解了现代计算机的基本硬件组成和背后最基本的冯诺依曼体系结构,我们就可以正式进入计算机组成原理的学习了。在学习一个一个零散的知识点之前,我整理了一份学习地图,好让你对将要…

AI:132-基于深度学习的涉案人脸图像识别与敲诈勒索嫌疑分析

🚀点击这里跳转到本专栏,可查阅专栏顶置最新的指南宝典~ 🎉🎊🎉 你的技术旅程将在这里启航! 从基础到实践,深入学习。无论你是初学者还是经验丰富的老手,对于本专栏案例和项目实践都有参考学习意义。 ✨✨✨ 每一个案例都附带有在本地跑过的关键代码,详细讲解供…

华清远见作业第四十二天——Qt(第四天)

思维导图&#xff1a; 编程&#xff1a; 代码&#xff1a; widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include<QTextToSpeech> //语音播报类 QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public Q…

一种新型的AlGaN/GaN HEMTs小信号建模与参数提取方法

来源&#xff1a;A new small-signal modeling and extraction methodin AlGaN/GaN HEMTs&#xff08;SOLID-STATE ELECTRONICS 07年&#xff09; 摘要 本文提出了一种新型的用于GaN HEMTs&#xff08;氮化镓高电子迁移率晶体管&#xff09;的小信号等效电路&#xff0c;包含2…

大离谱!AI写作竟让孔子遗体现身巴厘岛,看完笑不活了

大家好&#xff0c;我是二狗。 这两天我在知乎上看到了一个AI写作大翻车的案例&#xff0c;看完简直笑不活了&#xff0c;特地分享给大家一起 happy happy&#xff5e; 知乎网友“打开盒子吓一跳”一上来就抛出来了一个“孔子去世”的王炸。 首先&#xff0c;下面是一条真实新…

Linux第65步_学习“Makefie”

学习“Makefie”&#xff0c;为后期学习linux驱动开发做铺垫。 1、在“/home/zgq/linux/atk-mp1”创建一个“Test_MakeFile”目录用于学习“Makefie”。 打开终端 输入“cd /home/zgq/linux/回车”&#xff0c;切换到“/home/zgq/linux/”目录 输入“mkdir Linux_Drivers回…

代码随想录刷题笔记-Day22

1. 修剪二叉搜索树 669. 修剪二叉搜索树https://leetcode.cn/problems/trim-a-binary-search-tree/ 给你二叉搜索树的根节点 root &#xff0c;同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树&#xff0c;使得所有节点的值在[low, high]中。修剪树 不应该 改变保留…

神经网络系列---计算图基本原理

文章目录 计算图符号微分符号微分的步骤示例符号微分在计算图中的使用总结 数值微分前向差分法中心差分法数值微分的使用注意事项总结 自动微分1. 基本原理2. 主要类型3. 计算图4. 应用5. 工具和库6. 优点和缺点 计算图1. **计算图的建立**2. **前向传播**3. **反向传播**4. **…

《插入排序》与《选择排序》

目录 前言&#xff1a; 排序的概念&#xff1a; 插入排序&#xff1a; 1.直接插入排序&#xff1a; 2.希尔排序( 缩小增量排序 )&#xff1a; 选择排序&#xff1a; 1.直接选择排序: 2.快速排序&#xff1a; hore思想&#xff1a; 挖坑法&#xff1a; 双指针法&#…

责任链模式与spring容器的搭配应用

背景 有个需求&#xff0c;原先只涉及到一种A情况设备的筛选&#xff0c;每次筛选会经过多个流程&#xff0c;比如先a功能&#xff0c;a功能通过再筛选b功能&#xff0c;然后再筛选c功能&#xff0c;以此类推。现在新增了另外一种B情况的筛选&#xff0c;B情况同样需要A情况的筛…

软件设计师软考题目解析02 --每日五题

想说的话&#xff1a;要准备软考了。0.0&#xff0c;其实我是不想考的&#xff0c;但是吧&#xff0c;由于本人已经学完所有知识了&#xff0c;只是被学校的课程给锁在那里了&#xff0c;不然早找工作去了。寻思着反正也无聊&#xff0c;就考个证玩玩。 本人github地址&#xf…

网络中的进程监控

每个企业都有一些流程和程序来实现他们的业务目标&#xff0c;这同样适用于网络&#xff0c;网络中的进程监控是分析、处理和管理网络内发生的各种活动以提高网络性能和能力的做法。 网络中需要监控的基本进程 监视系统资源&#xff08;CPU 利用率、内存利用率、CPU 温度等&a…

ChatGPT在数据分析学习阶段的应用

ChatGPT在数据分析学习阶段的应用 ​ 这个阶段&#xff0c;核心是三件事&#xff1a;制定学习计划、确定学习资料以及学习策略。我们可以自己完成这几件事&#xff0c;当然也可以借助ChatGPT来高效地达到目的。 1.1 制定学习计划 ​ 学习阶段的第一件事是制定学习计划&#…

红队评估四靶场

文章目录 环境搭建1.设置所需网卡2.更改win7设置3.DC设置4.web设置开启docker服务5.kali网段`渗透启动`1.确认对方靶机的IP地址2.端口探测3.web探测`2001端口``2002端口`Tomcat/8.5.19漏洞复现`2003端口`4.docker逃逸5.ssh密钥爆破`域渗透启动`1.提权2.隧道搭建各项配置文件内容…

自助点餐系统微信小程序,支持外卖、到店等

总体介绍 系统总共分为三个端&#xff1a;后端&#xff0c;后台管理系统、微信小程序。 基于当前流行技术组合的前后端分离商城系统&#xff1a; SpringBoot2MybatisPlusSpringSecurityjwtredisVue的前后端分离的商城系统&#xff0c; 包含分类、sku、积分、多门店等 预览图…
最新文章