DMS:直接可微的网络搜索方法,最快仅需单卡10分钟 | ICML 2024

news2024/9/19 19:46:09

Differentiable Model ScalingDMS)以直接、完全可微的方式对宽度和深度进行建模,是一种高效且多功能的模型缩放方法。与先前的NAS方法相比具有三个优点:1)DMS在搜索方面效率高,易于使用。2)DMS实现了高性能,可与SOTA NAS方法相媲美。3)DMS是通用的,与各种任务和架构兼容。

来源:晓飞的算法工程笔记 公众号

论文: Differentiable Model Scaling using Differentiable Topk

  • 论文地址:https://arxiv.org/abs/2405.07194

Introduction


  在近年来,像GPTViT这样的大型模型展示了出色的性能。值得注意的是,GPT-4的涌现强调了通过扩展网络来实现人工通用智能(AGI)的重要性。为了支持这个扩展过程,论文引入了一种通用而有效的方法来确定网络在扩展过程中的最佳宽度和深度。

  目前,大多数网络的结构设计仍然依赖于人类专业知识。通常需要大量资源来调整结构超参数,导致很难确定最佳结构。与此同时,神经架构搜索(NAS)方法已经被引入到自动化网络结构设计中。根据搜索策略将NAS方法分为两类:随机搜索方法和基于梯度的方法。

  随机搜索方法需要对大量子网络进行采样以比较性能。然而,这些方法的搜索效率受到样本评估周期的限制,导致性能降低和搜索成本增加。

  与随机搜索方法不同,基于梯度的方法采用梯度下降法来优化结构参数、 提高效率,使其更善于平衡搜索成本和最终性能。然而,一个巨大的挑战依然存在:如何以直接和可微的方式为结构超参数建模?早期的方法一直在努力应对这一挑战,结果导致性能下降、成本增加。具体来说,根据建模策略将先前的方法分为三类:

  1. 多元素选择:在搜索卷积层中的通道数时,将通道数建模为通道选择(比如PaS通过可学习二值卷积生成0/1掩码对通道进行剪枝),如图1 a.1所示。
  2. 单数字选择:在搜索卷积层中的通道数时,将通道数建模为从多个候选数字中的选择一个(比如FBNetV2在一层中学习不同大小的候选卷积的权重),如图1 a.2所示。
  3. 梯度估计topk:尝试直接建模宽度和深度(比如通过梯度估计学习动态的k值以及给每个通道生成重要性分数,随后选择topk通道),如图1 a.3所示。这个可能跟多元素选择有点类似,核心区别是多元素选择是为了生成掩码,而这个则是为了生成动态k值。

  但所有上述策略都无法以直接和完全可微分的方式对结构超参数进行建模。为了解决上述挑战,论文引入了一个完全可微分的topk运算符,可以无缝地以直接和可微分的方式对深度和宽度进行建模。值得注意的是,每个可微分的topk运算符都有一个可学习参数,表示深度或宽度结构超参数,可以基于任务损失和资源约束损失的指导进行优化。与现有的基于梯度的方法相比,论文的方法在优化效率方面表现出色。

  基于可微分topk,论文提出了一种可微分模型缩放(DMS)算法来搜索网络的最佳宽度和深度。为了验证功效和效率,在各种任务中进行了严格的测试,包括视觉任务和NLP任务,以及不同的架构,包括CNNTransformer。由于可微分topk具有高效的搜索效率,DMS在性能或搜索成本方面均优于先前的SOTA方法。

  总的来说,论文的贡献如下:

  1. 引入了可微分的topk运算符,可以以直接和可微分的方式对结构超参数进行建模,因此很容易进行优化。
  2. 基于可微分的topk提出了一种可微分模型缩放(DMS)算法,用于搜索网络的最佳宽度和深度。
  3. 评估了DMS在各种任务和架构上的性能。例如,DMS在搜索过程中只需0.4 GPU天,就能比最先进的zero-shot NAS方法ZiCo表现出1.3%的优势。与性能相当的one-shot NAS方法ScaleNet以及multi-shot NAS方法Amplification相比,DMS所需的搜索成本仅为几十分之一。此外,DMS是一种广泛适用的方法,在COCO数据集上将Yolo-v8-n的提高了2.0%,并提高了裁剪Llama-7B模型样本分类精度。

Related Work


Stochastic Search Methods

  随机搜索方法通常通过采样和评估的循环过程进行操作。在每一步中,它们会对具有不同构的模型进行采样,然后对其进行评估。这种策略非常灵活,可以处理连续和离散的搜索空间。然而,它的一个显著缺点搜索效率低下,导致资源消耗高和性能不理想。具体而言,基于随机搜索的方法可以分为三种:

  1. multi-shot NAS:需要训练多个模型,这非常耗时,如EfficientNet用了1714TPU天来进行搜索。
  2. one-shot NAS:需要训练一个庞大的超网络,也需要大量资源,如ScaleNet用了379GPU天来训练一个超网络。
  3. zero-shot NAS:通过消除训练任何模型来减少成本,但其性能尚未达到所期望的标准。

Gradient-based Methods

  基于梯度的结构搜索方法使用梯度下降来探索模型的结构,这些方法一般比随机搜索方法更高效。基于梯度的方法的关键在于如何使用可学习参数来建模结构超参数并计算其梯度,理想情况下,可学习参数应直接建模结构超参数并且其梯度应以完全可微的方式计算。然而,先前的方法在建模网络的宽度和深度时往往难以同时满足这两个条件,可以将它们分为三类:(1)多元素选择,(2)单数字选择和(3)梯度估计topk。前两类间接地建模结构超参数,而第三类不可微分,需要进行梯度估计。

  为了提高结构搜索的优化效率,论文引入了一种新的可微分的topk方法,可以直接建模宽度和深度,并且是完全可微分的。从实验结果来看,论文的方法更加高效和有效。

Method


Differentiable Top-k

  假设存在一个由 k k k 表示的结构超参数,表示元素的数量,比如卷积层中的 k k k 个通道或网络阶段中的 k k k 个残差块。 k k k 的最大值为 N N N,使用 c ∈ R N {\mathbf{c}} \in \mathbb{R}^N cRN来表示元素的重要性,其中较大的值表示更高的重要性。可微分topk方法的目标是输出一个软掩码 m ∈ 0 , 1 N {\mathbf{m}} \in 0,1^N m0,1N,代表具有前 k k k 个重要分数的选定元素。

topk运算符使用可学习的参数 a a a 作为阈值,选择那些重要性值大于 a a a 的元素。 a a a 能够直接建模元素数量 k k k,因为 k k k 可以看作是 a a a 的一个函数,其中 k = ∑ N _ i = 1 1 c _ i > a k=\sum^N\_{i=1}{1c\_i>a} k=N_i=11c_i>a 1 A 1A 1A 是一个指示函数,如果 A A A 为真则等于1,否则等于0 c _ i c\_i c_i 表示第 i i i 个元素的重要性。将topk表示为一个函数 f f f,如下所示:

m _ i = f ( a ) ≈ { 1 if  c _ i > a   0 otherwise \begin{align} m\_i = f(a) \approx \begin{cases} 1 & \text{if } c\_i > a \ 0 & \text{otherwise} \end{cases} \end{align} m_i=f(a){1if c_i>a 0otherwise

  在先前的方法中, f f f 通常是一个分段函数,不平滑也不可微分,且 a a a 的梯度是通过估计计算得出的。论文认为采用相对于 a a a 完全可微分的 f f f 的最大挑战是重要性分数分布不均匀。具体来说,不均匀的分布导致重要性值排序中的两个相邻元素之间的差异较大。假设每次迭代时通过固定值更新 a a a,当前后元素的重要性差异很大时,则需要许多步才能使 a a a 跨越这两个元素。当差异很小时, a a a 可以在一步内跨越许多元素。因此,在元素重要性不均匀时,以完全可微分的方式优化 a a a 是非常困难。

  为了解决这个挑战,论文采用了一种重要性归一化过程,将不均匀分布的重要性强制转换为均匀分布的值,使得topk函数在可微分的情况下变得平滑且易于优化。总结起来,可微分topk有两个步骤:重要性归一化和软掩码生成。

Importance Normalization

  根据以下方式,通过将所有元素的重要性映射到从01的均匀分布的值来对所有元素的重要性归一化:

c i ′ = 1 N ∑ j = 1 N 1 c _ i > c _ j . \begin{align} & c_i' = \frac{1}{N}\sum^N_{j=1}{1c\_i>c\_j}. \end{align} ci=N1j=1N1c_i>c_j.

  归一化后的元素重要性用 c ′ {\mathbf{c}}' c 表示。 1 A 1A 1A 是与上面相同的指示函数, c {\mathbf{c}} c 中的任意两个元素通常是不同的。值得注意的是,虽然 c ′ \mathbf{c}' c01之间均匀分布,但 c \mathbf{c} c 可以遵循任何分布。

  直观地说, c ′ _ i c'\_i c_i 表示 c {\mathbf{c}} c 中值小于 c _ i c\_i c_i 的部分。此外,可学习的阈值 a a a 也变得有意义,表示元素的剪枝比例。 k k k 可以通过 k = ⌊ ( 1 − a ) N ⌉ k=\lfloor(1-a)N\rceil k=⌊(1a)N 计算,其中 ⌊   ⌉ \lfloor \, \rceil 是一个取整函数。 a a a 限制在 0 , 1 0,1 0,1 的范围内,其中 a = 0 a=0 a=0 表示不剪枝, a = 1 a=1 a=1 表示剪枝所有元素。

Soft Mask Generation

  在归一化之后,可以使用基于相对大小的剪枝比例 a a a 和归一化元素重要性 c ′ {\mathbf{c}}' c的平滑可微函数轻松生成软掩码${\mathbf{m}} $。

m _ i = f ( a ) = Sigmoid ( λ ( c ′ _ i − a ) ) = 1 1 + e − λ ( c ′ _ i − a ) . \begin{align} & m\_i = f(a)= \text{Sigmoid}(\lambda({\mathbf{c}}'\_i- a)) = \frac{1}{1+e^{-\lambda({\mathbf{c}}'\_i - a)}}. \end{align} m_i=f(a)=Sigmoid(λ(c_ia))=1+eλ(c_ia)1.

  论文添加了一个超参数 λ \lambda λ来控制从公式3到硬掩码生成函数的逼近程度。当 λ \lambda λ趋近于无穷大时,公式3接近于硬掩码生成函数(根据固定阈值 a a a 直接得出0/1)。通常将 λ \lambda λ设置为 N N N,因为当 c ′ _ i > a + 3 / N c'\_i>a+3/N c_i>a+3/N c ′ _ i < a − 3 / N c'\_i<a-3/N c_i<a3/N时,$|(m_i-\lfloor m_i \rceil)|<0.05 $。这意味着除了重要性值接近剪枝比例的六个元素外,其他元素的掩码接近于01,近似误差小于0.05。因此, λ = N \lambda=N λ=N足以逼近topk的硬掩码生成函数。

  公式3的前向和反向图分别如图2(a) 和图2(b) 所示,可以观察到以下两点:

  1. topk直接使用可学习的剪枝比例 a a a 来建模元素数量 k k k,并在前向过程中生成极化的软掩码 m {\mathbf{m}} m,以完美模拟剪枝后的模型。
  2. 可微分topk完全可微分,并且能够稳定地进行优化。 a a a相对于 m i m_i mi的梯度为 $\frac{\partial m_i}{\partial a} = -\lambda(1-m_i)m_i $。我们的__topk直观地检测模糊区域中 0.05 < m _ i < 0.95 0.05<m\_i<0.95 0.05<m_i<0.95的掩码梯度。请注意,图2__(b) 描述的是 ∂ m _ i ∂ a \frac{\partial m\_i}{\partial a} am_i的值,而不是 a a a 的总梯度, a a a 的总梯度为 ∑ i = 1 N ∂ t a s k _ l o s s ∂ m _ i ∂ m _ i ∂ a + ∂ r e s o u r c e _ l o s s ∂ a \sum_{i=1}^{N}{\frac{\partial task\_loss}{\partial m\_i}\frac{\partial m\_i}{\partial a}}+\frac{\partial resource\_loss}{\partial a} i=1Nm_itask_lossam_i+aresource_loss

Element Evaluation

  由于元素重要性会被归一化后再进行掩码生成,所以不限制元素重要性的分布,可以通过多种方法来量化元素重要性,例如L1-norm 等。论文以滑动平均方式实现了Taylor importance,具体如下所示:

c i t + 1 = c t _ i × d e c a y + ( m t _ i × g i ) 2 × ( 1 − d e c a y ) . \begin{align} c^{t+1}_i = c^t\_i \times decay + (m^t\_i \times g_{i})^2 \times (1-decay). \end{align} cit+1=ct_i×decay+(mt_i×gi)2×(1decay).

  在这里, t t t表示训练步骤, g _ i g\_i g_i m _ i m\_i m_i 相对于训练损失的梯度, D e c a y Decay Decay是衰减率, c _ i 0 c\_i^0 c_i0的初始值设为零,衰减率设为0.99。请注意,元素的重要性不是通过梯度下降来更新的。通过利用Taylor importance,可以高效且稳定地估计元素的重要性。

Differentiable Model Scaling

  依靠可微分topk,论文提出了可微分模型缩放(Differentiable Model ScalingDMS)来优化网络的宽度和深度。DMS有三种基于基于训练的模型剪枝的流水线变体,如表1所示。

  • DMS _ p \text{DMS}\_{\text{p}} DMS_p

DMS _ p \text{DMS}\_{\text{p}} DMS_p 是基于训练的模型剪枝流水线,由预训练阶段、搜索阶段和重新训练阶段组成:

  1. 预训练阶段用于预训练一个超网络,通常需要大量时间和资源。
  2. 搜索阶段在特定资源约束下搜索超网络的最优宽度和深度,由于论文方法具有较高的搜索效率,因此搜索阶段只使用了大约1/10或更少的重新训练轮数。
  3. 在重新训练阶段,重新对已经进行了搜索的模型进行训练。与SOTA剪枝方法进行比较时,使用这个流水线。
  4. DMS _ np \text{DMS}\_{\text{np}} DMS_np

DMS np \text{DMS}_{\text{np}} DMSnp 是论文中默认和最常用的流水线。预训练阶段的高本占据了总成本的大部分,这是__NAS__和剪方法在实际应用中面临的一个重大障碍。为克服这个问题,从 DMS \text{DMS}_{\text{}} DMS 中去除了预训练阶段,直接从随机初始化超网络开始搜索。通过增加超网络大小, DMS np \text{DMS}_{\text{np}} DMSnp 在性能和效率上都超过了 DMS p \text{DMS}_{\text{p}} DMSp,并且比其他NAS方法更加高效。

  • DMS _ p- \text{DMS}\_{\text{p-}} DMS_p-

DMS p- \text{DMS}_{\text{p-}} DMSp- 用于快速比较不同搜索方法。与 DMS p {\text{DMS}_\text{p}} DMSp 相比,它只优化结构参数,不对搜索到的模型进行重新训练。利用现有的预训练超网络,也能输出合理的结果。此外,它只需要数百次迭代,在单个RTX3090上花费不到10分钟就可以搜索出一个模型。

  • Search Space

  如图1(b)所示,论文的搜索空间涵盖了网络的宽度和深度,这是模型扩展最关键的结构超参数。为了表示这些维度,使用了可微分的topk方法。在网络中,宽度通常涵盖了卷积层中的通道维度、全连接层中的特征维度等。关于深度,论文专注于具有残差连接的网络,并搜索每个阶段中的块数。具体来说,将可微分topk的软掩码合并到残差连接中,使得每个块可以表示为 x _ i + 1 = x _ i + f ( x _ i ) × m _ i x\_{i+1}=x\_i+f(x\_i)\times m\_i x_i+1=x_i+f(x_i)×m_i

  此外,对于结构超参数 x x x,在范围 1 , x _ m a x 1, x\_{max} 1,x_max 内以步长1进行搜索,而大多数先前的NAS方法则在范围 x m i n , x m a x x_{min}, x_{max} xmin,xmax 内以步长32进行搜索。这个搜索空间是由人类专家设计的一个较好的子空间,然而论文的搜索空间更加通用且成本最低。实验结果显示,论文的方法在精细搜索空间上可以达到更好的性能,这个空间更难搜索,而先前的方法在粗粒度搜索空间上的表现较好,这种空间更容易搜索。

  • Resource Constraint Loss

  为了确保网络遵循特定的资源约束,在优化过程中加入了一个额外的组件,称为Resource Constraint Loss。因此,整体的损失函数为:

l o s s = l o s s t a s k + λ r e s o u r c e × l o s s _ r e s o u r c e .   l o s s _ r e s o u r c e = { log ⁡ ( r c r t ) if  r c > r t   0 otherwise . \begin{align} loss= & loss_{task}+\lambda_{resource}\times loss\_{resource}. \ & loss\_{resource}=\begin{cases} \log(\frac{r_{c}}{r_{t}}) & \text{if } r_{c} > r_{t} \ 0 & \text{otherwise} \end{cases}. \end{align} loss=losstask+λresource×loss_resource. loss_resource={log(rtrc)if rc>rt 0otherwise.

  在这里, l o s s t a s k loss_{task} losstask 表示任务损失。 l o s s r e s o u r c e loss_{resource} lossresource 表示额外的资源约束损失, λ _ r e s o u r c e \lambda\_{resource} λ_resource 作为其权重系数。 r r r 表示当前资源消耗水平,根据可学习参数的不同topk操作符进行计算。 r _ t r\_t r_t 代表目标资源耗水平,由用户指定。由于topk是完全可微分的,可学习结构参数可以在任务损失和资源约束失的指导下进行优化。

Experiment


如果本文对你有帮助,麻烦点个赞或在看呗

更多内容请关注 微信公众号【晓飞的算法工程笔记】

work-life balance.

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

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

相关文章

Javascript嵌套函数的调用

这里其实还是讲讲我对javascript闭包的认识。js中闭包就是以嵌套函数的外表出现的。内容是我自己琢磨的&#xff0c;我估计如果这个问题了解很清楚的话&#xff0c;javascript的闭包就没有问题了。其实这里探讨的是一个非常司空见惯&#xff0c;但是可能很多人没有注意的细节。…

SQL-函数篇

在SQL中&#xff0c;函数是用于执行特定操作的预定义代码块。它们可以帮助我们处理字符串、数值、日期等数据类型。下面是一些常用的SQL函数及其用法。 下面是一些常用的函数&#xff1a; 字符串函数 字符串函数用于操作和处理字符串数据。 -- 将两个字符串连接起来 select c…

爱心动画代码HTML5

这段代码是一个HTML5 Canvas动画&#xff0c;它通过JavaScript创建了一个动态的爱心效果。页面初始化时&#xff0c;首先定义了一些基本设置&#xff0c;如粒子数量、持续时间、速度等。然后&#xff0c;定义了Point和Particle类&#xff0c;用于处理粒子的位置和运动。接着&am…

部署Nginx负载均衡+动静分离的群集

目录 一、Nginx应用 二、正向代理与反向代理 1.1正向代理 1.2反向代理 三、负载均衡 1.轮询&#xff08;Round Robin&#xff09; 2.最小连接数 3.IP hash: 4.加权轮询 5.最少事件算法 6.一致性hash 一、Nginx应用 Nginx是一款非常优秀的HTTP服务器软件 支持高达50 …

【生日视频制作】洪崖洞高大楼AE模板修改文字软件生成器教程特效素材【AE模板】

洪崖洞企业高大楼生日视频制作教程AE模板改文字特效生成器素材 怎么如何做的【生日视频制作】洪崖洞企业高大楼AE模板修改文字软件生成器教程特效素材【AE模板】 生日视频制作步骤&#xff1a; 安装AE软件下载AE模板把AE模板导入AE软件修改图片或文字渲染出视频

【JAVA八股文】持续更新中...

【-------------数据类型------------】 一、基本类型、包装类型 基本类型&#xff1a;整型&#xff08;byte short int long &#xff09;浮点型&#xff08;float double&#xff09;布尔型&#xff08;boolean&#xff09; 字符型&#xff…

【联想电脑】:使用拓展坞后转接HDMI,无法识别显示屏

项目场景&#xff1a; 作为一个嵌入式软件开发者&#xff0c;有两个外接屏幕&#xff0c;不足为奇。 但是在今天的使用电脑过程中&#xff0c;出现了接了一个拓展坞上面有HDMI接口&#xff0c;但是HDMI接口接上外接显示屏的时候电脑无法识别到&#xff0c;导致只有电脑直连的HD…

安装Pentaho Data Integration并启动

“pdi-ce-9.3.0.0-428.zip”包在 “/opt/software/”目录下。 步骤详情 1. 解压zip包2. 启动 Pentaho Data Integration PDI&#xff08;Kettle&#xff09; GUI 界面 1. 解压zip包 因为 Kettle 是绿色软件工具&#xff0c;开箱即用&#xff0c;无须安装。首先进入“/opt/soft…

ansible 中剧本的书写与运行

1.更改配置文件vim /etc/ansible/hosts 2.测试m0主机与s0、s1、s2&#xff0c;之间可以ping通 [rootm0 ansible]# ansible group02 -m ping 3.书写脚本文件 [rootm0 ~]# vim test0001.yml ​ --- - hosts: group02remote_user: roottasks: ​- name:…

【Qt】常用控件QLabel

常用控件QLabel QLabel可以用来显示文本和图片。 QLabel的属性 其核心属性如下&#xff1a; 属性说明 text QLabel 中的⽂本 textFormat ⽂本的格式. Qt::PlainText 纯⽂本Qt::RichText 富⽂本(⽀持 html 标签)Qt::MarkdownText markdown 格式Qt::AutoText 根据⽂本内容…

uniapp 页面跳转传参:父页面监听子页面传过来的数据

父页面 监听events事件 uni.navigateTo({url: "/components/watermark-camera",events: { // 重点重点重点重点重点重点重点重点getImages(data) { // 接收子页面抛出的 getImages 事件console.log("水印相机的照片&#xff1a;", data)}}})子页面 const …

人工智能和机器学习 3(复旦大学计算机科学与技术实践工作站)python机器学习、Pytorch库入门、d2l学习+<机器学习、神经网络————原理、理论>

前言 安装 — 动手学深度学习 2.0.0 documentation (d2l.ai)https://zh.d2l.ai/chapter_installation/index.html 安装 我们需要配置一个环境来运行 Python、Jupyter Notebook、相关库以及运行本书所需的代码&#xff0c;以快速入门并获得动手学习经验。 安装 Miniconda 最…

【css】水平对齐方式(justify、text-align、display: flex;)

一、justify 完整的属性名是 justify-contentjustify-content 用于定义位于同一行的项目在主轴&#xff08;通常是水平方向&#xff09;上的对齐方式。 center &#xff1a;居中start : 起始位置对齐&#xff08;左对齐&#xff09;end : 结束位置对齐&#xff08;右对齐&…

使用 LlamaIndex 中的 Relik 进行实体链接和关系提取

从文本构建知识图谱长期以来一直是一个令人着迷的研究领域。随着大型语言模型 (LLM) 的出现&#xff0c;该领域获得了更多主流关注。然而&#xff0c;LLM 的成本可能相当高。另一种方法是微调较小的模型&#xff0c;这种方法得到了学术研究的支持&#xff0c;可以产生更有效的解…

无线领夹麦克风哪个牌子好?最好的无线麦克风品牌排行推荐

伴随着智能手机的不断发展&#xff0c;手机不单单只是承担着联系的作用&#xff0c;凭借着小巧、出色拍摄体验等&#xff0c;成为了绝大部分朋友记录生活的绝佳选择&#xff0c;例如录制VLog、短视频等等。不过录制视频必然需要考虑到收音问题&#xff0c;因为在实际录制过程中…

Java面试八股之什么是消息队列的高并发缓冲

什么是消息队列的高并发缓冲 消息队列的高并发缓冲是指在处理大量并发请求时&#xff0c;通过消息队列来平滑处理请求的一种机制。这种机制可以帮助系统在高并发场景下保持稳定性和性能。 高并发缓冲的核心思想&#xff1a; 解耦&#xff1a; 消息队列作为一个中间层&#…

树莓派5 笔记26:ollama大型语言模型_中文输入法_Python_espeak文字转语音

今日继续学习树莓派5 8G&#xff1a;&#xff08;Raspberry Pi&#xff0c;简称RPi或RasPi&#xff09; 本人所用树莓派4B 装载的系统与版本如下: 版本可用命令 (lsb_release -a) 查询: Opencv 与 python 版本如下&#xff1a; 下载大语言模型&#xff0c;下载中文输入法&#…

HTML+CSS+JS实现商城首页[web课设代码+模块说明+效果图]

系列文章目录 1.Web前端大作业htmlcss静态页面–掌****有限公司 2.Web前端大作业起点小说静态页面 3.Web前端大作业网易云页面 4.Web前端大作业商城页面 5.Web前端大作业游戏官网页面 6.Web前端大作业网上商城页面 7.HTMLCSS淘宝首页[web课设代码模块说明效果图] 8.HTMLCSSJS实…

Linux | 深入探究Linux进程控制:从fork函数到进程等待再到进程替换

目录 1、进程的创建&#xff1a;fork函数 2、父子进程的奇怪现象&#xff1a;为什么同一个地址有不同的值&#xff1f;——区分内存的虚拟地址和物理地址 代码&#xff1a;利用fork函数的返回值进行父子进程分流&#xff0c;执行不同的代码块 虚拟地址和物理地址&#xff1…

selenium学习记录

1、初识selenium 概述&#xff1a; Selenium是一个Web的自动化测试工具&#xff0c;最初是为网站自动化测试而开发的&#xff0c;类型像我们玩游戏用的按键精灵&#xff0c;可以按指定的命令自动操作&#xff0c;不同是Selenium 可以直接运行在浏览器上&#xff0c;它支持所有…