当前位置: 首页 > news >正文

【AI系统】MobileFormer

MobileFormer

在本文中,将介绍一种新的网络-MobileFormer,它实现了 Transformer 全局特征与 CNN 局部特征的融合,在较低的成本内,创造一个高效的网络。通过本节,让大家去了解如何将 CNN 与 Transformer 更好的结合起来,同时实现模型的轻量化。

MobileFormer

MobileFormer:一种通过双线桥将 MobileNet 和 Transformer 并行的结构。这种方式融合了 MobileNet 局部性表达能力和 Transformer 全局表达能力的优点,这个桥能将局部性和全局性双向融合。和现有 Transformer 不同,Mobile-Former 使用很少的 tokens(例如 6 个或者更少)随机初始化学习全局先验,计算量更小。

并行结构

Mobile-Former 将 MobileNet 和 Transformer 并行化,并通过双向交叉注意力连接(下见图)。Mobile(指 MobileNet)采用图像作为输入( X ∈ R H W × 3 X\in R^{HW \times 3} XRHW×3),并应用反向瓶颈块提取局部特征。Former(指 Transformers)将可学习的参数(或 tokens)作为输入,表示为 Z ∈ R M × d Z\in R^{M\times d} ZRM×d,其中 M 和 d 分别是 tokens 的数量和维度,这些 tokens 随机初始化。与视觉 Transformer(ViT)不同,其中 tokens 将局部图像 patch 线性化,Former 的 tokens 明显较少(M≤6),每个代表图像的全局先验知识。这使得计算成本大大降低。

在这里插入图片描述

低成本双线桥

Mobile 和 Former 通过双线桥将局部和全局特征双向融合。这两个方向分别表示为 Mobile→Former 和 Mobile←Former。我们提出了一种轻量级的交叉注意力模型,其中映射( W Q W^{Q} WQ, W K W^{K} WK, W V W^{V} WV)从 Mobile 中移除,以节省计算,但在 Former 中保留。在通道数较少的 Mobile 瓶颈处计算交叉注意力。具体而言,从局部特征图 X 到全局 tokens Z 的轻量级交叉注意力计算如下:

A X − > Z = [ A t t n ( z i ~ W i Q , x i ~ , x i ~ ) ] i = 1 : h W o (1) A_{X->Z} = [Attn(\widetilde{z_{i}}W_{i}^{Q},\widetilde{x_{i}},\widetilde{x_{i}})]_{i=1:h}W^{o}\tag{1} AX>Z=[Attn(zi WiQ,xi ,xi )]i=1:hWo(1)

其中局部特征 X 和全局 tokens Z 被拆分进入 h 个头,即 X = [ x 1 ~ . . . x h ~ ] , Z = [ z 1 ~ . . . z h ~ ] X=[\widetilde{x_{1}}...\widetilde{x_{h}}],Z=[\widetilde{z_{1}}...\widetilde{z_{h}}] X=[x1 ...xh ],Z=[z1 ...zh ] 表示多头注意力。第 i 个头的拆分 z 1 ~ ∈ R M × d h \widetilde{z_{1}}\in R^{M \times \frac {d}{h} } z1 RM×hd 与第 i 个 token z 1 ~ ∈ R d \widetilde{z_{1}}\in R^{d} z1 Rd 不同。 W i Q W_{i}^{Q} WiQ 是第 i 个头的查询映射矩阵。 W O W^{O} WO 用于将多个头组合在一起。Attn(Q,K,V)是查询 Q、键 K 和值 V 的标准注意力函数,即:

s o f t m a x ( Q K T d k ) softmax(\frac{QK^{T}}{\sqrt{d_{k}}}) softmax(dk QKT)

其中 [ . ] 1 : h [.]_{1:h} [.]1:h 表示将 h 个元素 concat 到一起。需要注意的是,键和值的映射矩阵从 Mobile 中移除,而查询的映射矩阵 W i Q W_{i}^{Q} WiQ 在 Former 中保留。类似地从全局到局部的交叉注意力计算如下:

A Z − > X = [ A t t n ( x i ~ , z i ~ ⊙ W i K , z i ~ ⊙ W i V ) ] i = 1 : h (2) A_{Z->X} = [Attn(\widetilde{x_{i}},\widetilde{z_{i}}\odot W_{i}^{K},\widetilde{z_{i}}\odot W_{i}^{V})]_{i=1:h}\tag{2} AZ>X=[Attn(xi ,zi WiK,zi WiV)]i=1:h(2)

其中 W i K W_{i}^{K} WiK W i V W_{i}^{V} WiV 分别是 Former 中键和值的映射矩阵。而查询的映射矩阵从 Mobile 中移除。

Mobile-Former 块

Mobile-Former 由 Mobile-Former 块组成。每个块包含四部分:Mobile 子块、Former 子块以及双向交叉注意力 Mobile←Former 和 Mobile→Former(如下图所示)。

在这里插入图片描述

输入和输出:Mobile-Former 块有两个输入:(a) 局部特征图 X ∈ R H W × C X\in R^{HW\times C} XRHW×C,为 C 通道、高度 H 和宽度 W,以及(b) 全局 tokens Z ∈ R M × d Z\in R^{M\times d} ZRM×d,其中 M 和 d 是分别是 tokens 的数量和维度,M 和 d 在所有块中一样。Mobile-Former 块输出更新的局部特征图 X X X 和全局 tokens Z Z Z,用作下一个块的输入。

Mobile 子块:如上图所示,Mobile 子块将特征图 X X X 作为输入,并将其输出作为 Mobile←Former 的输入。这和反向瓶颈块略有不同,其用动态 ReLU 替换 ReLU 作为激活函数。不同于原始的动态 ReLU,在平均池化特征图上应用两个 MLP 以生成参数。我们从 Former 的第一个全局 tokens 的输出 z 1 ′ z'_{1} z1 应用两个 MLP 层(上图中的θ)保存平均池化。其中所有块的 depth-wise 卷积的核大小为 3×3。

class Mobile(nn.Module):def __init__(self, in_channel, expand_size, out_channel, token_demension, kernel_size=3, stride=1, k=2):super(Mobile, self).__init__()self.in_channel, self.expand_size, self.out_channel = in_channel, expand_size, out_channelself.token_demension, self.kernel_size, self.stride, self.k = token_demension, kernel_size, stride, kif stride == 2:self.strided_conv = nn.Sequential(nn.Conv2d(self.in_channel, self.expand_size, kernel_size=3, stride=2, padding=int(self.kernel_size // 2), groups=self.in_channel).cuda(),nn.BatchNorm2d(self.expand_size).cuda(),nn.ReLU6(inplace=True).cuda())self.conv1 = nn.Conv2d(self.expand_size, self.in_channel, kernel_size=1, stride=1).cuda()self.bn1 = nn.BatchNorm2d(self.in_channel).cuda()self.ac1 = DynamicReLU(self.in_channel, self.token_demension, k=self.k).cuda()      self.conv2 = nn.Conv2d(self.in_channel, self.expand_size, kernel_size=3, stride=1, padding=1, groups=self.in_channel).cuda()self.bn2 = nn.BatchNorm2d(self.expand_size).cuda()self.ac2 = DynamicReLU(self.expand_size, self.token_demension, k=self.k).cuda()          self.conv3 = nn.Conv2d(self.expand_size, self.out_channel, kernel_size=1, stride=1).cuda()self.bn3 = nn.BatchNorm2d(self.out_channel).cuda()else:self.conv1 = nn.Conv2d(self.in_channel, self.expand_size, kernel_size=1, stride=1).cuda()self.bn1 = nn.BatchNorm2d(self.expand_size).cuda()self.ac1 = DynamicReLU(self.expand_size, self.token_demension, k=self.k).cuda()      self.conv2 = nn.Conv2d(self.expand_size, self.expand_size, kernel_size=3, stride=1, padding=1, groups=self.expand_size).cuda()self.bn2 = nn.BatchNorm2d(self.expand_size).cuda()self.ac2 = DynamicReLU(self.expand_size, self.token_demension, k=self.k).cuda()          self.conv3 = nn.Conv2d(self.expand_size, self.out_channel, kernel_size=1, stride=1).cuda()self.bn3 = nn.BatchNorm2d(self.out_channel).cuda()def forward(self, x, first_token):if self.stride == 2:x = self.strided_conv(x)x = self.bn1(self.conv1(x))x = self.ac1(x, first_token)x = self.bn2(self.conv2(x))x = self.ac2(x, first_token)return self.bn3(self.conv3(x))

Former 子块:Former 子块是一个标准的 Transformer 块,包括一个多头注意力(MHA)和一个前馈网络(FFN)。在 FFN 中,膨胀率为 2(代替 4)。使用 post 层归一化。Former 在 Mobile→Former 和 Mobile←Former 之间处理(见上图)。

class Former(nn.Module):def __init__(self, head, d_model, expand_ratio=2):super(Former, self).__init__()self.d_model = d_modelself.expand_ratio = expand_ratioself.eps = 1e-10self.head = headassert self.d_model % self.head == 0self.d_per_head = self.d_model // self.headself.QVK = MLP([self.d_model, self.d_model * 3], bn=False).cuda()self.Q_to_heads = MLP([self.d_model, self.d_model], bn=False).cuda()self.K_to_heads = MLP([self.d_model, self.d_model], bn=False).cuda()self.V_to_heads = MLP([self.d_model, self.d_model], bn=False).cuda()self.heads_to_o = MLP([self.d_model, self.d_model], bn=False).cuda()self.norm = nn.LayerNorm(self.d_model).cuda()self.mlp = MLP([self.d_model, self.expand_ratio * self.d_model, self.d_model], bn=False).cuda()self.mlp_norm = nn.LayerNorm(self.d_model).cuda()def forward(self, x):QVK = self.QVK(x)Q = QVK[:, :, 0: self.d_model]Q = rearrange(self.Q_to_heads(Q), 'n m ( d h ) -> n m d h', h=self.head)  K = QVK[:, :, self.d_model: 2 * self.d_model]K = rearrange(self.K_to_heads(K), 'n m ( d h ) -> n m d h', h=self.head)   V = QVK[:, :, 2 * self.d_model: 3 * self.d_model]V = rearrange(self.V_to_heads(V), 'n m ( d h ) -> n m d h', h=self.head)  scores = torch.einsum('nqdh, nkdh -> nhqk', Q, K) / (np.sqrt(self.d_per_head) + self.eps)   scores_map = F.softmax(scores, dim=-1)v_heads = torch.einsum('nkdh, nhqk -> nhqd', V, scores_map) v_heads = rearrange(v_heads, 'n h q d -> n q ( h d )')attout = self.heads_to_o(v_heads)attout = self.norm(attout)  attout = self.mlp(attout)attout = self.mlp_norm(attout)  return attout  

Mobile→Former:文章提出的轻量级交叉注意力(式 1)用于将局部特征 X 融合到全局特征 tokens Z。与标准注意力相比,映射矩阵的键 W K W^{K} WK 和值 W V W^{V} WV(在局部特征 X 上)被移除以节省计算(见上图)。


class Mobile_Former(nn.Module):'''局部特征 -> 全局特征'''def __init__(self, d_model, in_channel):super(Mobile_Former, self).__init__()self.d_model, self.in_channel = d_model, in_channelself.project_Q = nn.Linear(self.d_model, self.in_channel).cuda()self.unproject = nn.Linear(self.in_channel, self.d_model).cuda()self.eps = 1e-10self.shortcut = nn.Sequential().cuda()def forward(self, local_feature, x):_, c, _, _ = local_feature.shapelocal_feature = rearrange(local_feature, 'n c h w -> n ( h w ) c')   project_Q = self.project_Q(x)   scores = torch.einsum('nmc , nlc -> nml', project_Q, local_feature) * (c ** -0.5)scores_map = F.softmax(scores, dim=-1)  fushion = torch.einsum('nml, nlc -> nmc', scores_map, local_feature)unproject = self.unproject(fushion) return unproject + self.shortcut(x)

Mobile-Former:这里的交叉注意力(式 2)与 Mobile→Former 的方向相反,其将全局 tokens 融入本地特征。局部特征是查询,全局 tokens 是键和值。因此,我们保留键 W K W^{K} WK 和值 W V W^{V} WV 中的映射矩阵,但移除查询 W Q W^{Q} WQ 的映射矩阵以节省计算,如上图所示。

计算复杂度:Mobile-Former 块的四个核心部分具有不同的计算成本。给定输入大小为 H W × C HW\times C HW×C 的特征图,以及尺寸为 d 的 M 个全局 tokens,Mobile 占据了大部分的计算量 O ( H W C 2 ) O(HWC^{2}) O(HWC2)。Former 和双线桥是重量级的,占据不到总计算成本的 20%。具体而言,Former 的自注意力和 FFN 具有复杂度 O ( M 2 d + M d 2 ) O(M^{2}d+Md^{2}) O(M2d+Md2)。Mobile→Former 和 Mobile←Former 共享交叉注意力的复杂度 O ( M H W C + M d C ) O(MHWC+MdC) O(MHWC+MdC)

class Former_Mobile(nn.Module):'''全局特征 -> 局部特征'''def __init__(self, d_model, in_channel):super(Former_Mobile, self).__init__()self.d_model, self.in_channel = d_model, in_channelself.project_KV = MLP([self.d_model, 2 * self.in_channel], bn=False).cuda()self.shortcut = nn.Sequential().cuda()def forward(self, x, global_feature):res = self.shortcut(x)n, c, h, w = x.shapeproject_kv = self.project_KV(global_feature)K = project_kv[:, :, 0 : c]  V = project_kv[:, :, c : ]  x = rearrange(x, 'n c h w -> n ( h w ) c') scores = torch.einsum('nqc, nkc -> nqk', x, K) scores_map = F.softmax(scores, dim=-1) v_agg = torch.einsum('nqk, nkc -> nqc', scores_map, V)  feature = rearrange(v_agg, 'n ( h w ) c -> n c h w', h=h)return feature + res

网络结构

一个 Mobile-Former 架构,图像大小为 224×224,294M FLOPs,以不同的输入分辨率堆叠 11 个 Mobile-Former 块。所有块都有 6 个维度为 192 的全局 tokens。它以一个 3×3 的卷积作为 stem 和第一阶段的轻量瓶颈块,首先膨胀,然后通过 3×3 depth-wise 卷积和 point-wise 卷积压缩通道数。第 2-5 阶段包括 Mobile-Former 块。每个阶段的下采样,表示为 Mobile-Former 分类头在局部特征应用平均池化,首先和全局 tokens concat 到一起,然后经过两个全连接层,中间是 h-swish 激活函数。Mobile-Former 有七种模型,计算成本从 26M 到 508M FLOPs。它们的结构相似,但宽度和高度不同。

class MobileFormerBlock(nn.Module):def __init__(self, in_channel, expand_size, out_channel, d_model, stride=1, k=2, head=8, expand_ratio=2):super(MobileFormerBlock, self).__init__()self.in_channel, self.expand_size, self.out_channel = in_channel, expand_size, out_channelself.d_model, self.stride, self.k, self.head, self.expand_ratio = d_model, stride, k, head, expand_ratioself.mobile = Mobile(self.in_channel, self.expand_size, self.out_channel, self.d_model, kernel_size=3, stride=self.stride, k=self.k).cuda()self.former = Former(self.head, self.d_model, expand_ratio=self.expand_ratio).cuda()self.mobile_former = Mobile_Former(self.d_model, self.in_channel).cuda()self.former_mobile = Former_Mobile(self.d_model, self.out_channel).cuda()def forward(self, local_feature, global_feature):z_hidden = self.mobile_former(local_feature, global_feature)z_out = self.former(z_hidden)x_hidden = self.mobile(local_feature, z_out[:, 0, :])x_out = self.former_mobile(x_hidden, z_out)return x_out, z_out

如果您想了解更多AI知识,与AI专业人士交流,请立即访问昇腾社区官方网站https://www.hiascend.com/或者深入研读《AI系统:原理与架构》一书,这里汇聚了海量的AI学习资源和实践课程,为您的AI技术成长提供强劲动力。不仅如此,您还有机会投身于全国昇腾AI创新大赛和昇腾AI开发者创享日等盛事,发现AI世界的无限奥秘~

相关文章:

【AI系统】MobileFormer

MobileFormer 在本文中,将介绍一种新的网络-MobileFormer,它实现了 Transformer 全局特征与 CNN 局部特征的融合,在较低的成本内,创造一个高效的网络。通过本节,让大家去了解如何将 CNN 与 Transformer 更好的结合起来…...

python数据分析之爬虫基础:解析

目录 1、xpath 1.1、xpath的安装以及lxml的安装 1.2、xpath的基本使用 1.3、xpath基本语法 2、JsonPath 2.1、jsonpath的安装 2.2、jsonpath的使用 2.3、jsonpath的基础语法 3、BeautifulSoup 3.1、bs4安装及创建 3.2、beautifulsoup的使用 3.3、beautifulsoup基本语…...

uniapp中导入uview或者uview plus

关于SCSS uview-plus依赖SCSS,您必须要安装此插件,否则无法正常运行。 如果您的项目是由HBuilder X创建的,相信已经安装scss插件,如果没有,请在HX菜单的 工具->插件安装中找到"scss/sass编译"插件进行安…...

【LeetCode】122.买卖股票的最佳时机II

文章目录 题目链接:题目描述:解题思路一(贪心算法):解体思路二(动态规划): 题目链接: 122.买卖股票的最佳时机II 题目描述: 解题思路一(贪心算法…...

openGauss开源数据库实战十九

文章目录 任务十九 openGauss DML 语句测试任务目标实施步骤一、准备工作二、INSERT语句三、DELETE语句四、UPDATE语句五、清理工作 任务十九 openGauss DML 语句测试 任务目标 掌握DML语句的用法,包括INSERT语句、DELETE语句和UPDATE语句。 实施步骤 一、准备工作 使用Li…...

恶补英语初级第18天,《询问他人的喜好(上)》

对话 Do you like coffee? Yes, I do. Do you want a cup? Yes, please. Do you want any sugar? Yes, please. Do you want any milk? No, thank you. I don’t like milk in my coffee, I like black coffee. Do you like biscuits? Yes, I do. Do you want one? Yes, …...

centos 报 ping: www.baidu.com: Name or service not known

[rootlocalhost ~]$ ping www.baidu.com ping: www.baidu.com: Name or service not known解决办法: 首先要求检查特定文件(/etc/resolv.conf)内是否正确配置了 DNS sudo vim /etc/resolv.conf没有正确配置可以添加如下代码: n…...

Python:使用随机森林分类器进行模型评估:ROC 曲线与 AUC 指标计算

前言 这段代码的目标是使用 随机森林分类器(Random Forest Classifier) 来进行二分类任务,并基于每个数据子集计算 ROC 曲线(Receiver Operating Characteristic Curve)以及 AUC(Area Under Curve&#xf…...

数据库表约束完全指南:提升数据完整性和准确性

数据库表约束完全指南:提升数据完整性和准确性 在数据库设计中,表约束是确保数据完整性和准确性的关键工具。本文将详细介绍各种类型的表约束及其使用方法,包括非空约束、唯一约束、主键约束、外键约束、默认值约束、检查约束以及自动递增约…...

【JavaEE】多线程(6)

一、用户态与内核态 【概念】 用户态是指用户程序运行时的状态,在这种状态下,CPU只能执行用户态下的指令,并且只能访问受限的内存空间 内核态是操作系统内核运行时的状态,内核是计算机系统的核心部分,CPU可以执行所有…...

BERT和RoBERTa;双向表示与单向的简单理解

目录 BERT和RoBERTa大型预训练语言模型 BERT的原理 RoBERTa的原理 举例说明 双向表示与单向的简单理解 除了预训练语言模型,还有什么模型 一、模型类型与结构 二、训练方式与数据 三、应用场景与功能 四、技术特点与优势 BERT和RoBERTa大型预训练语言模型 BERT(Bi…...

Pytorch使用手册-计算机视觉迁移学习教程(专题十三)

在本教程中,你将学习如何使用迁移学习训练一个卷积神经网络进行图像分类。更多关于迁移学习的内容可以参考 CS231n 课程笔记。 引用课程笔记中的内容: 实际上,很少有人从头开始训练一个完整的卷积网络(随机初始化),因为拥有足够大数据集的情况相对罕见。相反,通常会在非…...

Jackson - Java对象与JSON相互转换

在这篇文章中,我将向您展示如何使用Jackson-databind API来实现Java对象与JSON之间的绑定,以及如何将JSON数据转换为Java对象。 对于Java开发者来说,将JSON转换为Java对象及反向操作是一个常见的任务,因此我将通过示例演示如何完…...

怎麼解決路由器IP地址衝突?

路由器IP地址衝突通常發生在網路中有兩個設備嘗試使用相同的IP地址時。這種衝突會導致網路連接問題,因為每個設備需要一個唯一的IP地址才能正常通信。 1. 重啟設備 重啟路由器和設備:有時候簡單的重啟可以解決問題,設備重新獲取一個新的IP地…...

趣味数学 2.3.7 | 完全免费,无注册登录,简约纯净

趣味数学是一款完全免费的数学学习软件,支持安卓系统。它无需登录注册,界面简约纯净,分类详细,涵盖趣味数学、数学初练、应用计算、数字推理、图形推理、数字2048、题目练习和数学知识等多个分类。每个分类包含丰富的题目和关卡&a…...

Oracle ASM特性介绍和增删盘操作

1. 介绍 1.1. 在没有ASM之前ORACLE数据库靠什么去解决存储问题: 裸设备:裸设备就是没有被文件系统格式化的分区或者是直接挂载到操作系统上的磁盘。ORACLE可以直接将数据写入到裸设备中,读写能非常优异。像ORACLE的数据文件、控制文件、REDO日志在过去…...

深度优先搜索迷宫路径

深度优先搜索迷宫路径 问题描述 我们需要编写一个程序,通过深度优先搜索(DFS)找到从迷宫左上角到右下角的一条通路。 迷宫的表示: 迷宫由 0 和 1 构成的二维数组表示。0 表示可以走的路径,1 表示障碍。用户输入迷宫的…...

多媒体技术的 发展阶段----高中信息技术教资面试

上课,同学们好!请坐 在正式上课之前,老师带来 了一段微课视频,请同学们认真观看大屏幕。等下来回答老师的问题。 好,视频播放完成了,现在老师想问问大家。大家从视频中都看到了什么尼?好&…...

行为型设计模式之《责任链模式》实践

定义 责任链模式(Chain Of Responsibility Pattern)顾名思义,就是为请求创建一条处理链路,链路上的每个处理器都判断是否可以处理请求,如果不能处理则往后走,依次从链头走到链尾,直到有处理器可…...

中酱黑松露手工古法酱油,邂逅独特 “酱油红”

在美食的世界里,调味品往往扮演着画龙点睛的角色,它们虽不似主食材那般夺目,却能悄无声息地赋予菜肴灵魂与韵味。而今天,要带大家走进的,便是中酱手工古法酱油所营造出的独特美味天地,去领略那一抹别具魅力…...

Java NIO channel

channel(通道),byteBuffer(缓冲区),selector(io多路复用),通道FileChannel,SocketChannel的transferTo,transferFrom,MappedByteBuffer实现了零拷贝。 JVM调操作系统方法,read,write,都可以送字…...

智能交通(8)——腾讯开悟智能交通信号灯调度赛道

本文档用于记录参加腾讯开悟智能信号灯调度赛道的模型优化过程。官方提供了dqn和target_dqn算法,模型的优化在官方提供的代码基础上进行。最终排名是在榜单16,没能进入最后的决赛。 一.赛题介绍 赛题简介:在本地赛题中,参赛团队…...

ip所属地址是什么意思?怎么改ip地址归属地

在数字化时代,IP地址作为网络设备的唯一标识符,不仅关乎设备间的通信,还涉及到用户的网络身份与位置信息。IP所属地址,即IP地址的归属地,通常反映了设备连接互联网时的地理位置。本文将深入解析IP所属地址的含义&#…...

攻防世界 ctf刷题 新手区1-10

unserialize3 因为我上个笔记写了 php返序列化 所以先趁热打铁 看这个题目名字 我们就知道是 反序列化呀 因为flag有值所以 我们先输个 111 看看有没有线索 没线索但是这边 有个发现就是他是使用get方式传参的 可能他会把我们的输入 进行传入后台有可能进行反…...

Node做一个自动删除指定文件和文件夹工具

node14 可以搭配脚手架工具实现自动实现删除 // 引入path模块,用于处理文件路径 const path require(path); // 引入fs模块的promises API,用于异步文件操作 const fs2 require(fs).promises; // 引入fs模块,用于同步文件操作 const fs …...

陈若尧新歌《一来二去》陆续登陆全球音乐平台

由青年演员,歌手陈若尧带来的全新创作单曲《一来二去》由索尼音乐发行,于2024年11月18日陆续全球上线。这也是陈若尧与索尼音乐合作的第一首单曲。探索古典风格与流行音乐的新结合。歌曲上线不久,就因优美抒情的动人旋律,诗意而意味深远的歌词…...

【Docker】针对开发环境、测试环境、生产环境如何编排?

目录 一、引言 二、Docker Compose 文件基础 三、针对不同环境的 Docker 编排 开发环境 测试环境 生产环境 四、配置文件全局变量的编写 五、总结 一、引言 在软件开发和部署的过程中,不同的环境有着不同的需求和配置。Docker 作为一种强大的容器化技术&…...

小程序项目的基本组成结构

分类介绍 项目根目录下的文件及文件夹 pages文件夹 用来存放所有小程序的页面,其中每个页面都由4个基本文件组成,它们分别是: .js文件:页面的脚本文件,用于存放页面的数据、事件处理函数等 .json文件:…...

001-mysql安装

[rootcentos701 ~]# hostname -I 10.0.0.200 172.17.0.1 [rootcentos701 ~]# hostname centos701 [rootcentos701 ~]# rpm -qa | grep mariadb [rootcentos701 ~]# rpm -e --nodeps mariadb-libs-5.5.65-1.el7.x86_64 [rootcentos701 ~]# useradd mysql -s /sbin/nologin #创建…...

预训练模型与ChatGPT:自然语言处理的革新与前景

目录 一、ChatGPT整体背景认知 (一)ChatGPT引起关注的原因 (二)与其他公司的竞争情况 二、NLP学习范式的发展 (一)规则和机器学习时期 (二)基于神经网络的监督学习时期 &…...