Yolo v7网络实现细节(一)

news2024/10/5 14:31:08

Yolo v7网络实现细节

YOLO v7网络架构的整体介绍

不同GPU和对应模型:

  • ​​​​​​​边缘GPU:YOLOv7-tiny
  • 普通GPU:YOLOv7​​​​​​​
  • 云GPU的基本模型: YOLOv7-W6

激活函数:

  • YOLOv7 tiny: leaky ReLU
  • 其他模型:SiLU

同时,我们还针对不同的业务需求,使用基础模型进行模型缩放,得到不同类型的模型。 对于YOLOv7,我们对颈部进行stack scaling,并使用提出的复合缩放方法对整个模型的深度和宽度进行缩放,并以此获得YOLOv7-X。

  • YOLOv7缩放得到了YOLOv7-X
  • 对YOLOv7-W6我们使用新提出的复合缩放方法得到 YOLOv7-E6YOLOv7-D6
  • EELAN 用于 YOLOv7-E6,从而完成了 YOLOv7E6E

网络模块

Yolo v7网络由多个复杂的模块拼接构建而成,在学习使用Yolo v7网络之前首先要学习各个网络模块的实现细节。

CBS模块

CBS模块是最基本的一个网络模块可以说是Yolo v7中的基础卷积模块 。CBS模块由三个部分拼接组成。在最后通过画图软件给出CBS模块的直观表示。

  • CONV:卷积层
  • BN:批量归一化层
  • SiLU:SiLU激活函数层

CBS模块也就是三个拼接层的缩写,在common.py中的源码表示如下所示。

class Conv(nn.Module):
    # Standard convolution
    def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True):  # ch_in, ch_out, kernel, stride, padding, groups
        super(Conv, self).__init__()
        self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p), groups=g, bias=False)
        self.bn = nn.BatchNorm2d(c2)
        self.act = nn.SiLU() if act is True else (act if isinstance(act, nn.Module) else nn.Identity())

    def forward(self, x):
        return self.act(self.bn(self.conv(x)))

    def fuseforward(self, x):
        return self.act(self.conv(x))

注意与说明:这里的CBS模块与我之前在Yolo v5中的CBL模块相同,之所以定义为CBS模块是因为V7中使用过leakyRelu激活函数便于进行区分。

在这里插入图片描述

ELAN模块

在论文中也提到了YOLO v7网络在之前基础上改进网络结构的时候创新性的使用了ELAN模块,并将其应用到网络之中。

说明:在YOLO V7网络结构中用到的第一个ELAN模块输入是160x160的128通道的一个输入特征图。经过ELAN模块后变为了160x160的256通道数的输出

在这里插入图片描述
首先我们对论文中给出的ELAN[1]结构进行解读:

  1. 将输入的2c个通道平均分为两份c,c其中的第一个通道c直接作为concat连接层的一个输入
  2. 另外的一个通道c输入到两个部分,第一个部分同样作为concat连接层的一个输入,另外的一个部分输入到一个3x3的卷积模块中。
  3. 在3x3的卷积模块结束的地方并联一个另外的3x3模块,在深度和水平方向上进行了一个拓展。
  4. 将上面的四个部分进行一个concat,同时通过一个1x1的卷积核调整通道数的大小。

在学习ELAN模块的源码的时候我们发现,在common.py文件中并没有单独的编写一个ELAN模块而是通过CBS模块和Concat模块多次组合而成的

YOLO V7中ELAN模块的yaml配置文件项

第一个ELAN模块在配置文件项中对应的是4层到11层(画图时便于进行编号)

   [-1, 1, Conv, [64, 1, 1]], #ELAN 4
   [-2, 1, Conv, [64, 1, 1]], #5
   [-1, 1, Conv, [64, 3, 1]], #6
   [-1, 1, Conv, [64, 3, 1]], #7
   [-1, 1, Conv, [64, 3, 1]], #8
   [-1, 1, Conv, [64, 3, 1]], #9
   [[-1, -3, -5, -6], 1, Concat, [1]], #10
   [-1, 1, Conv, [256, 1, 1]],  # 11

通过concat模块拼接成一个维度torch.cat(x, self.d)

class Concat(nn.Module):
    def __init__(self, dimension=1):
        super(Concat, self).__init__()
        self.d = dimension

    def forward(self, x):
        return torch.cat(x, self.d)

在这里插入图片描述

E-ELAN模块

E-ELAN = extend ELANA(拓展的ELAN):E-ELAN模块时YOLO v7网络中全新提出的一个模块是V7网络的一个创新点

在论文的原图中给出了E-ELAN模块的说明图如下所示。

在这里插入图片描述

  1. 拓展一份并行的ELAN模块并将其输出相加来构成。
  2. 使用到了分组卷积的概念,组数为2的分组卷积相当于各自的卷积进行融合操作。
  3. 使用分组卷积可以将两组卷积看作是两个独立的运算结构(理解为并行的来进行运算。)

在这里插入图片描述

将3x3 2c 2c 2 = 3x3 c c + 3x3 c c的形式可以理解为红色部分的结构extend出一份绿色的结构。这种思想也是E-ELAN模块的构造思想

在这里插入图片描述
论文中的结构就可以等价为这种并行的ELAN结构。

这个结构只在YOLO v7e6e的配置文件中被使用到了

   [-1, 1, Conv, [64, 1, 1]],
   [-2, 1, Conv, [64, 1, 1]],
   [-1, 1, Conv, [64, 3, 1]],
   [-1, 1, Conv, [64, 3, 1]],
   [-1, 1, Conv, [64, 3, 1]],
   [-1, 1, Conv, [64, 3, 1]],
   [-1, 1, Conv, [64, 3, 1]],
   [-1, 1, Conv, [64, 3, 1]],
   [[-1, -3, -5, -7, -8], 1, Concat, [1]],
   [-1, 1, Conv, [160, 1, 1]],  # 12
   [-11, 1, Conv, [64, 1, 1]],
   [-12, 1, Conv, [64, 1, 1]],
   [-1, 1, Conv, [64, 3, 1]],
   [-1, 1, Conv, [64, 3, 1]],
   [-1, 1, Conv, [64, 3, 1]],
   [-1, 1, Conv, [64, 3, 1]],
   [-1, 1, Conv, [64, 3, 1]],
   [-1, 1, Conv, [64, 3, 1]],
   [[-1, -3, -5, -7, -8], 1, Concat, [1]],
   [-1, 1, Conv, [160, 1, 1]],  # 22
   [[-1, -11], 1, Shortcut, [1]],  # 23

这个结构和ELAN模块的并行有一定的差异,主要体现的是另外的一个创新点——模型缩放的概念产生的ELAN+的结构,之后进行说明。

Shortcut的区别是执行的是一个按元素位置相加的一个操作步骤。

class Shortcut(nn.Module):
    def __init__(self, dimension=0):
        super(Shortcut, self).__init__()
        self.d = dimension

    def forward(self, x):
        return x[0]+x[1]

MP1模块

将Yolov7.yaml中的12-16层这一经常出现的结构我们定义为MP1结构。
经过Mp1结构后通道数不变而尺寸减半了可以看作一个复杂的MaxPooling操作,出现在yolov7的前面的位置,我们定义为MP1模块

   [-1, 1, MP, []], #mp1
   [-1, 1, Conv, [128, 1, 1]],
   [-3, 1, Conv, [128, 1, 1]],
   [-1, 1, Conv, [128, 3, 2]],
   [[-1, -3], 1, Concat, [1]],  # 16-P3/8  

在这里插入图片描述

SPPCSPC模块

之前的模块CBS模块,ELAN模块,和MP1模块经过组合就可以构成yolov7的主干提取网络。

在neck部分将之前在v5中使用的SPPF模块进一步进行改进,改为了SPPCSP模块

class SPPCSPC(nn.Module):
    # CSP https://github.com/WongKinYiu/CrossStagePartialNetworks
    def __init__(self, c1, c2, n=1, shortcut=False, g=1, e=0.5, k=(5, 9, 13)):
        super(SPPCSPC, self).__init__()
        c_ = int(2 * c2 * e)  # hidden channels
        self.cv1 = Conv(c1, c_, 1, 1)
        self.cv2 = Conv(c1, c_, 1, 1)
        self.cv3 = Conv(c_, c_, 3, 1)
        self.cv4 = Conv(c_, c_, 1, 1)
        # 存放 5x5 9x9 13x13的三个mp模块
        self.m = nn.ModuleList([nn.MaxPool2d(kernel_size=x, stride=1, padding=x // 2) for x in k])
        self.cv5 = Conv(4 * c_, c_, 1, 1)
        self.cv6 = Conv(c_, c_, 3, 1)
        self.cv7 = Conv(2 * c_, c2, 1, 1)

    def forward(self, x):
        x1 = self.cv4(self.cv3(self.cv1(x)))
        y1 = self.cv6(self.cv5(torch.cat([x1] + [m(x1) for m in self.m], 1)))
        y2 = self.cv2(x)
        return self.cv7(torch.cat((y1, y2), dim=1))

我们根据源码绘制出SPPCSPC的网络结构图如下所示(输入特征图为20x20x1024

在这里插入图片描述

ELAN’模块

在head部分对ELAN模块进行模型变形处理得到了,ELAN’模块对应yolov7配置文件中的56到63层的信息

其yaml配置文件如下所示

   [-1, 1, Conv, [256, 1, 1]], #56 ELAN'
   [-2, 1, Conv, [256, 1, 1]],
   [-1, 1, Conv, [128, 3, 1]],
   [-1, 1, Conv, [128, 3, 1]],
   [-1, 1, Conv, [128, 3, 1]],
   [-1, 1, Conv, [128, 3, 1]],
   [[-1, -2, -3, -4, -5, -6], 1, Concat, [1]],
   [-1, 1, Conv, [256, 1, 1]], # 63 ELAN'

之前的4个卷积组成了2个分路ELAN’可以看作是ELAN的变形,即4个卷积组成了4个分路(V7中的56-63层输入为40x40x512的输入)

在这里插入图片描述

MP2模块

mp2的模块结构其实可以不用单独的进行介绍,与mp1唯一的不同的地方就在于对了一个来自63层的连接输入Concat。

其实本质上和v5一样在head网络部分使用到了PAN这种整体的结构来进行构建。

   [-1, 1, MP, []], #76 mp2
   [-1, 1, Conv, [128, 1, 1]],
   [-3, 1, Conv, [128, 1, 1]],
   [-1, 1, Conv, [128, 3, 2]],
   [[-1, -3, 63], 1, Concat, [1]], #80 mp2

在这里插入图片描述

Repconv模块

重参数卷积模块(在部署和推理的时候使用不同的结构进行)

在这里插入图片描述

class RepConv(nn.Module):
    # Represented convolution
    # https://arxiv.org/abs/2101.03697

    def __init__(self, c1, c2, k=3, s=1, p=None, g=1, act=True, deploy=False):
        super(RepConv, self).__init__()

        self.deploy = deploy
        self.groups = g
        self.in_channels = c1
        self.out_channels = c2

        assert k == 3
        assert autopad(k, p) == 1

        padding_11 = autopad(k, p) - k // 2

        self.act = nn.SiLU() if act is True else (act if isinstance(act, nn.Module) else nn.Identity())

        if deploy:
            self.rbr_reparam = nn.Conv2d(c1, c2, k, s, autopad(k, p), groups=g, bias=True)

        else:
            self.rbr_identity = (nn.BatchNorm2d(num_features=c1) if c2 == c1 and s == 1 else None)

            self.rbr_dense = nn.Sequential(
                nn.Conv2d(c1, c2, k, s, autopad(k, p), groups=g, bias=False),
                nn.BatchNorm2d(num_features=c2),
            )

            self.rbr_1x1 = nn.Sequential(
                nn.Conv2d( c1, c2, 1, s, padding_11, groups=g, bias=False),
                nn.BatchNorm2d(num_features=c2),
            )

基于拼接的模型缩放处理

3.2 Model scaling for concatenation-based models

因此论文的作者提出并使用了第二个在网络模型上的创新点,一种复合的模型缩放方法

when performing width and depth scaling, and used this to design the corresponding model scaling method.

能够同时改变模型的高度和宽度。

首先需要说明和引入的概念是yolov7x.yaml是在yolov7模型的基础上进行一个复合的模型缩放。(缩放倍数为1.25倍)即倍数因子为1.25

缩放后的模块即为ELAN+模块在网络模块中对其进行介绍。

在这里插入图片描述

YLOLV7X

  • YOLOV7X是在yolov7的基础上进行缩放得到的缩放的倍数即为1.25
  • 将ELAN模块替换为了ELAN+模块使得整个模型变得更宽
  • 模型的输入和输出的通道数都变为了原来的1.25倍。

ELAN+模块

YOLOV7X中的4层到第13层。
在这里插入图片描述

   [-1, 1, Conv, [64, 1, 1]], #ELAN+
   [-2, 1, Conv, [64, 1, 1]],
   [-1, 1, Conv, [64, 3, 1]],
   [-1, 1, Conv, [64, 3, 1]],
   [-1, 1, Conv, [64, 3, 1]],
   [-1, 1, Conv, [64, 3, 1]],
   [-1, 1, Conv, [64, 3, 1]],
   [-1, 1, Conv, [64, 3, 1]],
   [[-1, -3, -5, -7, -8], 1, Concat, [1]],
   [-1, 1, Conv, [320, 1, 1]],  # 13

之后涉及到的模型缩放的概念和这种思想保持一致

计划的重参数卷积

4.1. Planned re-parameterized convolution

将重参数卷积应用到残差模块中去,或者是基于拼接的模块中去。Repconv在训练时使用复杂的模型进行训练,在推理时进行重参数化使用简单的模型来进行推理。

虽然 RepConv [13] 在 VGG 上取得了优异的性能,但当我们直接将其应用于 ResNet 和 DenseNet 等架构时,其准确率会显着降低。 我们使用梯度流传播路径来分析重新参数化的卷积应该如何与不同的网络相结合。我们还相应地设计了计划的重新参数化卷积。

在这里插入图片描述
RepConv 实际上将 3×3 卷积、1×1 卷积和恒等连接组合在一个卷积层中。 在分析了 RepConv 和不同架构的组合和对应性能后,我们发现 RepConv 中的恒等连接破坏了 ResNet 中的残差和 DenseNet 中的连接,为不同的特征图提供了更多的梯度多样性。 基于以上原因,我们使用无身份连接的 RepConv (RepConvN) 来设计计划重参数化卷积的架构。 在我们的想法中,当一个带有残差或连接的卷积层被重新参数化的卷积代替时,应该没有恒等连接。

在这里插入图片描述
RepVGG是采用了VGG风格进行搭建的,采用了重参数化技术,因此叫RepVGG。
在这里插入图片描述

标签分配方法

深度监督

深度监督 [38] 是一种经常用于训练深度网络的技术。 它的主要概念是在网络的中间层添加额外的辅助头,以辅助损失为指导的浅层网络权重。 即使对于 ResNet [26] 和 DenseNet [32] 等通常收敛良好的架构,深度监督 [70, 98, 67, 47, 82, 65, 86, 50] 仍然可以显着提高模型在许多任务上的性能 . 图 5 (a) 和 (b) 分别显示了“没有”和“有”深度监督的目标检测器架构。 在本文中,我们将负责最终输出的head称为lead head,用于辅助训练的head称为辅助head。

在这里插入图片描述

总结:深度监督是指在模型训练的过程中,除了最终的检测头之外,在中间的网络层引入辅助头来参与损失函数的计算并协助更新参数的方法。

标签分配

过去,在深度网络的训练中,标签分配通常直接参考GT,并根据给定的规则生成hard label

本文方法

作者提出一个“label assigner(标签分配器)” 机制,该机制将网络预测结果与GT一起考虑,然后分配soft label

关于hard label和soft label:

hard label:有些论文中也称为hard target ,其实这也是借鉴了知识蒸馏的思想,hard字面意思上就可以看出比较强硬,是就是,不是就是不是,标签形式:(1,2,3…)或(0,1,0,0…)
soft label:soft是以概率的形式来表示。可理解为对标签的平滑也即软化,比如像[0.6,0.4]
现在比较流行的结构中,经常会将网络输出的数据分布通过一定的优化方法等与GT进行匹配生成soft label(其实我们熟悉的经过softmax的或者sigmod输出就是一种soft label

独立标签匹配

在论文提出的两种新的标签分配策略之前提出的结构

这是独立标签匹配结构,将Auxiliary head和Lead head分离,然后使用它们自己的预测结果和真实标签来进行标签分配。

在这里插入图片描述

先导头导向标签分配器

Lead head guided label assigner

主要基于Lead head的预测结果和GT来计算,并通过优化过程生成soft label 。这组soft label 将用作Auxiliary head和Lead head的训练。

原因:

  • Lead head 的学习能力更强一些,所以从它当中得到的soft label在数据集的数据概率中更具有代表性。
  • Lead head 能够只学习 Auxiliary head 没有学习到的特征。

在这里插入图片描述

由粗到精的 lead head 指导标签分配器

(Coarse-to-fine lead head guided label assigner)由粗至细的lead head引导标签分配器

在这个过程中生成了两组不同的soft label,即粗标签和细标签

  • 细标签与Lead head 在标签分配器上生成的soft label相同
  • 粗标签是通过放宽认定positive target的条件生成的,也就是允许更多的grids作为positive target

首先是细标签,网络最终输出的三个head是Lead head,会将这部分的预测结果与ground truth生成soft label,网络会觉得这个soft label得到是数据分布更接近真实的数据分布,训练得到的内容更加“细致”
再来说说粗标签,Auxiliary head由于是从中间网络部分得到的,它的预测效果肯定是没有深层网络Lead head提取到的数据或者特征更细致,所以Auxiliary head部分的内容是比较“粗糙”的,在训练过程中,会将Lead head与ground truth的soft label当成一个全新的ground truth,然后与Auxiliary head之间建立损失函数,说白了,就是让辅助head的预测结果也“近似”为Lead head

在这里插入图片描述

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

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

相关文章

南方健康2024米思会:科普患教赋能医药增长闭环,千亿蓝海市场大爆发!

2024年6月25日-28日,在中国•南太湖举办的2024米思会如约而至,顺利落下帷幕,本次大会以“韧进启新局”为主题,以不懈进取的“韧劲”,立身破局,迎变启新。通过4天3夜的思想碰撞和互动交流,引领行…

使用shell脚本实现DM8开机自动启动

编写shell脚本 #!/bin/bashsu -dmdba >>EOF cd /home/dmdba/dmdbms/bin ./DmServiceDMTEST start echo "dm start ... " EOF注意:DmServiceDMTEST每个服务器设置的不一样,根据实际进行更换 授权脚本可执行权限 chmod -x /dmdata/dmse…

策略为王股票软件源代码-----如何修改为自己软件61----资讯菜单修改-----举例---------调用同花顺网页------

http://stock.sina.com.cn 将原来的新浪行情,修改为同花顺, 搜索 stock.sina.com.cn... StkUI\View\InfoView.cpp(58):char

【C++:默认成员函数初始化列表】

构造函数 特点 没有返回值支持函数重载对象实例化时,编译器自动调用作用不是构造,而是初始化函数名与类名相同无参函数和全缺省的函数,不用传参就能调用的函数叫做默认构造函数 构造函数是一个特殊的成员函数 注:无参构造函数在实…

Lock4j简单的支持不同方案的高性能分布式锁实现及源码解析

文章目录 1.Lock4j是什么?1.1简介1.2项目地址1.3 我之前手写的分布式锁和限流的实现 2.特性3.如何使用3.1引入相关依赖3.2 配置redis或zookeeper3.3 使用方式3.3.1 注解式自动式3.3.2 手动式 4.源码解析4.1项目目录4.2实现思路 5.总结 1.Lock4j是什么? 1.1简介 lock4j是苞米…

平均102天 Accept的国产医学顶刊,影响因子4连涨,还免版面费!

《Asian Journal of Pharmaceutical Sciences》 (亚洲药物制剂科学) 是由沈阳药科大学主办、Elsevier合作出版的全英文药剂学学术期刊,是“中国科技期刊卓越行动计划”资助期刊,现已被SCIE、PubMed Central、Scopus和DOAJ等国际著名检索系统收录&#xf…

【已解决】“import ... =“ 只能在 TypeScript 文件中使用

现象 在使用 import 语法的时候,代码报红,提示:“import ... “ 只能在 TypeScript 文件中使用 原因 代码被 VSCode 解析成 TypeScript 语法 解决方案: 关闭 JavaScript 的验证启用即可。 mac 快捷方式:comman s…

25.【C语言】循环结构之for 上

1.基本使用 类比while 在while循环中&#xff0c;有三个不可或缺的部分&#xff1a;初始化&#xff0c;判断部分&#xff0c;调整部分 int i 0;//初始化 while (i < 10)//判断部分 {……i;//调整部分 }三个部分太分散&#xff0c;用for循环可集为一体&#xff0c;简洁 …

【海贼王的数据航海】ST表——RMQ问题

目录 1 -> RMQ问题 1.1 -> 定义 1.2 -> 解决策略 2 -> ST表 2.1 -> 定义 2.2 什么是可重复贡献问题 2.3 -> 预处理ST表 2.4 -> 处理查询 2.5 -> 实际问题 1 -> RMQ问题 1.1 -> 定义 RMQ (Range Minimum/Maximum Query)即区间最值查询…

印度第二大移动提供商 3.75 亿数据待售

一个名为“xenZen”的威胁行为者已在 BreachForums 上出售 Airtel 的数据库。 该列表包含来自 3.75 亿客户的数据。 数据详情&#xff1a; 手机号码 名 出生日期 父亲的名字 地址 电子邮件ID 类型 国籍 阿达尔 带照片的身份证明详细信息 地址详细信息证明等 鉴于…

【反悔堆 优先队列 临项交换 决策包容性】630. 课程表 III

本文涉及知识点 贪心 反悔堆 优先队列 临项交换 Leetcode630. 课程表 III 这里有 n 门不同的在线课程&#xff0c;按从 1 到 n 编号。给你一个数组 courses &#xff0c;其中 courses[i] [durationi, lastDayi] 表示第 i 门课将会 持续 上 durationi 天课&#xff0c;并且必…

应用信息查看器更新至1.5.0

https://download.csdn.net/download/zzmzzff/89518318

构建滑块组件_第 1 部分

前言 ● 本次将和大家一起学习实现滑块的功能 ● 由于这有些错乱&#xff0c;我们将用图片来代替&#xff0c;以实现功能 ● 这里我们简单的说一下原理&#xff0c;如下图所示&#xff0c;通过改变tanslateX的值来达到滑动的效果&#xff0c;所以最核心的就是我们需要通过…

ODOO17的邮件机制-系统自动推送修改密码的邮件

用户收到被要求重置密码的邮件&#xff1a; 我们来分析一下ODOO此邮件的工作机制&#xff1a; 1、邮件模板定义 2、渲染模板的函数&#xff1a; 3、调用此函数的机制&#xff1a; 当用户移除或增加了信任的设备&#xff08;如电脑、手机端等&#xff09;&#xff0c;系统会自…

银河麒麟V10 SP1 审计工具 auditd更新

前言 银河麒麟V10 SP1 审计工具 auditd 引发的内存占用过高&#xff0c; 内存使用率一直在 60% 以上&#xff0c; 内存一直不释放 排查 可以使用ps或者top查看系统进程使用情况 ps -aux|sort -k4nr|head -n 5 发现银河麒麟审计工具 auditd 一直占用内存不释放 解决 办法一…

GD32MCU如何实现掉电数据保存?

大家在GD32 MCU应用时&#xff0c;是否会碰到以下应用需求&#xff1a;希望在MCU掉电时保存一定的数据或标志&#xff0c;用以记录一些关键的数据。 以GD32E103为例&#xff0c;数据的存储介质可以选择内部Flash或者备份数据寄存器。 如下图所示&#xff0c;片内Flash具有10年…

如何使用uer做多分类任务

如何使用uer做多分类任务 语料集下载 找到这里点击即可 里面是这有json文件的 因此我们对此要做一些处理&#xff0c;将其转为tsv格式 # -*- coding: utf-8 -*- import json import csv import chardet# 检测文件编码 def detect_encoding(file_path):with open(file_path,…

OceanBase Meetup北京站|跨行业应用场景中的一体化分布式数据库:AI赋能下的探索与实践

随着业务规模的不断扩张和数据处理需求的日益复杂化&#xff0c;传统数据库架构逐渐暴露出业务稳定性波动、扩展性受限、处理效率降低以及运营成本高等一系列问题。众多行业及其业务场景纷纷踏上了数据库现代化升级之路。 为应对这些挑战&#xff0c;7月6日&#xff0c;OceanB…

在Linux环境下搭建Redis服务结合内网穿透实现通过GUI工具远程管理数据库

文章目录 前言1. 安装Docker步骤2. 使用docker拉取redis镜像3. 启动redis容器4. 本地连接测试4.1 安装redis图形化界面工具4.2 使用RDM连接测试 5. 公网远程访问本地redis5.1 内网穿透工具安装5.2 创建远程连接公网地址5.3 使用固定TCP地址远程访问 前言 本文主要介绍如何在Li…

1.Python学习笔记

一、环境配置 1.Python解释器 把程序员用编程语言编写的程序&#xff0c;翻译成计算机可以执行的机器语言 安装&#xff1a; 双击Python3.7.0-选择自定义安装【Customize installation】-勾选配置环境变量 如果没有勾选配置环境变量&#xff0c;输入python就会提示找不到命令…