优化器算法

news2024/9/22 15:36:20

优化器算法

在这里插入图片描述

梯度下降算法

首先引用动手学深度学习中对梯度下降算法的直观理解与推导。说明了不断的迭代可能会使得f(x)的值不断下降,从直观上解释了梯度下降的可能性。

  1. 将损失函数在x点处一阶泰勒展开。

f ( x + ϵ ) = f ( x ) + ϵ f ′ ( x ) + O ( ϵ 2 ) . f(x+\epsilon)=f(x)+\epsilon f^{\prime}(x)+\mathcal{O}\left(\epsilon^{2}\right) . f(x+ϵ)=f(x)+ϵf(x)+O(ϵ2).

即在一阶近似中,f(x十ε)可通过x处的函数值f(x)和一阶导数f’(x)得出。我们可以假设在负梯度方向上移动的ε会减少f。为了简单起见,我们选择固定步长 n>0,然后取ε = -nf’(x)。

  1. 将其代入泰勒展开式中可以得到下面的式子:n>0和f’(x)的平方大于0经过化简可以得到第二个式子。

f ( x − η f ′ ( x ) ) = f ( x ) − η f ′ 2 ( x ) + O ( η 2 f ′ 2 ( x ) ) . f\left(x-\eta f^{\prime}(x)\right)=f(x)-\eta f^{\prime 2}(x)+\mathcal{O}\left(\eta^{2} f^{\prime 2}(x)\right) . f(xηf(x))=f(x)ηf′2(x)+O(η2f′2(x)).

f ( x − η f ′ ( x ) ) ≲ f ( x ) . f\left(x-\eta f^{\prime}(x)\right) \lesssim f(x) . f(xηf(x))f(x).

  1. 最后我们说明了如果使用下面的式子来迭代x的值则会使得f(x)的值不断的下降到极小值,梯度为0时终止

x ← x − η f ′ ( x ) x \leftarrow x-\eta f^{\prime}(x) xxηf(x)

总结:梯度下降算法最初提出是解决凸优化的问题,但在神经网络中损失函数的优化问题不一定全部是凸优化问题,通常情况下是找一个局部的极值。

在这里插入图片描述

L ( f ( x i , θ ) , y i )  损失函数  L\left(f\left(x_{i}, \theta\right), y_{i}\right) \text { 损失函数 } L(f(xi,θ),yi) 损失函数 

∇ θ L ( f ( x i , θ ) , y i ) g = 1 N ∇ θ ∑ i = 1 N L ( f ( x i , θ ) , y i ) θ ← θ − ε g \begin{array}{l} \nabla_{\theta} L\left(f\left(x_{i}, \theta\right), y_{i}\right) \\ g=\frac{1}{N} \nabla_{\theta} \sum_{i=1}^{N} L\left(f\left(x_{i}, \theta\right), y_{i}\right) \\ \theta \leftarrow \theta-\varepsilon g \end{array} θL(f(xi,θ),yi)g=N1θi=1NL(f(xi,θ),yi)θθεg

梯度下降的步骤

梯度下降算法的核心思想是通过迭代的调整参数,逐步找到函数的局部最小值这个过程可以概括为以下几个步骤:

  1. 初始化参数:选择一个初始点作为参数的起始值,这些参数对应于损失函数的变量!

  2. 计算梯度:在当前参数值处,计算损失函数的梯度(即导数)。梯度指向损失函数变化最快的方向。(或者是求梯度的平均值

  3. 更新参数:根据梯度和一个预先设定的学习率(步长)来更新参数。参数更新的公式通常是:
    θ = θ − η ⋅ ∇ J ( θ ) \theta=\theta-\eta \cdot \nabla J(\theta) θ=θηJ(θ)

一维梯度下降

首先从最简单的一元线性回归来说明梯度下降算法的步骤,损失函数采用回归任务中最常用的均方误差损失。
在这里插入图片描述

L = 1 2 ∑ i = 1 3 [ y i − ( w ^ x i + b ) ] 2 \begin{array}{c} L=\frac{1}{2} \sum_{i=1}^{3}\left[y_{i}-\left(\widehat{w} x_{i}+b\right)\right]^{2} \\ \end{array} L=21i=13[yi(w xi+b)]2

L = 1 2 ∑ i = 1 3 b 2 + 2 ( w ^ x i − y i ) b + ( y i − w ^ x i ) 2 L=\frac{1}{2} \sum_{i=1}^{3} b^{2}+2\left(\widehat{w} x_{i}-y_{i}\right) b+\left(y_{i}-\widehat{w} x_{i}\right)^{2} L=21i=13b2+2(w xiyi)b+(yiw xi)2

在这里插入图片描述

将损失函数求最小值的问题转换为了二次函数求最值的问题,二次函数显然是凸函数,是一个典型的凸优化问题。

多维梯度下降

现在我们对单变量的情况有了更好的理解,让我们考虑一下X[x1,x2,x3…xd]的情况。 即目标函数含有多个变量的问题,区别在于在求导时采用的时求解的是梯度向量的形式。

∇ f ( x ) = [ ∂ f ( x ) ∂ x 1 , ∂ f ( x ) ∂ x 2 , … , ∂ f ( x ) ∂ x d ] ⊤ \nabla f(\mathbf{x})=\left[\frac{\partial f(\mathbf{x})}{\partial x_{1}}, \frac{\partial f(\mathbf{x})}{\partial x_{2}}, \ldots, \frac{\partial f(\mathbf{x})}{\partial x_{d}}\right]^{\top} f(x)=[x1f(x),x2f(x),,xdf(x)]

对每一个变量参数分别进行迭代优化:
x i ← x i − η ∗ ∇ f ( X ) x_{i} \leftarrow x_{i}-\eta * \nabla f(X) xixiηf(X)

在这里插入图片描述

梯度下降算法分类

梯度下降法有三种不同的形式:

  • BGD(Batch GradientDescent):批量梯度下降,每次参数更新使用所有样本
  • SGD(Stochastic GradientDescent):随机梯度下降,每次参数更新只使用1个样本
  • MBGD(Mini-Batch GradientDescent):小批量随机梯度下降,每次参数更新使用小批量数据样本(minibatch)

小批量随机梯度下降

梯度下降(gradient descent)的方法, 这种方法几乎可以优化所有深度学习模型。 它通过不断地在损失函数递减的方向上更新参数来降低误差。

梯度下降最简单的用法是计算损失函数(数据集中所有样本的损失均值) 关于模型参数的导数(在这里也可以称为梯度)。 但实际中的执行可能会非常慢:因为在每一次更新参数之前,我们必须遍历整个数据集。 因此,我们通常会在每次需要计算更新的时候随机抽取一小批样本, 这种变体叫做小批量随机梯度下降(minibatch stochastic gradient descent)。

我们计算小批量的平均损失关于模型参数的导数(也可以称为梯度)。 最后,我们将梯度乘以一个预先确定的正数n,并从当前参数的值中减掉。

w ← w − η ∣ B ∣ ∑ i ∈ B ∂ w l ( i ) ( w , b ) = w − η ∣ B ∣ ∑ i ∈ B x ( i ) ( w ⊤ x ( i ) + b − y ( i ) ) , b ← b − η ∣ B ∣ ∑ i ∈ B ∂ b l ( i ) ( w , b ) = b − η ∣ B ∣ ∑ i ∈ B ( w ⊤ x ( i ) + b − y ( i ) ) . \begin{aligned} \mathbf{w} & \leftarrow \mathbf{w}-\frac{\eta}{|\mathcal{B}|} \sum_{i \in \mathcal{B}} \partial_{\mathbf{w}} l^{(i)}(\mathbf{w}, b)=\mathbf{w}-\frac{\eta}{|\mathcal{B}|} \sum_{i \in \mathcal{B}} \mathbf{x}^{(i)}\left(\mathbf{w}^{\top} \mathbf{x}^{(i)}+b-y^{(i)}\right), \\ b & \leftarrow b-\frac{\eta}{|\mathcal{B}|} \sum_{i \in \mathcal{B}} \partial_{b} l^{(i)}(\mathbf{w}, b)=b-\frac{\eta}{|\mathcal{B}|} \sum_{i \in \mathcal{B}}\left(\mathbf{w}^{\top} \mathbf{x}^{(i)}+b-y^{(i)}\right) . \end{aligned} wbwBηiBwl(i)(w,b)=wBηiBx(i)(wx(i)+by(i)),bBηiBbl(i)(w,b)=bBηiB(wx(i)+by(i)).

( w , b ) ← ( w , b ) − η ∣ B ∣ ∑ i ∈ B ∂ ( w , b ) l ( i ) ( w , b ) . (\mathbf{w}, b) \leftarrow(\mathbf{w}, b)-\frac{\eta}{|\mathcal{B}|} \sum_{i \in \mathcal{B}} \partial_{(\mathbf{w}, b)} l^{(i)}(\mathbf{w}, b) . (w,b)(w,b)BηiB(w,b)l(i)(w,b).

我们通常所说的SGD其实指定就是小批量随机梯度下降算法。

优缺点总结

  • 优点:算法简洁,当学习率取值恰当时,可以收敛到全局最优点(凸函数)或局部最优点(非凸函数)。

缺点

  1. 对超参数学习率比较敏感:过小导致收敛速度过慢,过大又越过极值点。

在这里插入图片描述

  1. 学习率除了敏感,有时还会因其在迭代过程中保持不变,很容易造成算法被卡在鞍点的位置。

在这里插入图片描述

  1. 在较平坦的区域,由于梯度接近于0,优化算法会因误判,在还未到达极值点时,就提前结束迭代,陷入局部极小值。

之后的算法优化是从梯度方面和学习率方面对整个优化器算法进行优化。

动量法

动量法可以看作是:带有动量的随机梯度下降算法。

思想:让参数的更新具有惯性,每一步更新都是由前面梯度的累积当前点梯度g组合而成。

在这里插入图片描述

优化器算法的执行步骤:累加梯度更新+参数更新

累加梯度更新:

v ← α v + ( 1 − α ) g . 其中,  α  为动量参数,  v  为累计梯度,  v  为当前梯度,  η  为学习率  v \leftarrow \alpha v+(1-\alpha) g \text {. 其中, } \alpha \text { 为动量参数, } v \text { 为累计梯度, } v \text { 为当前梯度, } \eta \text { 为学习率 } vαv+(1α)g其中α 为动量参数v 为累计梯度v 为当前梯度η 为学习率 

参数更新:

x ← x − η ∗ v x \leftarrow x-\eta * v xxηv

动手学深度学习中给出的动量法公式:
v t ← β v t − 1 + g t , x t ← x t − 1 − η t v t . \begin{array}{l} \mathbf{v}_{t} \leftarrow \beta \mathbf{v}_{t-1}+\mathbf{g}_{t}, \\ \mathbf{x}_{t} \leftarrow \mathbf{x}_{t-1}-\eta_{t} \mathbf{v}_{t} . \end{array} vtβvt1+gt,xtxt1ηtvt.
我们通过a变量来控制动量。

优点:

  1. 加快收敛能帮助参数在正确的方向上加速前进
    在这里插入图片描述

  2. 可以帮助跳出局部最小值
    在这里插入图片描述

AdaGrad算法

Adagrad优化算法被称为自适应学习率优化算法

之前我们讲的随机梯度下降法,对所有的参数,都是使用相同的、固定的学习率进行优化的,但是不同的参数的梯度差异可能很大,使用相同的学习率,效果不会很好。

举例 : 假设损失函数是 f ( x ) = x 1 2 + 10 x 2 2 , x 和 y 的初值分别为 x 1 = 40 , x 2 = 20 举例: 假设损失函数是 f(x)=x_{1}^{2}+10 x_{2}^{2}, x 和 y 的初值分别为 x_{1}=40, x_{2}=20 举例:假设损失函数是f(x)=x12+10x22,xy的初值分别为x1=40,x2=20
( 通过观察 , 我们即可知道 , x 1 = 0 , x 2 = 0 就是两个参数的极值点 ) (通过观察, 我们即可知道, x_{1}=0, x_{2}=0 就是两个参数的极值点) (通过观察,我们即可知道,x1=0,x2=0就是两个参数的极值点)
→ ∂ l o s s ∂ x 1 = 80 , ∂ l o s s ∂ x 2 = 400 → x 1 \rightarrow \frac{\partial l o s s}{\partial x_{1}}=80, \frac{\partial l o s s}{\partial x_{2}}=400 \quad \rightarrow x_{1} x1loss=80,x2loss=400x1
将要移动的幅度小于 x 2 将移动的幅度而 x 1 距离离极值点 x 1 = 0 是较远的 , 所以 , 我们使用梯度下降法 , 效果并不会好 将要移动的幅度 小于 x_{2} 将移动的幅度而 x_{1} 距离离极值点 x_{1}=0 是较远的, 所以, 我们使用梯度下降法, 效果并不会好 将要移动的幅度小于x2将移动的幅度而x1距离离极值点x1=0是较远的,所以,我们使用梯度下降法,效果并不会好

Adagrad思想:对于不同参数,设置不同的学习率

算法步骤

  1. 方法:对于每个参数,初始化一个累计平方梯度r=0将该参数的梯度平方求和累加到这个变量r上:

g = 1 m ∇ θ ∑ i = 1 m L ( f ( x i , θ ) , y i ) g=\frac{1}{m} \nabla_{\theta} \sum_{i=1}^{m} L\left(f\left(x_{i}, \theta\right), y_{i}\right) g=m1θi=1mL(f(xi,θ),yi)
r ← r + g 2 r \leftarrow r+g^{2} rr+g2

  1. 然后,在更新这个参数的时候,学习率就变为:

θ ← θ − ε r + δ g \theta \leftarrow \theta-\frac{\varepsilon}{\sqrt{r}+\delta} g θθr +δεg

δ 是一个小量,稳定数值计算一般取值为 1 0 − 10 \delta 是一个小量,稳定数值计算一般取值为10^{-10} δ是一个小量,稳定数值计算一般取值为1010

  1. 最后我们进行权重的更新完成整个算法:

w ← w − η r + δ ∗ g w \leftarrow w-\frac{\eta}{\sqrt{r+\delta}} * g wwr+δ ηg

这样,不同的参数由于梯度不同,他们对应的r大小也就不同,所以学习率也就不同,这也就实现了自适应的学习率。

总结:Adagrad 的核心想法就是,如果一个参数的梯度一直都非常大,那么其对应的学习率就变小一点,防止震荡,而一个参数的梯度一直都非常小,那么这个参数的学习率就变大一点,使得其能够更快地更新,这就是Adagrad算法加快深层神经网络的训练速度的核心。

RMSProp算法

RMSProp:Root MeanSquare Propagation均方根传播。

RMSProp是在adagrad的基础上,进一步在学习率的方向上优化经过改进后在2012年提出的一个算法。

g = 1 m ∇ θ ∑ i = 1 m L ( f ( x i , θ ) , y i ) g=\frac{1}{m} \nabla_{\theta} \sum_{i=1}^{m} L\left(f\left(x_{i}, \theta\right), y_{i}\right) g=m1θi=1mL(f(xi,θ),yi)

在adagrad算法中r的变化之和梯度g有关,可能会存在让学习率过小而无法进行控制的问题 在此基础上我们引入了一个新的变量衰减系数p

衰减系数p可以手动调节从而优化学习过程。

r ← ρ r + ( 1 − ρ ) g 2 θ ← θ − ε r + δ g \begin{array}{l} r \leftarrow \rho r+(1-\rho) g^{2} \\ \theta \leftarrow \theta-\frac{\varepsilon}{\sqrt{r+\delta}} g \end{array} rρr+(1ρ)g2θθr+δ εg

Adam算法

Adam算法可以理解为在原始梯度下降的基础上,同时对梯度学习率两个方面同时进行改进。并结合了之前所提出算法的优点。

是使用了动量和自适应学习率的集大成算法,也是目前使用最为广泛的优化器算法之一。

算法步骤

Adam算法的关键组成部分之一是:它使用指数加权移动平均值来估算梯度的动量和二次矩,即它使用状态变量:

  1. 在梯度方向增加动量,同时采用和RMSProp算法相同的学习率调整方法,进行累计梯度平方的计算

v t ← β 1 v t − 1 + ( 1 − β 1 ) g t s t ← β 2 s t − 1 + ( 1 − β 2 ) g t 2 \begin{array}{l} \mathbf{v}_{t} \leftarrow \beta_{1} \mathbf{v}_{t-1}+\left(1-\beta_{1}\right) \mathbf{g}_{t} \\ \mathbf{s}_{t} \leftarrow \beta_{2} \mathbf{s}_{t-1}+\left(1-\beta_{2}\right) \mathbf{g}_{t}^{2} \end{array} vtβ1vt1+(1β1)gtstβ2st1+(1β2)gt2

在这里插入图片描述

  1. 进行偏差的调整与纠正

v ^ t = v t 1 − β 1 t  and  s ^ t = s t 1 − β 2 t . \hat{\mathbf{v}}_{t}=\frac{\mathbf{v}_{t}}{1-\beta_{1}^{t}} \text { and } \hat{\mathbf{s}}_{t}=\frac{\mathbf{s}_{t}}{1-\beta_{2}^{t}} . v^t=1β1tvt and s^t=1β2tst.

  1. 写出更新方程并进行权重的更新操作。(将学习率和动量值结合在一起进行实现)

g t ′ = η v ^ t s ^ t + ϵ . \mathbf{g}_{t}^{\prime}=\frac{\eta \hat{\mathbf{v}}_{t}}{\sqrt{\hat{\mathbf{s}}_{t}}+\epsilon} . gt=s^t +ϵηv^t.

x t ← x t − 1 − g t ′ \mathbf{x}_{t} \leftarrow \mathbf{x}_{t-1}-\mathbf{g}_{t}^{\prime} xtxt1gt

w ← w − η r ^ + δ ∗ v ^ w \leftarrow w-\frac{\eta}{\sqrt{\hat{r}+\delta}} * \hat{v} wwr^+δ ηv^

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

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

相关文章

在InternStudio上创建一台GPU服务器

填写配置 创建完成 ssh连接,并测试常用指令 查看开发机信息 查看gpu信息 创建conda环境 跑个test

可重入锁深入学习(有码)

【摘要】 ​今天,梳理下java中的常用锁,但在搞清楚这些锁之前,先理解下 “临界区”。临界区在同步的程序设计中,临界区段活称为关键区块,指的是一个访问共享资源(例如:共享设备或是共享存储器&a…

9. Python的魔法函数

Python中的魔法函数 在Python中魔法函数是在为类赋能,使得类能够有更多操作。通过重写类中的魔法函数,可以完成很多具体的任务 1. __str__ 通过str魔法函数,可以设置对类的实例的 print() 内容 2. __len__ 通过len魔法函数,可…

tessy 集成测试:小白入门指导手册

目录 1,创建集成测试模块且分析源文件 2,设置测试环境 3,TIE界面设置相关函数 4,SCE界面增加用例 5,编辑数据 6,用例所对应的测试函数序列 7,添加 work task 函数 8,为测试场景添加函数 9,为函数赋值 10,编辑时间序列的数值 11,执行用例 12,其他注意事项…

计算机毕设:服装购物管理系统(Java+Springboot+MySQL+Tomcat),完整源代码+数据库+毕设文档+部署说明

本文关键字:Java编程;Springboot框架;毕业设计;毕设项目;编程实战;医护人员管理系统;项目源代码;程序数据库;毕设文档;项目部署说明; 一、项目说…

Java中JUC包详解

文章目录 J.U.C.包LockReadWriteLockLockSupportAQSReentrantLock对比synchronized加锁原理释放锁原理 CountDownLatchCyclicBarrierSemaphore J.U.C.包 java.util.concurrent,简称 J.U.C.。是Java并发工具包,提供了在多线程编程中常用的工具类和框架&a…

实战检验:Orange Pi AIpro AI开发板的性能测试与使用体验

文章目录 前言Orange Pi AIpro 简介Orange Pi AIpro 体验将Linux镜像烧录到TF卡YOLO识别视频中物体肺部CT识别 Orange Pi AIpro 总结 前言 Orange Pi AIpro,作为首款基于昇腾技术的AI开发板,它集成了高性能图形处理器,配备8GB/16GB LPDDR4X内…

MySQL复合查询(重点)

前面我们讲解的mysql表的查询都是对一张表进行查询,在实际开发中这远远不够。 基本查询回顾 查询工资高于500或岗位为MANAGER的雇员,同时还要满足他们的姓名首字母为大写的J mysql> select * from emp where (sal>500 or jobMANAGER) and ename l…

强化学习:bellman方程求解state value例题

最近在学习强化学习相关知识,强烈推荐西湖大学赵世钰老师的课程,讲解的非常清晰流畅,一路学习下来令人身心大爽,感受数学抽丝剥茧,化繁为简的神奇魅力。 bellman方程还是比较容易理解的:当前状态下的state …

嵌入式linux系统中GDB调试器详解

前言 GDB全称GNU symbolic debugger,它是诞生于GNU开源组织的(同时诞生的还有 GCC、Emacs 等)UNIX及UNIX-like下的调试工具,是Linux下最常用的程序调试器,GDB 支持调试多种编程语言编写的程序,包括C、C++、Go、Objective-C、OpenCL、Ada 等。但是在实际应用中,GDB 更常…

linux_进程周边知识——理解冯诺依曼体系结构

前言: 本篇内容是为了让友友们较好地理解进程的概念, 而在真正了解进行概念之前, 要先了解一下冯诺依曼体系结构。 所以博主会先对冯诺伊曼体系结构进行解释, 然后再讲解进程的概念。 ps: 本篇内容适合了解一些linux指…

github中下载zip后,本地仓库如何与github上的项目相关联

有时候网速问题&#xff0c;git clone 太慢&#xff0c;就直接下载zip文件&#xff0c;然后再进行关联 1、下载zip 2、解压&#xff0c;把文件夹名称中-main去掉 3、进行关联 cd <repo> git init git add . git remote add origin https://github.com/<user>/&l…

springboot在线教育平台-计算机毕业设计源码68562

摘要 在数字化时代&#xff0c;随着信息技术的飞速发展&#xff0c;在线教育已成为教育领域的重要趋势。为了满足广大学习者对于灵活、高效学习方式的需求&#xff0c;基于Spring Boot的在线教育平台应运而生。Spring Boot以其快速开发、简便部署以及良好的可扩展性&#xff0c…

第一个基于FISCOBCOS的前后端项目(发行转账)(已开源)

本文旨在介绍一个简单的基于fiscobcos的前后端网站应用。Springbootjs前后端不分离。 所使用到的合约也是一个最基本的。首先您需要知道的是完整项目分为三部分&#xff0c;1是区块链平台webase搭建&#xff08;此项目使用节点前置webase-front即可&#xff09;&#xff0c;2是…

帕金森病患者在日常饮食中需要注意哪些特殊的营养需求?

帕金森病患者的特殊营养需求 帕金森病患者在日常饮食中需要特别注意以下几个方面的营养需求&#xff1a; 蛋白质摄入&#xff1a;由于帕金森病药物可能与蛋白质竞争同一种转运蛋白进入大脑&#xff0c;因此建议将蛋白质的摄入量分散在一天中的多餐中&#xff0c;避免集中在单一…

【python学习】多线程编程的背景、定义、特点、优缺点、使用场景和示例以及和单线程的区别

引言 随着计算机技术的发展&#xff0c;多核处理器已经成为了主流,为了充分利用多核处理器带来的并行计算能力&#xff0c;提高程序的执行效率和响应速度&#xff0c;多线程编程变得尤为重要 Python作为一种高级编程语言&#xff0c;提供了多线程编程的支持&#xff0c;允许开发…

力扣 24两两交换链表中节点

画图 注意有虚拟头结点 注意判断时先判断cur->next ! nullptr,再判断cur->next->next ! nullptr 注意末尾返回dumyhead->next&#xff0c;用新建result指针来接并返回 class Solution { public:ListNode* swapPairs(ListNode* head) {ListNode *dummyhead new …

【2024_CUMCM】时间序列1

目录 概念 时间序列数据 时期和时点时间序列 数值变换规律 长期趋势T 季节趋势S 循环变动C 不规则变动I 叠加和乘积模型 叠加模型 相互独立 乘积模型 相互影响 注 spss缺失值填补 简单填补 五种填补方法 填补原则 1.随机缺失 2.完全随机缺失 3.非随机缺失…

WGCLOUD登录页面支持输入验证码吗

支持的 v3.5.3版本开始&#xff0c;WGCLOUD支持在登录页面配置输入验证码&#xff0c;我们可以根据自己的场景需要&#xff0c;配置是否在登录页面显示验证码&#xff0c;如下说明 登录页面添加验证码说明 - WGCLOUD

酒店管理系统小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;酒店管理员管理&#xff0c;房间类型管理&#xff0c;房间信息管理&#xff0c;订单信息管理&#xff0c;系统管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;房间信息…