YOLOv8改进 | Neck篇 | Slim-Neck替换特征融合层实现超级涨点 (又轻量又超级涨点)

一、本文介绍

本文给大家带来的改进机制是Slim-neck提出的Neck部分Slim-neck是一种设计用于优化卷积神经网络中neck部分的结构。在我们YOLOv8中,neck是连接主干网络(backbone)和头部网络(head)的部分,负责特征融合和处理,以便提高检测的准确性和效率。亲测在小目标检测和大尺度目标检测的数据集上都有大幅度的涨点效果(mAP直接涨了大概有0.4左右同时本文对Slim-Neck的框架原理进行了详细的分析,不光让大家会添加到自己的模型在写论文的时候也能够有一定的参照,最后本文会手把手教你添加Slim-Neck模块到网络结构中(值得一提的是这个Slim-neck还可以减少GFLOPs大概2修改完大概是8.0GFLOP所以非常适合轻量化的读者)。

 (这里分析一下打分原因,推荐指数和涨点效果都是4克星,首先推荐指数是因为这是2022年的结构所以减少一分,但是大家可以根据这个结构进行一定的改进,毕竟其中的模块还是可以直接使用的,涨点效果0.4map还可以打4星)

推荐指数:⭐⭐⭐⭐

涨点效果:⭐⭐⭐⭐⭐

专栏回顾:YOLOv8改进系列专栏——本专栏持续复习各种顶会内容——科研必备    

训练结果对比图->  

这次试验我用的数据集大概有七八百张照片训练了150个epochs,虽然没有完全拟合但是效果有很高的涨点幅度,所以大家可以进行尝试毕竟不同的数据集上效果也可能差很多,同时我在后面给了多种yaml文件大家可以分别进行实验来检验效果。

可以看到这个涨点幅度mAP直接涨了大概有0.4左右,这个涨幅还可以,毕竟属于小的改进,重要的是大家能够从其中总结出来思想,能否提出一个新的Neck部分,没准下一个顶会文章就是你了,哈哈。

目录

一、本文介绍

二、Slim-neck原理

2.1  Slim-neck的基本原理

2.2 GSConv的引入

2.3 模块元素

2.4 灵活性

三、 Slim-neck的完整代码

四、手把手教你添加Slim-neck模块 

4.1 修改一

4.2 步骤二

4.3 步骤三 

五、 Slim-neck的yaml文件

六、 训练截图

五、本文总结


二、Slim-neck原理

论文地址:官方论文地址

代码地址:官方代码地址


2.1  Slim-neck的基本原理

Slim-neck是一种设计用于优化卷积神经网络(CNN)中“neck”部分的结构。在目标检测器中,"neck"是连接CNN的主干网络(backbone)和头部网络(head)的部分,负责特征融合和处理,以便提高检测的准确性和效率。

我们可以将Slim-neck的基本原理分为以下几点:

1. GSConv的引入:GSConv是为了在卷积神经网络(CNN)中加快图像的预测计算。在传统的CNN中,空间信息逐渐转换成通道信息,而这一过程在每一次特征图空间压缩和通道扩张时都会导致语义信息的部分丢失。GSConv旨在在保持较低时间复杂度的同时,尽可能地保留通道之间的隐藏连接。

2. 模块元素:GSConv之后,研究者继续引入GS瓶颈(GS bottleneck)和跨阶段部分网络(GSCSP)模块VoV-GSCSP,这些模块设计用于进一步提升性能。在实际应用中,更简单的结构模块由于更易于硬件实现,更有可能被采用。

3. 灵活性:论文提出了需要灵活使用GSConv、GS瓶颈和VoV-GSCSP这四个模块。可以像搭乐高一样构建Slim-neck层。

下面我为大家展示应用于YOLOv5模型的Slim-neck架构。这种架构使用了GSConvVoV-GSCSP模块,以构建一个高效的神经网络“颈部”。在这个架构中,不同尺度的特征图(P3, P4, P5)首先通过GSConv模块处理,然后通过上采样(upsample)和拼接(Concat)操作与其他尺度的特征图结合。这样处理后的特征图再次通过GSConv模块,最后使用VoV-GSCSP模块来进一步提取和融合特征,以准备最终的检测头(head-1, head-2, head-3)进行目标检测。

通过这种模块化和分层的方法,Slim-neck架构能够在保持高准确度的同时减少计算复杂性和推理时间,这对于在自动驾驶车辆等计算资源受限的环境中的应用尤其重要。


2.2 GSConv的引入

GSConv的引入是为了解决在卷积神经网络(CNN)中预测计算的速度问题。在CNN的骨干网络(backbone)中,输入图像几乎总是经历一个类似的转换过程:空间信息逐步向通道传递。每一次特征图的空间(宽度和高度)压缩和通道扩张都会导致语义信息的部分丢失。通道密集型的卷积计算(SC)最大限度地保留了每个通道之间的隐含连接,而通道稀疏的卷积(DSC)则完全切断了这些连接。GSConv尽可能地保持这些连接,并且具有更低的时间复杂度。

上面提到的时间复杂度通常由浮点运算(FLOPs)来定义。因此,SC、DSC和GSConv的时间复杂度分别为:

- SC:O(W \cdot H \cdot K_1 \cdot K_2 \cdot C_1 \cdot C_2)
- DSC:O(W \cdot H \cdot K_1 \cdot K_2 \cdot C_1)
- GSConv:O([W \cdot H \cdot K_1 \cdot K_2 \cdot C_2] / 2 \cdot (C_1 + 1))

其中W是输出特征图的宽度,H是高度,K_1 \cdot K_2是卷积核的大小,C_{1}是每个卷积核的通道数,也是输入特征图的通道数,C_{2}是输出特征图的通道数。

下图为大家展示了GSConv模块的结构

1. 卷积层(Conv):输入特征图首先通过一个卷积层,该层的输出通道数为C2/2。

2. 深度可分离卷积层(DWConv):该层标记为蓝色,表示深度可分离卷积(DSC)操作。它对输入特征图的每个通道独立进行卷积。

3. 拼接(Concat):将Conv层和DWConv层的输出进行拼接。

4. 随机排列(Shuffle):拼接后的特征图经过一个shuffle操作,以重新排列特征通道,提高特征间的信息流动。

5. 输出:最终输出的特征图有C2个通道。

我将通过下图为大家清晰展示标准卷积(SC)和深度可分离卷积(DSC)的计算过程。标准卷积是通道密集型的计算,而深度可分离卷积是通道稀疏的计算。

上图强调了在传统的标准卷积和现代轻量级深度可分离卷积之间的差异,其中后者在保持足够精确度的同时,减少了计算的复杂性,这对于计算资源受限的环境尤其有益。这种方法通常用于移动和边缘设备的神经网络架构中,以提高运行效率。 


2.3 模块元素

模块元素是构成Slim-neck架构的基础部分,设计它们的目的是为了减少计算成本,同时保持或提高模型的学习能力。模块元素可以灵活使用,像搭积木一样组合成Slim-neck层,提供了构建高效深度学习模型的灵活性和效率

1. GSConv:是一种减少计算复杂性的轻量级卷积,它的计算成本约为标准卷积(SC)的一半,但在模型的学习能力方面与SC相当。

2. GS bottleneck:基于GSConv,这是一种增强模块,用于提高特征的非线性表达和信息的复用。

3. VoV-GSCSP:利用一次性聚合方法设计的跨阶段部分网络模块,用于在不同阶段的特征图之间进行有效的信息融合。

下图显示了GS bottleneck模块VoV-GSCSP模块的结构:

(a) GS bottleneck模块,其中包含GSConv模块的一个或多个实例。 (b), (c), (d) 分别展示了不同设计方案的VoV-GSCSP模块。

GS bottleneck模块是为了进一步增强网络处理特征的能力,通过GSConv模块的堆叠来提高模型的学习能力。而VoV-GSCSP模块是利用不同的结构设计方案,以提高特征利用效率和网络性能。这些模块设计是Slim-neck理念的体现,旨在减少计算复杂性和推理时间,同时保持准确性。通过这样的模块化设计,可以根据需要灵活地构建出适合特定任务的网络架构。


2.4 灵活性

灵活性是指使用四种模块:GSConv、GS bottleneck和VoV-GSCSP,以及能够根据需要构建Slim-neck层的能力,类似于搭建乐高积木一样。这种灵活性允许研究者和工程师根据不同的需求和应用场景,调整和优化网络结构,从而实现特定目标的高效性和准确性。


三、 Slim-neck的完整代码

复制下面的代码在'ultralytics/nn/modules'目录下新建一个py文件粘贴进去,我这里的名字是Slimneck(大家注意不要带-否则会找不到文件的!!!)其它的具体使用 方式看章节四。

import torch
import torch.nn as nn
import math


def autopad(k, p=None):  # kernel, padding
    # Pad to 'same'
    if p is None:
        p = k // 2 if isinstance(k, int) else [x // 2 for x in k]  # auto-pad
    return p


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().__init__()
        self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p), groups=g, bias=False)
        self.bn = nn.BatchNorm2d(c2)
        self.act = nn.Mish() if act else nn.Identity()

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

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


class GSConv(nn.Module):
    # GSConv https://github.com/AlanLi1997/slim-neck-by-gsconv
    def __init__(self, c1, c2, k=1, s=1, g=1, act=True):
        super().__init__()
        c_ = c2 // 2
        self.cv1 = Conv(c1, c_, k, s, None, g, act)
        self.cv2 = Conv(c_, c_, 5, 1, None, c_, act)

    def forward(self, x):
        x1 = self.cv1(x)
        x2 = torch.cat((x1, self.cv2(x1)), 1)
        b, n, h, w = x2.data.size()
        b_n = b * n // 2
        y = x2.reshape(b_n, 2, h * w)
        y = y.permute(1, 0, 2)
        y = y.reshape(2, -1, n // 2, h, w)

        return torch.cat((y[0], y[1]), 1)


class GSConvns(GSConv):
    # GSConv with a normative-shuffle https://github.com/AlanLi1997/slim-neck-by-gsconv
    def __init__(self, c1, c2, k=1, s=1, g=1, act=True):
        super().__init__(c1, c2, k=1, s=1, g=1, act=True)
        c_ = c2 // 2
        self.shuf = nn.Conv2d(c_ * 2, c2, 1, 1, 0, bias=False)

    def forward(self, x):
        x1 = self.cv1(x)
        x2 = torch.cat((x1, self.cv2(x1)), 1)
        # normative-shuffle, TRT supported
        return nn.ReLU(self.shuf(x2))


class GSBottleneck(nn.Module):
    # GS Bottleneck https://github.com/AlanLi1997/slim-neck-by-gsconv
    def __init__(self, c1, c2, k=3, s=1, e=0.5):
        super().__init__()
        c_ = int(c2*e)
        # for lighting
        self.conv_lighting = nn.Sequential(
            GSConv(c1, c_, 1, 1),
            GSConv(c_, c2, 3, 1, act=False))
        self.shortcut = Conv(c1, c2, 1, 1, act=False)

    def forward(self, x):
        return self.conv_lighting(x) + self.shortcut(x)


class DWConv(Conv):
    # Depth-wise convolution class
    def __init__(self, c1, c2, k=1, s=1, act=True):  # ch_in, ch_out, kernel, stride, padding, groups
        super().__init__(c1, c2, k, s, g=math.gcd(c1, c2), act=act)


class GSBottleneckC(GSBottleneck):
    # cheap GS Bottleneck https://github.com/AlanLi1997/slim-neck-by-gsconv
    def __init__(self, c1, c2, k=3, s=1):
        super().__init__(c1, c2, k, s)
        self.shortcut = DWConv(c1, c2, k, s, act=False)


class VoVGSCSP(nn.Module):
    # VoVGSCSP module with GSBottleneck
    def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5):
        super().__init__()
        c_ = int(c2 * e)  # hidden channels
        self.cv1 = Conv(c1, c_, 1, 1)
        self.cv2 = Conv(c1, c_, 1, 1)
        self.gsb = nn.Sequential(*(GSBottleneck(c_, c_, e=1.0) for _ in range(n)))
        self.res = Conv(c_, c_, 3, 1, act=False)
        self.cv3 = Conv(2 * c_, c2, 1)  #

    def forward(self, x):
        x1 = self.gsb(self.cv1(x))
        y = self.cv2(x)
        return self.cv3(torch.cat((y, x1), dim=1))


class VoVGSCSPC(VoVGSCSP):
    # cheap VoVGSCSP module with GSBottleneck
    def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5):
        super().__init__(c1, c2)
        c_ = int(c2 * 0.5)  # hidden channels
        self.gsb = GSBottleneckC(c_, c_, 1, 1)

 


四、手把手教你添加Slim-neck模块 

 


4.1 修改一

我们上面的代码复制粘贴到'ultralytics/nn/modules'目录下新建一个py文件粘贴进去,我这里的名字是Slimneck(大家注意不要带-否则会找不到文件的!!!)

 


4.2 步骤二

之后我们找到'ultralytics/nn/tasks.py'文件,在其中注册我们的slim-neck模块。

(这里需要注意的是我们用的是slim-neck中的VOVSCSP和GSConv模块)

首先我们需要在文件的开头导入我们的slim-neck中的VOVSCSP和GSConv模块,如下图所示->

 


4.3 步骤三 

我们找到如下代码,按照我的进行添加即可。

到此就可以了,完成了注册然后只需要修改yaml文件就可以进行训练了~

 


五、 Slim-neck的yaml文件

我这里和官方的yaml文件给的一样,但是官方给的是yolov5的我进行了一定的转换,换成了YOLO

v8的。

# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect

# Parameters
nc: 80  # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
  # [depth, width, max_channels]
  n: [0.33, 0.25, 1024]  # YOLOv8n summary: 225 layers,  3157200 parameters,  3157184 gradients,   8.9 GFLOPs
  s: [0.33, 0.50, 1024]  # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients,  28.8 GFLOPs
  m: [0.67, 0.75, 768]   # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients,  79.3 GFLOPs
  l: [1.00, 1.00, 512]   # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
  x: [1.00, 1.25, 512]   # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs

# YOLOv8.0n backbone
backbone:
  # [from, repeats, module, args]
  - [-1, 1, Conv, [64, 3, 2]]  # 0-P1/2
  - [-1, 1, Conv, [128, 3, 2]]  # 1-P2/4
  - [-1, 3, C2f, [128, True]]
  - [-1, 1, Conv, [256, 3, 2]]  # 3-P3/8
  - [-1, 6, C2f, [256, True]]
  - [-1, 1, Conv, [512, 3, 2]]  # 5-P4/16
  - [-1, 6, C2f, [512, True]]
  - [-1, 1, Conv, [1024, 3, 2]]  # 7-P5/32
  - [-1, 3, C2f, [1024, True]]
  - [-1, 1, SPPF, [1024, 5]]  # 9

# YOLOv8.0n head
head:
# slim-neck
  - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
  - [[-1, 6], 1, Concat, [1]]  # cat backbone P4
  - [-1, 3, VoVGSCSP, [512]]  # 12

  - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
  - [[-1, 4], 1, Concat, [1]]  # cat backbone P3
  - [-1, 3, VoVGSCSP, [256]]  # 15 (P3/8-small)

  - [-1, 1, GSConv, [256, 3, 2]]
  - [[-1, 12], 1, Concat, [1]]  # cat head P4
  - [-1, 3, VoVGSCSP, [512]]  # 18 (P4/16-medium)

  - [-1, 1, GSConv, [512, 3, 2]]
  - [[-1, 9], 1, Concat, [1]]  # cat head P5
  - [-1, 3, VoVGSCSP, [1024]]  # 21 (P5/32-large)

  - [[15, 18, 21], 1, Detect, [nc]]  # Detect(P3, P4, P5)

六、 训练截图

下面是训练成功的截图,证明这个模块的改进是没有毛病的~同时如果你用我的模块成功了,还是希望大家来给我的文章点赞和评论支持一下,这样我也好发更多的模块,而且我YOLOv8系列马上就停更了,我可能要去更v5了,之后文章如果大家有需要才会更新了,因为感觉v5看的人更多一些。

 


五、本文总结

到此本文的正式分享内容就结束了,在这里给大家推荐我的YOLOv8改进有效涨点专栏,本专栏目前为新开的平均质量分98分,后期我会根据各种最新的前沿顶会进行论文复现,也会对一些老的改进机制进行补充,目前本专栏免费阅读(暂时,大家尽早关注不迷路~)如果大家觉得本文帮助到你了,订阅本专栏,关注后续更多的更新~

专栏回顾:YOLOv8改进系列专栏——本专栏持续复习各种顶会内容——科研必备

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

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

相关文章

Tair(2):Tair安装部署

1 安装相关依赖库 yum install -y gcc gcc-c make m4 libtool boost-devel zlib-devel openssl-devel libcurl-devel yum:是yellowdog updater modified 的缩写,Linux中的包管理工具gcc:一开始称为GNU C Compiler,也就是一个C编…

本地如何使用PHP搭建简单Imagewheel云图床,结合内网穿透实现在外远程访问?

文章目录 1.前言2. Imagewheel网站搭建2.1. Imagewheel下载和安装2.2. Imagewheel网页测试2.3.cpolar的安装和注册 3.本地网页发布3.1.Cpolar临时数据隧道3.2.Cpolar稳定隧道(云端设置)3.3.Cpolar稳定隧道(本地设置) 4.公网访问测…

vue3使用Mars3D写区块地图

效果图 引入相关文件 因为我也是第一次使用&#xff0c;所以我是把插件和源文件都引入了&#xff0c;能使用启动 源文件 下载地址&#xff1a; http://mars3d.cn/download.html 放入位置 在index.html中引入 <!--引入cesium基础lib--><link href"/static/C…

Stable diffusion 简介

Stable diffusion 是 CompVis、Stability AI、LAION、Runway 等公司研发的一个文生图模型&#xff0c;将 AI 图像生成提高到了全新高度&#xff0c;其效果和影响不亚于 Open AI 发布 ChatGPT。Stable diffusion 没有单独发布论文&#xff0c;而是基于 CVPR 2022 Oral —— 潜扩…

爆肝整理,Java接口自动化测试实战-rest-assured(详细总结)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、关于rest-assu…

聊个开心的敏捷话题——40小时工作制

近年来&#xff0c;加班现象在很多行业已经普遍制度化&#xff0c;甚至“996”已成为一些行业标签。企业高强度的压榨让员工不堪重负&#xff0c;且时常由此引发的各种悲剧也并不鲜见。 所以&#xff0c;今天我们一起来聊一个开心轻松的话题——极限编程的40h工作制原则。 40…

本科毕业论文查重率高吗【一文读懂】

大家好&#xff0c;今天来聊聊本科毕业论文查重率高吗&#xff0c;希望能给大家提供一点参考。 以下是针对论文重复率高的情况&#xff0c;提供一些修改建议和技巧&#xff1a; 本科毕业论文查重率高吗&#xff1f;重要性与应对策略 摘要&#xff1a;对于本科毕业生来说&#…

PyQt6 QDateEdit日期控件

​锋哥原创的PyQt6视频教程&#xff1a; 2024版 PyQt6 Python桌面开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili2024版 PyQt6 Python桌面开发 视频教程(无废话版) 玩命更新中~共计39条视频&#xff0c;包括&#xff1a;2024版 PyQt6 Python桌面开发 视频教程(无废话…

java--正则表达式书写规则

1.正在表达式 ①就是由一些特定的字符组成&#xff0c;代表的是一个规则。 ②作用一&#xff1a;用来校验数据格式是否合法。 ③作用二&#xff1a;在一段文本中查找满足要求的内容 2.String提供了一个匹配正则表达式的方法 3.正则表达式的书写规则

Uniapp安卓原生插件开发Demo

文章目录 前言一、安装开发工具二、导入uni插件原生项目三、开发Module四、开发Component五、合并原生代码到uniapp项目中总结 前言 当HBuilderX中提供的能力无法满足App功能需求&#xff0c;需要通过使用Andorid/iOS原生开发实现时&#xff0c;可使用App离线SDK开发原生插件来…

第二十一章,网络通信

网络协议 IP协议 IP是Internet Protocol的简称&#xff0c;是一种网络协议。Internet 网络采用的协议是TCP/IP协议&#xff0c;其全称是Transmission Control Protocol/Internet Protocol。Internet 依靠TCP/IP协议&#xff0c;在全球范围内实现了不同硬件结构、不同操作系统…

排序算法之三:希尔排序

希尔排序基本思想 希尔排序法又称缩小增量法 希尔排序法的基本思想是&#xff1a;先选定一个整数&#xff0c;把待排序文件中所有记录分成个组&#xff0c;所有距离为的记录分在同一组内&#xff0c;并对每一组内的记录进行排序。然后&#xff0c;取&#xff0c;重复上述分组…

Vue3+ElementPlus:icon图标不显示(给表格字段里添加图标)

一、背景 在Vue3项目中&#xff0c;想在表格的字段中引入图标因为给字段做了触发提示&#xff0c;希望用户能够注意到这个功能&#xff0c;因此想加个图标提示一下用户&#xff0c;效果如下&#xff1a; 触发提示效果如下&#xff1a; &#xff08;样式这里就不进行优化了&am…

【VS Code开发】使用Live Server搭建MENJA小游戏并发布至公网远程访问

文章目录 前言1. 编写MENJA小游戏2. 安装cpolar内网穿透3. 配置MENJA小游戏公网访问地址4. 实现公网访问MENJA小游戏5. 固定MENJA小游戏公网地址 前言 本篇教程&#xff0c;我们将通过VS Code实现远程开发MENJA小游戏&#xff0c;并通过cpolar内网穿透发布到公网&#xff0c;分…

【nodejs升级版本】win10 nodejs版本低升级版本流程

首先 网上说的n模块不支持window系统&#xff01;&#xff01;&#xff01; window系统升级node只能到node官网下载window安装包来覆盖之前的node 升级步骤如下&#xff1a; 1&#xff0c;找到你node的安装路径&#xff0c;不知道的可以cmd命令行中输入这个命令就可以看到了…

Python:核心知识点整理大全13-笔记

目录 6.4.3 在字典中存储字典 6.5 小结 第7章 用户输入和while循环 7.1 函数 input()的工作原理 7.1.1 编写清晰的程序 7.1.2 使用 int()来获取数值输入 7.1.3 求模运算符 7.1.4 在 Python 2.7 中获取输入 7.2 while 循环简介 7.2.1 使用 while 循环 往期快速传送门…

jsonpath:使用Python处理JSON数据

使用Python处理JSON数据 25.1 JSON简介 25.1.1 什么是JSON JSON全称为JavaScript Object Notation&#xff0c;一般翻译为JS标记&#xff0c;是一种轻量级的数据交换格式。是基于ECMAScript的一个子集&#xff0c;采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清…

中国教师未来发展趋势

随着科技的进步和社会的发展&#xff0c;教师的发展趋势尤其引人关注。那么&#xff0c;教师未来的发展趋势又将是什么呢&#xff1f;” 引领未来的教育变革 在快速发展的信息化社会&#xff0c;教育行业正经历着前所未有的变革。中国教师将扮演着引领这场变革的重要角色。未来…

教培管理系统源码 培训管理系统源码

教培管理系统源码 培训管理系统源码 使用教培管理系统可以带来哪些好处&#xff1a; 1. 提高管理效率&#xff1a;教培管理系统可以自动化处理许多管理任务&#xff0c;如学生信息管理、课程管理、成绩管理等&#xff0c;从而减少人工干预&#xff0c;提高管理效率。 2. 提…

Nodejs后端+express框架

前言 基于vue3Node后台管理项目&#xff0c;补充nodejs和express相关知识。 文章目录 一&#xff0c;express 1.官网 Express - 基于 Node.js 平台的 web 应用开发框架 - Express中文文档 | Express中文网 2.安装 npm install express --save 二、MongoDB 特点 非关…