学习率设置

news2024/11/28 19:30:02

        在我们刚刚接触深度学习时,对学习率只有一个很基础的认知,当学习率过大的时候会导致模型难以收敛,过小的时候会收敛速度过慢,其实学习率是一个十分重要的参数,合理的学习率才能让模型收敛到最小点而非局部最优点或鞍点。

1 什么是学习率

        学习率是训练神经网络的重要超参数之一,它代表在每一次迭代中梯度向损失函数最优解移动的步长,通常用 η η η 表示。它的大小决定网络学习速度的快慢。在网络训练过程中,模型通过样本数据给出预测值,计算代价函数并通过反向传播来调整参数。重复上述过程,使得模型参数逐步趋于最优解从而获得最优模型。在这个过程中,学习率负责控制每一步参数更新的步长。合适的学习率可以使代价函数以合适的速度收敛到最小值。


2 学习率对网络的影响

        梯度更新公式: θ = θ − η ∂ ∂ θ J ( θ ) \theta = \theta - \eta\frac{\partial}{\partial \theta}J(\theta) θ=θηθJ(θ)

        根据上述公式我们可以看到,如果学习率 η η η 较大,那么参数的更新速度就会很快,可以加快网络的收敛速度,但如果学习率过大,可能会导致参数在最优解附近震荡,代价函数难以收敛,甚至可能会错过最优解,导致参数向错误的方向更新,代价函数不仅不收敛反而可能爆炸(如图1a所示)。

        如果学习率 η η η 较小,网络可能不会错过最优点,但是网络学习速度会变慢。同时,如果学习率过小,则很可能会陷入局部最优点(如图1b所示)。

        因此,只有找到合适的学习率,才能保证代价函数以较快的速度逼近全局最优解。

图1:不同学习率下的梯度更新

        对于深度学习模型训练时,在梯度下降法中,固定学习率时,当到达收敛状态时,会在最优值附近一个较大的区域内摆动;而当随着迭代轮次的增加而减小学习率,会使得在收敛时,在最优值附近一个更小的区域内摆动。(之所以曲线震荡朝向最优值收敛,是因为在每一个mini-batch中都存在噪音)。如下图所示。


3 学习率的设置

        那么如何去设置学习率这个超参数呢?总体上可以分为两种:人工调整和策略调整

        人工调整学习率一般是根据我们的经验值进行尝试,通常我们会尝试性的将初始学习率设为:0.1,0.01,0.001,0.0001等来观察网络初始阶段epoch的loss情况:

  • 如果训练初期loss出现梯度爆炸或NaN这样的情况(暂时排除其他原因引起的loss异常),说明初始学习率偏大,可以将初始学习率降低10倍再次尝试;
  • 如果训练初期loss下降缓慢,说明初始学习率偏小,可以将初始学习率增加5倍或10倍再次尝试;
  • 如果训练一段时间后loss下降缓慢或者出现震荡现象,可能训练进入到一个局部最小值或者鞍点附近。如果在局部最小值附近,需要降低学习率使训练朝更精细的位置移动;如果处于鞍点附件,需要适当增加学习率使步长更大跳出鞍点。
  • 如果网络权重采用随机初始化方式从头学习,有时会因为任务复杂,初始学习率需要设置的比较小,否则很容易梯度飞掉带来模型的不稳定(振荡)。这种思想也叫做Warmup,在预热的小学习率下,模型可以慢慢趋于稳定,等模型相对稳定后再选择预先设置的学习率进行训练,使得模型收敛速度变得更快,模型效果更佳。
  • 如果网络基于预训练权重做的微调(finetune),由于模型在原数据集上以及收敛,有一个较好的起点,可以将初始学习率设置的小一些进行微调,比如0.0001。

        策略调整学习率包括固定策略的学习率衰减和自适应学习率衰减,由于学习率如果连续衰减,不同的训练数据就会有不同的学习率。当学习率衰减时,在相似的训练数据下参数更新的速度也会放慢,就相当于减小了训练数据对模型训练结果的影响。为了使训练数据集中的所有数据对模型训练有相等的作用,通常是以epoch为单位衰减学习率。

        在模型优化中,常用到的几种学习率衰减方法有:分段常数衰减、多项式衰减、指数衰减、自然指数衰减、余弦衰减、线性余弦衰减、噪声线性余弦衰减。


3.1 学习率衰减常用参数有哪些

参数名称参数说明
learning_rate初始学习率
global_step用于衰减计算的全局步数,非负,用于逐步计算衰减指数
decay_steps衰减步数,必须是正值,决定衰减周期
decay_rate衰减率
end_learning_rate最低的最终学习率
cycle学习率下降后是否重新上升
alpha最小学习率
num_periods衰减余弦部分的周期数
initial_variance噪声的初始方差
variance_decay衰减噪声的方差

3.2 分段常数衰减(Piecewise Decay)

        ​分段常数衰减需要事先定义好的训练次数区间,在对应区间置不同的学习率的常数值,一般情况刚开始的学习率要大一些,之后要越来越小,要根据样本量的大小设置区间的间隔大小,样本量越大,区间间隔要小一点。下图即为分段常数衰减的学习率变化图,横坐标代表训练次数,纵坐标代表学习率。


图2:分段常数衰减的学习率变化图

3.3 指数衰减(Exponential Decay)

        ​以指数衰减方式进行学习率的更新,学习率的大小和训练次数指数相关,其更新规则为:
d e c a y e d _ l e a r n i n g _ r a t e = l e a r n i n g _ r a t e ∗ d e c a y _ r a t e g l o b a l _ s t e p d e c a y _ s t e p s decayed{\_}learning{\_}rate =learning{\_}rate*decay{\_}rate^{\frac{global{\_step}}{decay{\_}steps}} decayed_learning_rate=learning_ratedecay_ratedecay_stepsglobal_step

        这种衰减方式简单直接,收敛速度快,是最常用的学习率衰减方式,如下图所示,绿色的为学习率随训练次数的指数衰减方式,红色的即为分段常数衰减,它在一定的训练区间内保持学习率不变。


图3:指数衰减衰减的学习率变化图

3.4 自然指数衰减(Natural Exponential Decay)

        ​它与指数衰减方式相似,不同的在于它的衰减底数是 e e e,故而其收敛的速度更快,一般用于相对比较容易训练的网络,便于较快的收敛,其更新规则如下
d e c a y e d _ l e a r n i n g _ r a t e = l e a r n i n g _ r a t e ∗ e − d e c a y _ r a t e g l o b a l _ s t e p decayed{\_}learning{\_}rate =learning{\_}rate*e^{\frac{-decay{\_rate}}{global{\_}step}} decayed_learning_rate=learning_rateeglobal_stepdecay_rate

        下图为为分段常数衰减、指数衰减、自然指数衰减三种方式的对比图,红色的即为分段常数衰减图,阶梯型曲线。蓝色线为指数衰减图,绿色即为自然指数衰减图,很明可以看到自然指数衰减方式下的学习率衰减程度要大于一般指数衰减方式,有助于更快的收敛。

图4:分段常数衰减、指数衰减、自然指数衰减三种方式的对比图

3.5 多项式衰减(Polynomial Decay)

        ​应用多项式衰减的方式进行更新学习率,这里会给定初始学习率和最低学习率取值,然后将会按照给定的衰减方式将学习率从初始值衰减到最低值,其更新规则如下式所示。
g l o b a l _ s t e p = m i n ( g l o b a l _ s t e p , d e c a y _ s t e p s ) d e c a y e d _ l e a r n i n g _ r a t e = ( l e a r n i n g _ r a t e − e n d _ l e a r n i n g _ r a t e ) ∗ ( 1 − g l o b a l _ s t e p d e c a y _ s t e p s ) p o w e r + e n d _ l e a r n i n g _ r a t e global{\_}step=min(global{\_}step,decay{\_}steps) \\ decayed{\_}learning{\_}rate =(learning{\_}rate-end{\_}learning{\_}rate)* \left( 1-\frac{global{\_step}}{decay{\_}steps}\right)^{power} \\ +end{\_}learning{\_}rate global_step=min(global_step,decay_steps)decayed_learning_rate=(learning_rateend_learning_rate)(1decay_stepsglobal_step)power+end_learning_rate

        ​需要注意的是,有两个机制,降到最低学习率后,到训练结束可以一直使用最低学习率进行更新,另一个是再次将学习率调高,使用 decay_steps 的倍数,取第一个大于 global_steps 的结果,如下式所示.它是用来防止神经网络在训练的后期由于学习率过小而导致的网络一直在某个局部最小值附近震荡,这样可以通过在后期增大学习率跳出局部极小值。
d e c a y _ s t e p s = d e c a y _ s t e p s ∗ c e i l ( g l o b a l _ s t e p d e c a y _ s t e p s ) decay{\_}steps = decay{\_}steps*ceil \left( \frac{global{\_}step}{decay{\_}steps}\right) decay_steps=decay_stepsceil(decay_stepsglobal_step)

        如下图所示,红色线代表学习率降低至最低后,一直保持学习率不变进行更新,绿色线代表学习率衰减到最低后,又会再次循环往复的升高降低。

图5:多项式衰减的学习率变化图

3.6 余弦衰减(Cosine Annealing Decay)

        ​余弦衰减就是采用余弦的相关方式进行学习率的衰减,衰减图和余弦函数相似。该方法为论文SGDR:Stochastic Gradient Descent with Warm Restarts中cosine annealing动态学习率。其更新机制如下式所示:
g l o b a l _ s t e p = m i n ( g l o b a l _ s t e p , d e c a y _ s t e p s ) c o s i n e _ d e c a y = 0.5 ∗ ( 1 + c o s ( π ∗ g l o b a l _ s t e p d e c a y _ s t e p s ) ) d e c a y e d = ( 1 − α ) ∗ c o s i n e _ d e c a y + α d e c a y e d _ l e a r n i n g _ r a t e = l e a r n i n g _ r a t e ∗ d e c a y e d global{\_}step=min(global{\_}step,decay{\_}steps) \\ cosine{\_}decay=0.5*\left( 1+cos\left( \pi* \frac{global{\_}step}{decay{\_}steps}\right)\right) \\ decayed=(1-\alpha)*cosine{\_}decay+\alpha \\ decayed{\_}learning{\_}rate=learning{\_}rate*decayed global_step=min(global_step,decay_steps)cosine_decay=0.5(1+cos(πdecay_stepsglobal_step))decayed=(1α)cosine_decay+αdecayed_learning_rate=learning_ratedecayed

        ​如下图所示,红色即为标准的余弦衰减曲线,学习率从初始值下降到最低学习率后保持不变。蓝色的线是线性余弦衰减方式曲线,它是学习率从初始学习率以线性的方式下降到最低学习率值。绿色噪声线性余弦衰减方式。

图6:余弦衰减的学习率变化图

3.7 多间隔衰减(Multi Step Decay)

        间隔衰减 (Step Decay)是指学习率按照指定的轮数间隔进行衰减,该过程可举例说明为:

learning_rate = 0.5 # 学习率初始值
step_size = 30      # 每训练30个epoch进行一次衰减
gamma = 0.1         # 衰减率

learning_rate = 0.5    if epoch < 30 
learning_rate = 0.05   if 30 <= epoch < 60
learning_rate = 0.005  if 60 <= epoch < 90

        多间隔衰减(Multi Step Decay)是指学习率按特定间隔进行衰减,与间隔衰减的区别在于:间隔衰减的epoch间隔是单一且固定的,而多间隔衰减中的epoch间隔是预先指定的多间隔。该过程可举例说明为:

learning_rate = 0.5    # 学习率初始值
milestones = [30, 50]  # 指定轮数间隔
gamma = 0.1            # 衰减率

learning_rate = 0.5    if epoch < 30
learning_rate = 0.05   if 30 <= epoch < 50
learning_rate = 0.005  if 50 <= epoch

3.8 逆时间衰减(Inverse Time Decay)

        学习率大小与当前衰减次数成反比。其计算公式如下:
n e w _ l e a r n i n g _ r a t e = l e a r n i n g _ r a t e 1 + g a m m a ∗ e p o c h new\_learning\_rate = \frac{learning\_rate}{1 + gamma * epoch} new_learning_rate=1+gammaepochlearning_rate
        其中,learning_rate为初始学习率,gamma为衰减率,epoch为训练轮数。

3.9 Lambda衰减(Lambda Decay)

        使用lambda函数来设置学习率,其中lambda函数通过epoch计算出一个因子,使用该因子乘以初始学习率。该衰减过程可参考如下例子:

learning_rate = 0.5                      # 学习率初始值
lr_lambda = lambda epoch: 0.95 ** epoch  # 定义lambda函数

learning_rate = 0.5                      # 当epoch = 0时,0.5 * 0.95 ** 0 = 0.5
learning_rate = 0.475                    # 当epoch = 1时,0.5 * 0.95 ** 1 = 0.475
learning_rate = 0.45125                  # 当epoch = 2时,0.5 * 0.95 ** 2 = 0.45125

3.10 诺姆衰减(Noam Decay)

        诺姆衰减的计算方式如下:
n e w _ l e a r n i n g _ r a t e = l e a r n i n g _ r a t e ∗ d m o d e − 0.5 ∗ m i n ( e p o c h − 0.5 , e p o c h ∗ w a r m u p _ s t e p s − 1.5 ) new\_learning\_rate = learning\_rate * d_{mode}^{-0.5}*min(epoch^{-0.5}, epoch*warmup\_steps^{-1.5}) new_learning_rate=learning_ratedmode0.5min(epoch0.5,epochwarmup_steps1.5)

        其中,dmodel 代表模型的输入、输出向量特征维度,warmup_steps 为预热步数,learning_rate 为初始学习率。更多细节请参考 attention is all you need。

3.11 loss自适应衰减(Reduce On Plateau)

        当loss停止下降时,降低学习率。其思想是:一旦模型表现不再提升,将学习率降低 2-10 倍对模型的训练往往有益。此外,每降低一次学习率后,将会进入一个冷静期。在冷静期内不会监控loss变化也不会进行衰减。当冷静期结束后,会继续监控loss的上升或下降。

3.12 线性学习率热身(Linear Warm Up)

        线性学习率热身是一种学习率优化策略,在正常调整学习率前,先逐步增大学习率。可借鉴论文《Cyclical Learning Rates for Training Neural Networks》文中介绍了估计最小学习率和最大学习率的方法,比如在首次训练时(第1个epoch),先设置一个非常小的初始学习率,在每个batch之后都更新网络,同时增加学习率,统计每个batch计算出的loss,看增加到多大时,loss开始变差(很容易看到,调大到一定程度,loss变大,甚至变成nan),从而得到初始学习率。其核心在于将学习率由小变大。

        当训练步数小于热身步数(warmup_steps)时,学习率 lr 按如下方式更新:
l r = s t a r t _ l r + ( e n d _ l r − s t a r t _ l r ) ∗ e p o c h w a r m u p _ s t e p s lr = start\_lr + (end\_lr - start\_lr) * \frac{epoch}{warmup\_steps} lr=start_lr+(end_lrstart_lr)warmup_stepsepoch

        当训练步数大于等于热身步数(warmup_steps)时,学习率 lr 为:
l r = l e a r n i n g r a t e lr = learning_rate lr=learningrate

        其中,lr 为热身之后的学习率,start_lr 为学习率初始值,end_lr 为最终学习率,epoch 为训练轮数。


4 torch.optim.lr_scheduler

        对于优化器,Optimizer机制在前面PyTorch基础(六)-- optim模块已介绍,这里主要介绍辅助类torch.optim.lr_scheduler包中提供的一些类,用于动态修改lr。

4.1 LambdaLr

        将每个参数组的学习率设置为初始lr乘以给定函数。当last_epoch=-1时,将初始lr设置为初始值。
l r epoch = l r initial ∗ L a m b d a ( e p o c h ) l r_{\text {epoch}} = l r_{\text{initial}} * Lambda(epoch) lrepoch=lrinitialLambda(epoch)

"""
:param lr_lambda(函数或列表):一个函数,给定一个整数形参epoch计算乘法因子,或一个这样的函数列表,optimizer.param_groups中的每组一个。
:param last_epoch (int):最后一个epoch的索引。默认值:1。
:param verbose (bool):如果为 True,则在每次更新时向标准输出输出一条消息。默认值: False。
"""
torch.optim.lr_scheduler.LambdaLR(optimizer, lr_lambda, last_epoch=-1, verbose=False,)
model = torch.nn.Linear(2, 1)
optimizer = torch.optim.SGD(model.parameters(), lr=1.0)
lambda1 = lambda epoch: 0.65 ** epoch
scheduler = torch.optim.lr_scheduler.LambdaLR(optimizer, lr_lambda=lambda1)     # 后面的代码主要在这里更改,所以不再赘述

lrs = []

for _ in range(10):
    optimizer.step()
    lrs.append(optimizer.param_groups[0]["lr"])
    # lrs.append(scheduler.get_lr())  # 与上一句功能相同
    # print("Factor = ", round(0.65 ** i,3)," , Learning Rate = ",round(optimizer.param_groups[0]["lr"],3))
    scheduler.step()
plt.plot(range(10),lrs)

4.2 StepLR

        每一个步长时期,每个参数组的学习速率以伽马衰减。请注意,这种衰减可能与这个调度程序外部对学习速率的其他改变同时发生。
KaTeX parse error: Unexpected end of input in a macro argument, expected '}' at end of input: …d{array}\right.

"""
:param step_size (int):学习率调整步长,每经过step_size,学习率更新一次。
:param gamma (float):学习率调整倍数。
:param last_epoch (int):上一个epoch数,这个变量用于指示学习率是否需要调整。当last_epoch符合设定的间隔时就会调整学习率。当设置为-1时,学习率设置为初始值。
"""
torch.optim.lr_scheduler.StepLR(optimizer, step_size, gamma=0.1, last_epoch=-1, verbose=False)

4.3 MultiStepLR

        当前epoch数满足设定值时,调整学习率。这个方法适合后期调试使用,观察loss曲线,为每个实验制定学习率调整时期
l r epoch = { G a m m a ∗ l r epoch - 1 ,  if  epoch in [milestones] l r epoch - 1 ,  otherwise  l r_{\text {epoch}}=\left\{\begin{array}{ll} Gamma * l r_{\text {epoch - 1}}, & \text { if } {\text{ epoch in [milestones]}} \\ l r_{\text {epoch - 1}}, & \text { otherwise } \end{array}\right. lrepoch={Gammalrepoch - 1,lrepoch - 1, if  epoch in [milestones] otherwise 

"""
:param milestones (list):一个包含epoch索引的list,列表中的每个索引代表调整学习率的epoch。list中的值必须是递增的。 如 [20, 50, 100] 表示在epoch为20, 50,100时调整学习率。
:param gamma (float):学习率调整倍数。
:param last_epoch (int):上一个epoch数,这个变量用于指示学习率是否需要调整。当last_epoch符合设定的间隔时就会调整学习率。当设置为-1时,学习率设置为初始值。
"""
torch.optim.lr_scheduler.MultiStepLR(optimizer, milestones, gamma=0.1, last_epoch=-1, verbose=False)

4.4 ExponentialLR

        按指数衰减调整学习率。每一个epoch以伽马衰减每个参数组的学习速率。
l r epoch = G a m m a ∗ l r epoch - 1 l r_{\text {epoch}}= Gamma * l r_{\text {epoch - 1}} lrepoch=Gammalrepoch - 1

"""
:param gamma (float):学习率调整倍数。
:param last_epoch (int):上一个epoch数,这个变量用于指示学习率是否需要调整。当last_epoch符合设定的间隔时就会调整学习率。当设置为-1时,学习率设置为初始值。
"""
torch.optim.lr_scheduler.ExponentialLR(optimizer, gamma, last_epoch=-1, verbose=False,)

4.5 CosineAnneaingLR

        模拟余弦退火曲线调整学习率。使用余弦退火计划设置每个参数组的学习速率。注意,因为调度是递归定义的,所以学习速率可以在这个调度程序之外被其他操作符同时修改。如果学习速率由该调度器单独设置,则每一步的学习速率为:
η t = η min ⁡ + 1 2 ( η max ⁡ − η min ⁡ ) ( 1 + cos ⁡ ( T c u r T max ⁡ π ) ) \eta_{t}=\eta_{\min }+\frac{1}{2}\left(\eta_{\max }-\eta_{\min }\right)\left(1+\cos \left(\frac{T_{c u r}}{T_{\max }} \pi\right)\right) ηt=ηmin+21(ηmaxηmin)(1+cos(TmaxTcurπ))

model = torch.nn.Linear(2, 1)
optimizer = torch.optim.SGD(model.parameters(), lr=1.0)
scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=10, eta_min=0)
lrs = []


for _ in range(100):
    optimizer.step()
    lrs.append(optimizer.param_groups[0]["lr"])
    scheduler.step()

plt.plot(lrs)

4.6 MultiplicativeLR

        将每个参数组的学习率乘以指定函数中给定的因子。当last_epoch=-1时,将初始lr设置为初始值。
l r epoch = l r epoch - 1 ∗ L a m b d a ( e p o c h ) l r_{\text {epoch}} = l r_{\text {epoch - 1}} * Lambda(epoch) lrepoch=lrepoch - 1Lambda(epoch)

# 参数与LambdaLr相同
torch.optim.lr_scheduler.MultiplicativeLR(optimizer, lr_lambda, last_epoch=-1, verbose=False,)

4.7 CyclicLR

        Cyclical Learning Rates for Training Neural Networks 学习率周期性变化。

"""
:param base_lr (float or list):循环中学习率的下边界。:param max_lr (floatorlist):循环中学习率的上边界。
:param tep_size_up (int):学习率上升的步数。
:param step_size_down (int):学习率下降的步数。
:param mode (str):{triangular, triangular2, exp_range}中的一个。默认: 'triangular'。
:param gamma (float):在mode='exp_range'时,gamma**(cycle iterations), 默认:1.0。
:apram scale_fn:自定义的scaling policy,通过只包含有1个参数的lambda函数定义。0 <= scale_fn(x) <= 1 for all x >= 0. 默认:None。如果定义了scale_fn, 则忽略 mode参数
:param last_epoch (int):上一个epoch数,这个变量用于指示学习率是否需要调整。当last_epoch符合设定的间隔时就会调整学习率。当设置为-1时,学习率设置为初始值。
"""
torch.optim.lr_scheduler.CyclicLR(optimizer, base_lr, max_lr, step_size_up, mode='triangular')
scheduler1 = torch.optim.lr_scheduler.CyclicLR(optimizer, base_lr=0.001, max_lr=0.1, step_size_up=5, mode='triangular')

        对OneCycleLR、OneCycleLRCosineAnnealingWarmRestarts的介绍,可以参考:图解 9 种Torch中常用的学习率调整策略


参考

  • 图解 9 种Torch中常用的学习率调整策略:https://mp.weixin.qq.com/s/A-BkpToAr2ubhTnz_bvkpQ
  • 学习率:https://paddlepedia.readthedocs.io/en/latest/tutorials/deep_learning/model_tuning/learning_rate.html
  • 如何配置神经网络的学习率:https://blog.csdn.net/weixin_39653948/article/details/105962154
  • 炼丹手册——学习率设置:https://zhuanlan.zhihu.com/p/332766013
  • PyTorch优化器与学习率设置详解:https://zhuanlan.zhihu.com/p/435669796
  • Transformers之自定义学习率动态调整:https://zhuanlan.zhihu.com/p/466992867

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

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

相关文章

学 Java 怎么进外企?

作者&#xff1a;**苍何&#xff0c;CSDN 2023 年 实力新星&#xff0c;前大厂高级 Java 工程师&#xff0c;阿里云专家博主&#xff0c;土木转码&#xff0c;现任部门技术 leader&#xff0c;专注于互联网技术分享&#xff0c;职场经验分享。 &#x1f525;热门文章推荐&#…

HNU程序设计 练习三-控制结构

1.台球游戏 【问题描述】 在本台球游戏中&#xff0c;包含多种颜色的球&#xff0c;其中&#xff1a;红球15只各1分、黄球1只2分、绿球1只3分、咖啡球1只4分、蓝球1只5分、粉球1只6分、黑球1只7分。 球的颜色表示为&#xff1a; r-红色球 y-黄色球 g-绿色球 c-咖啡色球 b-蓝色…

闭循环低温恒温器的使用注意事项

与液氮恒温器相比&#xff0c;闭循环低温恒温器显得稍微复杂一些&#xff01;这主要表现在组成部分、体积重量、使用操作、升降温时间等方面。闭循环低温恒温器主要由冷头、氦压缩机、两根氦气连管组成&#xff0c;配套设备还有控温仪、真空泵&#xff0c;可能还有循环水冷机。…

离散数学实践(2)-编程实现关系性质的判断

*本文为博主本人校内的离散数学专业课的实践作业。由于实验步骤已经比较详细&#xff0c;故不再对该实验额外提供详解&#xff0c;本文仅提供填写的实验报告内容与代码部分&#xff0c;以供有需要的同学学习、参考。 -------------------------------------- 编程语言&#xff…

VM虚拟机逆向 --- [NCTF 2018]wcyvm 复现

文章目录 前言题目分析 前言 第四题了&#xff0c;搞定&#xff0c;算是独立完成比较多的一题&#xff0c;虽然在还原汇编的时候还是很多问题。 题目分析 代码很简单&#xff0c;就是指令很多。 opcode在unk_6021C0处&#xff0c;解密的数据在dword_6020A0处 opcode [0x08, …

谈一谈SQLite、MySQL、PostgreSQL三大数据库

每一份付出&#xff0c;必将有一份收货&#xff0c;就像这个小小的果实&#xff0c;时间到了&#xff0c;也就会开花结果… 三大数据库概述 SQLite、MySQL 和 PostgreSQL 都是流行的关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;但它们在功能、适用场景和性…

【UE】从UI拖拽生成物体 —— 更改位置与定点销毁

本篇在上一篇博客&#xff08;【UE】从UI中拖拽生成物体-CSDN博客&#xff09;基础上继续增加更改生成的Actor的位置与定点销毁Actor的功能。 目录 效果 步骤 一、修改生成好的Actor位置 解决问题一&#xff1a;从UI拖出多个actor后&#xff0c;只能对第一个拖出的actor的…

传智杯-21算法赛初赛B组题目详细解法解析-AB题(C/C++、Python、Java)

🚀 欢迎来到 ACM 算法题库专栏 🚀 在ACM算法题库专栏,热情推崇算法之美,精心整理了各类比赛题目的详细解法,包括但不限于ICPC、CCPC、蓝桥杯、LeetCode周赛、传智杯等等。无论您是刚刚踏入算法领域,还是经验丰富的竞赛选手,这里都是提升技能和知识的理想之地。 ✨ 经典…

UG\NX二次开发 先设置默认颜色再创建对象

文章作者:里海 来源网站:里海NX二次开发3000例专栏 感谢粉丝订阅 感谢 qq_42461973 订阅本专栏,非常感谢。 简介 有粉丝问,可不可以先设置默认颜色再创建对象?这个是可以的,下面是例子: 效果 代码 #include "me.hpp" using namespace std;

java/springboot服务第三方接口安全签名(Signature)实现方案

前言 有的时候&#xff0c;我们需要把我们系统里的接口开放给第三方应用或企业使用&#xff0c;那第三方的系统并不在我们自己的认证授权用户体系内&#xff0c;此时&#xff0c;要如何保证我们接口的数据安全和身份识别呢&#xff1f; 在为第三方系统提供接口的时候&#xf…

筑基新一代数据底座,中国科大让智慧科研更有数

著名科学哲学家库恩在《科学革命的结构》中认为&#xff0c;范式是科研的一种理论体系&#xff0c;范式的突破会带来一系列科学革命。 如今在科研领域&#xff0c; 人工智能不断打破科研边界&#xff0c;AI for Science被视为下一个科研新范式&#xff0c;不仅为科学研究带来了…

Cesium:为地图添加指北针、缩放按钮和比例尺

作者&#xff1a;CSDN _乐多_ 网上找的很多代码用不了。本文记录了Cesium中为地图添加指北针、缩放按钮和比例尺的可用代码。 文章目录 一、代码 一、代码 const viewer new Cesium.Viewer(cesiumContainer, {// ...navigationHelpButton: false,sceneModePicker: false,sc…

校验验证码是否过期(定时刷新验证码)

需求&#xff1a; 我们在登录的时候会遇到通过接口请求验证码的操作&#xff0c;这里的验证码会有过期的时间&#xff0c;当我们验证码过期了&#xff0c;我们要进行重新刷新验证码。 我们这里根据后端返回的当前时间和过期时间判断&#xff0c;过期的时间超过了当前时间的时候…

Java面向对象 下(六)

Java面向对象 ( 下) 观看b站尚硅谷视频做的笔记 文章目录 Java面向对象 ( 下)1、 关键字&#xff1a;static1.1、static 的使用1.1.1、static 修饰属性1.1.2、 static 修饰方法1.1.3、 static 修饰代码块1.1.4、 static 修饰内部类1.1.5、类变量 vs 实例变量内存解析 1.2、 自…

关于msvcp120.dll丢失的解决方法详解,快速解决dll丢失问题

在计算机使用过程中&#xff0c;经常会遇到“msvcp120.dll丢失”的错误提示。这个错误提示通常出现在运行某些程序或游戏时&#xff0c;造成相关应用程序可能无法正常启动或运行。那么&#xff0c;究竟是什么原因导致了msvcp120.dll文件的丢失呢&#xff1f;本文将详细解析msvc…

【QT】文件读写

新建项目 加入控件 整体做一个布局 功能&#xff1a;选择文件路径&#xff0c;打开文件&#xff08;两种文件格式&#xff1a;utf-8、GBK&#xff09; #include "widget.h" #include "ui_widget.h" #include <QPushButton> #include <QFileDial…

云产品ECS免费试用获取奖励步骤

文章目录 1、获取活动链接2、报名参加3、试用产品领取产品试用权限配置安全组访问应用提交作品 4、提交任务获取奖励 1、获取活动链接 活动时间2023.11.1&#xff5e;2023.11.30 名额有限&#xff0c;先到先得 进群群主获取活动链接 2、报名参加 直接点击链接进入小程序进行…

【带头学C++】----- 三、指针章* ---- 3.1指针变量的定义

指针在C语言是核心&#xff0c;在C中更是核心。所以本章节将详细讲解指针的使用方法以及指针的一些特殊用法&#xff0c;和引用的区别&#xff0c;以及指针涉及到一些算法基础。通过案例引导&#xff0c;使得能更清楚命明白。在C中的指针是一种数据类型&#xff0c;其使用方法和…

【Java 进阶篇】Java ServletContext功能详解:域对象的使用

Java ServletContext是Java Web应用程序中的一个关键组件&#xff0c;它提供了一种在不同Servlet之间共享数据的机制。这种共享通过域对象来实现&#xff0c;包括ServletContext域、Session域和Request域。在本篇博客中&#xff0c;我们将重点关注ServletContext域&#xff0c;…

批处理写定时关机和开机自动运行老化视频

扬创科技出品的X86平板电脑&#xff08;7寸-21.5寸 6代7代10代酷睿系列 、J4125 、J1900&#xff0c;承接客户各种尺寸定制&#xff09;视频方式老化测试。 需求&#xff1a;1、开机启动自动运行老化视频。 2、下午5点25正式关机。 1、开机启动自动运行老化视频。 start &quo…