深度学习笔记之优化算法(五)AdaGrad算法的简单认识

深度学习笔记之优化算法——AdaGrad算法的简单认识

  • 引言
    • 回顾:动量法与Nesterov动量法
    • 优化学习率的合理性
    • AdaGrad算法的简单认识
    • AdaGrad的算法过程描述
    • (2023/10/10)补充:AdaGrad示例代码

引言

上一节对 Nesterov \text{Nesterov} Nesterov动量法进行了简单认识,本节将介绍 AdaGrad \text{AdaGrad} AdaGrad方法。

回顾:动量法与Nesterov动量法

关于动量法 ( Momentum ) (\text{Momentum}) (Momentum)迭代过程使用数学符号表示如下:
{ m t = β ⋅ m t − 1 + ( 1 − β ) ⋅ ∇ θ ; t − 1 J ( θ t − 1 ) θ t = θ t − 1 − η ⋅ m t \begin{cases} m_t = \beta \cdot m_{t-1} + (1 - \beta) \cdot \nabla_{\theta;t-1} \mathcal J(\theta_{t-1}) \\ \theta_t = \theta_{t-1} - \eta \cdot m_t \end{cases} {mt=βmt1+(1β)θ;t1J(θt1)θt=θt1ηmt

  • 其中 β \beta β表示动量因子,它可理解为权衡历史梯度信息 m t − 1 m_{t-1} mt1当前梯度信息 ∇ θ ; t − 1 J ( θ t − 1 ) \nabla_{\theta;t-1} \mathcal J(\theta_{t-1}) θ;t1J(θt1)之间比例的量,或者说:由于历史梯度信息参与当前迭代步骤的梯度贡献, β \beta β表示历史梯度信息的贡献衰减得有多快

  • η \eta η表示学习率,它描述是沿着梯度更新方向前进的步长大小。而动量法的核心思想在于:合理利用历史梯度信息,结合当前迭代步骤的梯度信息,共同优化当前迭代步骤的梯度更新方向

同理, Nesterov \text{Nesterov} Nesterov动量法的核心思想与动量法基本一致,只不过将当前迭代步骤的梯度信息替换为超前梯度信息
{ m t = β ⋅ m t − 1 + ( 1 − β ) ⋅ ∇ θ ; t − 1 J ( θ t − 1 + γ ⋅ m t − 1 ) θ t = θ t − 1 − η ⋅ m t \begin{cases} m_t = \beta \cdot m_{t-1} + (1 - \beta) \cdot \nabla_{\theta;t-1} \mathcal J(\theta_{t-1} + \gamma \cdot m_{t-1}) \\ \theta_t = \theta_{t-1} - \eta \cdot m_t \end{cases} {mt=βmt1+(1β)θ;t1J(θt1+γmt1)θt=θt1ηmt

可以看出:无论是动量法还是 Nesterov \text{Nesterov} Nesterov动量法,它们的底层逻辑都是针对梯度的更新方向,也就是 m t m_t mt自身;我们不否认,在 m t m_t mt优化过程中,也伴随着梯度大小的变化。但真正掌握梯度大小的参数,是学习率 η \eta η。而在这两种算法中, η \eta η至始至终都是一个固定的超参数。我们是否也可以对学习率进行优化 ? ? ?

优化学习率的合理性

在优化学习率之前,需要认识以下:对于学习率的优化是否是有必要 ? ? ?在线搜索方法(步长角度)中,我们从精确搜索非精确搜索两种角度对步长进行了充分的描述,并延伸出一系列的搜索准则,如 Armijo \text{Armijo} Armijo准则、 wolfe \text{wolfe} wolfe准则等等。

  • 这个小例子可能不是很贴切~因为无论是精确搜索还是非精确搜索,它们都建立在方向固定是负梯度方向这个条件下。但是像动量法或者是 Nesterov \text{Nesterov} Nesterov动量法,它的梯度方向会随着迭代步骤发生变化。
  • 但也可以从侧面看出,步长的选择是有优劣之分的,并不是一成不变的。

基于上面的简单描述,无论使用哪类方法,做为调整梯度大小(步长)学习率 η \eta η都不应该是一个确定的值。我们不否认:梯度向量自身会随着迭代步骤的增加而减小,并向零向量逼近;但如果学习率不跟随梯度向量进行变化,可能会出现下面的情况:

  • 极值点附近无法收敛。这种情况可能发生的条件是:在某迭代过程中,即便梯度信息已经足够小了,但由于学习率是定值,依然会导致虽然梯度方向指向正确,但梯度向量不够小穿过极值点
    梯度信息不够小而导致穿过极值点
  • 在后续的迭代过程中,它可能都无法收敛至极值点,从而在极值点周围震荡
    无法收敛至极值点产生震荡

因而无论使用哪类方法,关于学习率的变化趋势我们都希望:学习率随着迭代过程慢慢减小。既然已经知道了目标,我们可以想到一种硬核的学习率优化方式:学习率随着每一次迭代减小一个固定的数值,当学习率减小至 0 0 0时,整个学习过程结束

很明显,这种方式自然是不够优秀的,它的缺陷主要体现在:

  • 减小的固定数值人为设定的,实际上它也间接地人为设定了迭代步骤的上界。如果迭代次数超过了该上界——即便是没有到达极值点,也要强行将迭代停止
  • 相反地,如果人为设定的固定数值过小——意味着在迭代次数内已经到达极值点,它会一直在极值点处震荡,直到学习率为 0 0 0

可以看出:人为设定学习率的衰减不可取的,但也给我们提供新的思路:是否能够让学习率在迭代过程中自主进行调整 ? ? ?

AdaGrad算法的简单认识

AdaGrad \text{AdaGrad} AdaGrad算法的核心思想是:使学习率在算法迭代过程中进行自适应调节,而自适应调节同样依靠历史梯度信息。关于 AdaGrad \text{AdaGrad} AdaGrad的迭代过程使用数学符号表示如下:
{ G t = ∇ θ ; t − 1 J ( θ t − 1 ) R t ⇐ R t − 1 + G t ⊙ G t θ t ⇐ θ t − 1 − η R t + ϵ ⊙ G t \begin{cases} \mathcal G_t = \nabla_{\theta;t-1} \mathcal J(\theta_{t-1}) \\ \mathcal R_t \Leftarrow \mathcal R_{t-1} + \mathcal G_t \odot \mathcal G_t \\ \begin{aligned} \theta_t \Leftarrow \theta_{t-1} - \frac{\eta}{\sqrt{\mathcal R_t} + \epsilon} \odot \mathcal G_t \end{aligned} \end{cases} Gt=θ;t1J(θt1)RtRt1+GtGtθtθt1Rt +ϵηGt
其中:

  • G t \mathcal G_t Gt表示当前步骤的梯度方向
  • R t \mathcal R_t Rt动量法中的 m t m_t mt一样,是历史信息的一个累积载体;而这里的历史信息并不是单纯的历史梯度信息 G t \mathcal G_t Gt,而是 G t \mathcal G_t Gt与自身的内积结果 G t ⊙ G t \mathcal G_t \odot \mathcal G_t GtGt
  • ϵ \epsilon ϵ是一个较小的正数,仅为保证分母项不为 0 0 0

很明显,由于 G t ∈ R p \mathcal G_t \in \mathbb R^p GtRp( p p p表示权重空间维数),因而 G t ⊙ G t = ∥ G t ∥ 2 ∈ R \mathcal G_t \odot \mathcal G_t = \|\mathcal G_t \|^2 \in \mathbb R GtGt=Gt2R,是一个实数;因而 R t = R t + G t ⊙ G t = ∑ i = 1 t ∥ G i ∥ 2 ∈ R \begin{aligned}\mathcal R_t = \mathcal R_t + \mathcal G_t \odot \mathcal G_t = \sum_{i=1}^t \|\mathcal G_i \|^2 \in \mathbb R \end{aligned} Rt=Rt+GtGt=i=1tGi2R也是一个实数观察最后一项关于学习率的优化 η ⇒ η R t + ϵ \begin{aligned}\eta \Rightarrow \frac{\eta}{\sqrt{\mathcal R_t} + \epsilon}\end{aligned} ηRt +ϵη

  • 关于分母部分: R t + ϵ = ∑ i = 1 t ∥ G i ∥ 2 + ϵ \sqrt{\mathcal R_t} + \epsilon = \sqrt{\sum_{i=1}^t \|\mathcal G_i\|^2} + \epsilon Rt +ϵ=i=1tGi2 +ϵ可以发现:这个函数是单调递增的,也就是说:关于 η \eta η的优化结果只会减小,不会增加;在梯度结果 G t \mathcal G_t Gt存在较大变化时, η \eta η会相应减小
  • 可以将 G t \mathcal G_t Gt拿到分子上,可以得到: η ⋅ G t R t + ϵ \begin{aligned}\frac{\eta \cdot \mathcal G_t}{\sqrt{\mathcal R_t} + \epsilon}\end{aligned} Rt +ϵηGt(由于 ⊙ \odot 的两项分别是实数与向量,因而这里的内积 ⊙ \odot 就是乘法),其中分子的项 η ⋅ G t \eta \cdot \mathcal G_t ηGt实际上就是真实更新梯度,而 AdaGrad \text{AdaGrad} AdaGrad的操作就是将真实更新梯度执行标准化操作
    这种操作和批标准化( Batch Normalization \text{Batch Normalization} Batch Normalization)中也出现过类似的形式。该部分欢迎小伙伴们一起讨论~

这种学习率优化的优势在于:

  • 若某迭代步骤 t t t梯度 G t = ∇ θ ; t − 1 J ( θ t − 1 ) \mathcal G_t = \nabla_{\theta;t-1} \mathcal J(\theta_{t-1}) Gt=θ;t1J(θt1)过大,其会相应地得到一个快速下降的学习率
  • 相反,对于梯度 G t \mathcal G_t Gt较小的部分,虽然学习率依然在减小,但但减小的幅度也会下降。这种情况会使参数在更新过程中面对平缓的倾斜方向会存在不错的收敛效果

AdaGrad \text{AdaGrad} AdaGrad算法对于学习率的优化也存在明显的缺陷

  • 由于初始化状态下的参数可能是随机生成的,这种情况下有可能导致初始梯度 G \mathcal G G的结果极大/变化非常剧烈,而这种剧烈变化会使得 R t \mathcal R_t Rt累积了较大的内积信息,从而导致本在有效收敛的过程中,由于学习率过早地、并且过量的减少,最终使:参数没有动力收敛到预期的极值点而产生欠拟合

AdaGrad的算法过程描述

基于 AdaGrad \text{AdaGrad} AdaGrad的算法步骤表示如下:
初始化操作

  • 全局学习率 η \eta η,初始化参数 θ \theta θ
  • 超参数 ϵ = 1 0 − 7 \epsilon = 10^{-7} ϵ=107,梯度累积信息 R = 0 \mathcal R = 0 R=0

算法过程

  • While \text{While} While没有达到停止准则 do \text{do} do
  • 从训练集 D \mathcal D D中采集出包含 k k k个样本的小批量 { ( x ( i ) , y ( i ) ) } i = 1 k \{(x^{(i)},y^{(i)})\}_{i=1}^k {(x(i),y(i))}i=1k
  • 计算当前步骤参数 θ \theta θ梯度信息
    G ⇐ 1 k ∑ i = 1 k ∇ θ L [ f ( x ( i ) ; θ ) , y ( i ) ] \mathcal G \Leftarrow \frac{1}{k} \sum_{i=1}^k \nabla_{\theta} \mathcal L[f(x^{(i)};\theta),y^{(i)}] Gk1i=1kθL[f(x(i);θ),y(i)]
  • 使用 R \mathcal R R梯度内积进行累积
    R ⇐ R + G ⊙ G \mathcal R \Leftarrow \mathcal R + \mathcal G \odot \mathcal G RR+GG
  • 计算更新的梯度量
    Δ θ = − η ϵ + R ⊙ G \Delta \theta = - \frac{\eta}{\epsilon + \sqrt{\mathcal R}} \odot \mathcal G Δθ=ϵ+R ηG
  • 更新梯度 θ \theta θ
    θ ⇐ θ + Δ θ \theta \Leftarrow \theta + \Delta \theta θθ+Δθ
  • End While \text{End While} End While

(2023/10/10)补充:AdaGrad示例代码

由于之前的算法如动量法、 Nesterov \text{Nesterov} Nesterov动量法,这些方法核心是在随机梯度下降算法的基础上,对梯度向量的方向进行优化;因而在之前的代码中,关于步长的描述,可以使用最速下降法来摸鱼~ 但 AdaGrad \text{AdaGrad} AdaGrad算法是对梯度向量的大小(步长),也就是对学习率进行优化,因此这次我们老老实实地使用学习率进行实现~

和之前的文章一样,这里使用标准二次型 f ( x ) = x T Q x ; x = ( x 1 , x 2 ) T ; Q = ( 0.5 0 0 20 ) f(x) = x^T \mathcal Q x;x = (x_1,x_2)^T;\mathcal Q = \begin{pmatrix}0.5 \quad 0 \\ 0 \quad 20\end{pmatrix} f(x)=xTQx;x=(x1,x2)T;Q=(0.50020)作为目标函数,起始点位置: ( 8 1 ) T (8 \quad 1)^T (81)T,对应代码表示如下:

import numpy as np
import math
import matplotlib.pyplot as plt
from tqdm import tqdmdef f(x, y):return 0.5 * (x ** 2) + 20 * (y ** 2)def ConTourFunction(x, Contour):return math.sqrt(0.05 * (Contour - (0.5 * (x ** 2))))def Derfx(x):return xdef Derfy(y):return 40 * ydef DrawBackGround():ContourList = [0.2, 1.0, 4.0, 8.0, 16.0, 32.0]LimitParameter = 0.0001plt.figure(figsize=(10, 5))for Contour in ContourList:# 设置范围时,需要满足x的定义域描述。x = np.linspace(-1 * math.sqrt(2 * Contour) + LimitParameter, math.sqrt(2 * Contour) - LimitParameter, 200)y1 = [ConTourFunction(i, Contour) for i in x]y2 = [-1 * j for j in y1]plt.plot(x, y1, '--', c="tab:blue")plt.plot(x, y2, '--', c="tab:blue")def AdaGrad():Start = (8.0, 1.0)LocList = list()LocList.append(Start)Eta = 0.5Epsilon = 0.0000001R = 0.0Delta = 0.1while True:DerStart = (Derfx(Start[0]),Derfy(Start[1]))InnerProduct = (DerStart[0] ** 2) + (DerStart[1] ** 2)R += InnerProductUpdateEta = -1 * (Eta / (Epsilon + math.sqrt(R)))UpdateMessage = (UpdateEta * DerStart[0],UpdateEta * DerStart[1])Next = (Start[0] + UpdateMessage[0],Start[1] + UpdateMessage[1])DerNext = (Derfx(Next[0]),Derfy(Next[1]))# 这里终止条件使用梯度向量的模接近于Delta,一个很小的正值;if math.sqrt((DerNext[0] ** 2) + (DerNext[1] ** 2)) < Delta:breakelse:LocList.append(Next)Start = NextplotList = list()DrawBackGround()for (x, y) in tqdm(LocList):plotList.append((x, y))plt.scatter(x, y, s=30, facecolor="none", edgecolors="tab:red", marker='o')if len(plotList) < 2:continueelse:plt.plot([plotList[0][0], plotList[1][0]], [plotList[0][1], plotList[1][1]], c="tab:red")plotList.pop(0)plt.show()if __name__ == '__main__':AdaGrad()

对应图像结果表示如下:
AdaGrad示例
观察上述图像,可以发现:

  • 关于初始位置梯度非常大,这导致学习率有一个大幅度地削减。这具体表现在:一开始更新点移动的步长非常大,但仅仅在有限次地迭代步骤内,这个步长被缩减成非常小的数值
  • 观察中后段的迭代步骤,发现此时更新移动的步长极小,验证了《深度学习(花书)》 P187 8.5.1 AdaGrad \text{P187 8.5.1 AdaGrad} P187 8.5.1 AdaGrad中的:净效果在参数空间中更为平缓的倾斜方向会取得更大的进步

但是如果将上述代码中的衡量终止时刻的Delta逐步趋近于 0 0 0,观察算法的迭代次数的变化情况:
迭代步骤与终止条件之间的关系

观察上图,其中横坐标表示参数Delta趋近于 0 0 0的程度纵坐标表示相应 AdaGrad \text{AdaGrad} AdaGrad算法的迭代次数,可以发现:Delta趋近于 0 0 0的过程中,即便存在一个很小的变化,但依然需要极高的迭代步骤进行收敛。因此可以判断 AdaGrad \text{AdaGrad} AdaGrad算法并不具备二次终止性

Reference \text{Reference} Reference
“随机梯度下降、牛顿法、动量法、Nesterov、AdaGrad、RMSprop、Adam”,打包理解对梯度下降的优化
《深度学习(花书)》 P187 8.5.1 AdaGrad \text{P187 8.5.1 AdaGrad} P187 8.5.1 AdaGrad

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

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

相关文章

算法题:买卖股票的最佳时机 II (贪心算法解决股票问题)

这道题是贪心算法的中级难度练习题&#xff0c;由于题目设定&#xff0c;整个价格都是透明的&#xff0c;这里并不涉及需要预测股票涨势的问题。解决思路不难&#xff0c;就是一旦股票价格开始下降了就买入&#xff0c;一旦上升了&#xff0c;就赶紧卖出。&#xff08;完整题目…

SpringBoot 如何使用 Grafana 进行可视化监控

使用Spring Boot Sleuth进行分布式跟踪 在现代分布式应用程序中&#xff0c;跟踪请求和了解应用程序的性能是至关重要的。Spring Boot Sleuth是一个分布式跟踪解决方案&#xff0c;它可以帮助您在分布式系统中跟踪请求并分析性能问题。本文将介绍如何在Spring Boot应用程序中使…

DC2DC电源设计注意事项--1,Feedback

电源采集图如下图 Feedback 采集电压点应该在靠近负载侧。这样可以减少大电流导线导致的电压差&#xff0c;真实反应输出电压值 FB_1P21采集电路靠近芯片侧&#xff0c; 2.1&#xff0c;采集分压电路上侧为Vout Vnoise, 那么一分压就噪声就小了。假如采集电路远离芯片侧&…

CSS学习基础知识

CSS学习笔记 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice-width,…

Java-Atomic原子操作类详解及源码分析,Java原子操作类进阶,LongAdder源码分析

文章目录 一、Java原子操作类概述1、什么是原子操作类2、为什么要用原子操作类3、CAS入门 二、基本类型原子类1、概述2、代码实例 三、数组类型原子类1、概述2、代码实例 四、引用类型原子类1、概述2、AtomicReference3、ABA问题与AtomicStampedReference4、一次性修改&#xf…

ubuntu疑难杂症

1.ubuntu 使用apt 安装软件时提示出现不能获得lock $ sudo rm /var/lib/dpkg/lock$ sudo dpkg --configure -a$ sudo rm /var/lib/apt/lists/locksudo rm /var/lib/dpkg/lock sudo rm /var/lib/dpkg/lock-frontend sudo rm /var/cache/apt/archives/lock

手机待办事项app哪个好?

手机是日常很多人随身携带的设备&#xff0c;手机除了拥有通讯功能外&#xff0c;还能帮助大家高效管理日常工作&#xff0c;借助手机上的待办事项提醒APP可以快速地帮助大家规划日常事务&#xff0c;提高工作的效率。 过去&#xff0c;我也曾经在寻找一款能够将工作任务清晰罗…

区块链技术的飞跃: 2023年的数字革命

随着时代的推进和技术的不断创新&#xff0c;2023年成为区块链技术飞跃发展的一年。区块链&#xff0c;一个曾经只是数字货币领域的技术&#xff0c;现在已经逐渐渗透到各个行业&#xff0c;成为推动数字经济发展的重要力量。在这个数字革命的时代&#xff0c;我们探讨区块链技…

水库大坝除险加固安全监测系统解决方案

一、系统背景 为贯彻落实《办公厅关于切实加强水库除险加固和运行管护工作的通知》&#xff08;〔2021〕8号&#xff09;要求&#xff0c;完成“十四五”小型病险水库除险加固、雨水情测报和大坝安全监测设施建设任务&#xff0c;规范项目管理&#xff0c;消除安全隐患&#xf…

Hadoop设置hdfs全局指令

在终端进入用户个人环境变量配置文件 vim ~/.bashrc 然后添加如下内容 export PATH$PATH:/usr/local/hadoop/bin 添加到你的hadoop下载目录的bin目录为止就可以了 重新激活一下配置文件 source ~/.bashrc hdfs有专属于自己的文件存储目录,加上特殊的指令就可以箱终端一…

Python“梦寻”淘宝天猫店铺所有数据接口,淘宝店铺所有商品数据API接口,淘宝API接口申请指南(含代码示例)

获取淘宝店铺所有商品数据的接口可以通过淘宝开放平台获取。 具体操作步骤如下&#xff1a; 在淘宝开放平台注册成为开发者&#xff0c;并创建一个应用&#xff0c;获取到所需的 App Key 和 App Secret 等信息。使用获取到的 App Key 和 App Secret&#xff0c;进行签名和认证…

@MultipartConfig注解

前言&#xff1a; 在学习Javaweb的Servlet文件上传和下载的过程中&#xff0c;我们会遇到一个特殊的注解---MultipartConfig。 MultipartConfig的适用情况&#xff1a; 1.文件上传: 当您的应用程序需要接收用户上传的文件时&#xff0c;可以在相应的 Servlet 上使用 Multipart…

C++ - 智能指针 - auto_ptr - unique_ptr - std::shared_ptr - weak_ptr

前言 C当中的内存管理机制需要我们自己来进行控制&#xff0c;比如 在堆上 new 了一块空间&#xff0c;那么当这块空间不需要再使用的时候。我们需要手动 delete 掉这块空间&#xff0c;我们不可能每一次都会记得&#xff0c;而且在很大的项目程序当中&#xff0c;造成内存泄漏…

milvus测试

milvus测试 目标 其实&#xff0c;我应该弄明白他的输入输出分别是什么&#xff1f; 输入是图片&#xff0c;图片经过ml模型进行特征提取&#xff0c;再在milvus中进行存储或者检索 部署 ✘ delldell-Precision-3630-Tower  /nvme/baum/git-project/milvus   master …

SpringBoot 如何使用 Ehcache 作为缓存

使用Spring Boot Sleuth进行分布式跟踪 在现代分布式应用程序中&#xff0c;跟踪请求和了解应用程序的性能是至关重要的。Spring Boot Sleuth是一个分布式跟踪解决方案&#xff0c;它可以帮助您在分布式系统中跟踪请求并分析性能问题。本文将介绍如何在Spring Boot应用程序中使…

选择适合变更管理的产品开发工具的要点和建议

什么是变更管理&#xff1f; 变更管理是指导组织改进的学科。由于可观察到的行为变化&#xff0c;它会导致永久性变化。它确保您的组织以彻底、有序和可持续的方式学习和改进。成功的改进项目需要个人和团队保持一致&#xff0c;他们有共同的愿景&#xff0c;他们知道如何定义…

MidJourney | AI绘画也有艺术

免费绘画&#xff0c;体验更多AI可关&注公&众&号&#xff1a;AI研究工厂

大数据学习(2)Hadoop-分布式资源计算hive(1)

&&大数据学习&& &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 承认自己的无知&#xff0c;乃是开启智慧的大门 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4dd;支持一下博>主哦&#x…

如何将gif变成视频?3个转换方法

如何将gif变成视频&#xff1f;没错&#xff0c;GIF是一种动态图片格式&#xff0c;与视频在本质上有所区别。在一些自媒体平台上&#xff0c;我们无法直接分享GIF格式的图片&#xff0c;但可以将其转换为视频格式后再进行分享。因此&#xff0c;当我们想要分享我们喜欢的GIF图…

香港硬防服务器的防御有什么优缺点?

​  在选择服务器时&#xff0c;安全性是一个重要的考虑因素。而对于那些需要高级防御功能的用户来说&#xff0c;香港硬防服务器可能是一个不错的选择。它也有一些优缺点需要考虑。 香港硬防服务器优点&#xff1a; 强大的硬件资源&#xff1a;香港硬防服务器拥有足够的硬件…