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

深度学习——激活函数、损失函数、优化器

深度学习——激活函数、损失函数、优化器

  • 1、激活函数
    • 1.1、一些常见的激活函数
      • 1.1.1、sigmoid
      • 1.1.2、softmax
      • 1.1.3、tanh
      • 1.1.4、ReLU
      • 1.1.5、Leaky ReLU
      • 1.1.6、PReLU
      • 1.1.7、GeLU
      • 1.1.8、ELU
    • 1.2、激活函数的特点
      • 1.2.1、非线性
      • 1.2.2、几乎处处可微
      • 1.2.3、计算简单
      • 1.2.4、非饱和性
      • 1.2.5、单调性、输出范围有限
  • 2、损失函数
    • 2.1、深度估计回归损失
      • 2.1.1、L1损失函数
      • 2.1.2、L2损失函数
      • 2.1.3、smooth L1损失函数
      • 2.1.4、log cosh损失函数:
      • 2.1.5、==RMSE:均方根误差==
      • 2.1.6、MAE:平均绝对误差
      • 2.1.7、iRMSE
      • 2.1.8、REL系列
      • 2.1.9、 δ \delta δ :阈值精度
      • 2.1.10、log系列
    • 2.2、分类损失
      • 2.2.1、交叉熵损失:
      • 2.2.2、Focal Loss
    • 2.3、目标检测损失函数
      • 2.3.1、IoU Loss交并比损失
      • 3.2、GIoU Loss:泛化的IoU损失
      • 2.3.3、DIoU
      • 2.3.4、CIoU
      • 2.3.5、EIoU->F-EIoU
  • 3、优化器
    • 3.1、SGD、BGD、MBGD
    • 3.2、SGD with Momentum
    • 3.3、NAG
    • 3.4、AdaGard(自适应梯度)
    • 3.5、RMSprop算法
    • 3.6、Adadelta
    • 3.7、Adam 适应性矩估计
    • 3.8、Adamw
    • 3.9、各个优化器特点以及演化对比

1、激活函数

激活函数将非线性引入到网络中,没有激活函数相当于原始的感知机,只有线性操作,近似为矩阵相乘操作,加入激活函数后可以更好地拟合非线性函数。

1.1、一些常见的激活函数

1.1.1、sigmoid

σ ( x ) = 1 1 + e − x \sigma(x) = \frac{1}{1+e^{-x}} σ(x)=1+ex1
特点:将负无穷到正无穷的输入映射到0-1,处处连续可导,可以用于二分类,导数为 σ ′ ( x ) = σ ( x ) ( 1 − σ ( x ) ) \sigma'(x)=\sigma(x)(1-\sigma(x)) σ(x)=σ(x)(1σ(x))
缺点:在输出值接近0或1时会出现饱和现象,在反向传播时梯度较小,容易梯度消失,从而无法完成深层网络的训练。输出不是0均值的,会导致后层的神经元的输入是非0均值的信号,这会对梯度产生影响。并且计算复杂度较高,因为涉及到指数。

1.1.2、softmax

S o f t m a x ( x i ) = e x i Σ j e x j Softmax(x_i)=\frac{e^{x_i}}{\Sigma_j{e^{x_j}}} Softmax(xi)=Σjexjexi
softmax可以将上一层的原始数据进行归一化,转化为一个(0,1)之间的数值,这些数值可以被当作概率分布,用来作为多分类的目标预测值,一般作为神经网络的最后一层,接收上一层网络的输入值,然后将其转化为概率。sigmoid是softmax的一个特例,sigmoid函数只能用于预测值为0或1的二元分类。

1.1.3、tanh

σ ( x ) = e x − e − x e x + e − x \sigma(x) = \frac{e^x-e^{-x}}{e^x+e^{-x}} σ(x)=ex+exexex
输出范围在-1~1,相比sigmoid函数,是0均值,会比sigmoid函数要好一些,但是仍然会存在容易梯度消失的问题。并且计算复杂度仍然较高。

1.1.4、ReLU

σ ( x ) = { 0 x < 0 x x ⩾ 0 \sigma(x) = \begin{cases} 0 & x<0 \\ x & x \geqslant 0 \end{cases} σ(x)={0xx<0x0
或者 σ ( x ) = m a x ( 0 , x ) \sigma(x) = max(0,x) σ(x)=max(0,x)
整流线性单元,使用ReLU的SGD算法收敛速度比sigmoid和tanh快,在x>0时不会出现梯度消失问题,在x<0时,梯度为0,无法传播到前一层。计算复杂度低。
缺点:输出不是0均值的,并且在x<0时会存在神经元坏死问题,梯度无法传播,其后面的神经元梯度都为0,无法更新参数。

1.1.5、Leaky ReLU

σ ( x ) = { α x x < 0 x x > 0 \sigma(x) = \begin{cases} \alpha x & x<0 \\ x & x>0 \\ \end{cases} σ(x)={αxxx<0x>0
alpha默认0.01;为解决ReLU神经元坏死的问题,引入了LeakReLU,使得激活函数在负数区域也存在微小的梯度,而梯度是固定的斜率。

1.1.6、PReLU

σ ( x ) = { a x x < 0 x x > 0 \sigma(x) = \begin{cases} ax & x<0 \\ x & x>0 \\ \end{cases} σ(x)={axxx<0x>0
和LeakReLU不同的是这里的参数 a a a是可学习的

1.1.7、GeLU

σ ( x ) = 1 1 + e − 1.702 x \sigma(x) = \frac{1}{1+e^{-1.702x}} σ(x)=1+e1.702x1
在Transformer里面用的多一些

1.1.8、ELU

σ ( x ) = { α ( e x − 1 ) x < 0 x x > 0 \sigma(x) = \begin{cases} \alpha(e^x-1) & x<0 \\ x & x>0 \\ \end{cases} σ(x)={α(ex1)xx<0x>0
有负数饱和区域,从而对噪声有一些鲁棒性。可以看做是介于ReLU和Leaky ReLU之间的一个函数。当然,这个函数也需要计算exp,从而计算量上更大一些。

1.2、激活函数的特点

1.2.1、非线性

即导数不能是常数,来保证多层网络不退化成单层线性网络

1.2.2、几乎处处可微

几乎处处可微保证了在优化中梯度的可计算性,ReLU仅在有限个点处不可微。有限个不可微的点对优化结果不会有很大的影响。

1.2.3、计算简单

因为每一个神经元的输出都需要经过激活函数,简单的函数像是ReLU更适合做激活函数。

1.2.4、非饱和性

Sigmoid在正负区域都有饱和区,ReLU在负半轴有饱和区,饱和区参数无法得到有效更新,leakyReLU就是为了解决这个问题。

1.2.5、单调性、输出范围有限

2、损失函数

2.1、深度估计回归损失

2.1.1、L1损失函数

L1损失函数:最小绝对值偏差、最小绝对值误差:是目标值与估计值的绝对差值的总和。缺点:不稳定。收敛速度慢。优点:对离群点异常值更具有鲁棒性。
L 1 ( y ^ − y ) = ∑ i = 0 m ∣ y ( i ) − y ^ ( i ) ∣ L_1(\hat{y}-y)=\sum_{i=0}^m\left|y^{(i)}-\hat{y}^{(i)}\right| L1(y^y)=i=0m y(i)y^(i)
torch.nn.L1Loss(size_average=None, reduce=None, reduction='sum') # size_average与reduce已经被弃用,具体功能可由reduction替代。

l1_loss = torch.nn.L1Loss(size_average=None, reduce=None, reduction='sum') # 创建实例
loss = l1_loss(src,tgt)

L 1 ( y ^ − y ) = 1 N ∑ i = 0 m ∣ y ( i ) − y ^ ( i ) ∣ L_1\left(\hat{y}-y\right)=\frac1N\sum_{i=0}^m\left|y^{(i)}-\hat{y}^{(i)}\right| L1(y^y)=N1i=0m y(i)y^(i)
torch.nn.L1Loss(size_average=None, reduce=None, reduction='mean'),相当于MAE平均绝对误差。
torch.nn.functional.l1_loss(src, tgt, reduction='mean')
torch.mean(torch.abs(src-tgt))
(src-tgt).abs().mean()
如果是np.ndarray的话
np.mean(np.abs(src-tgt)) np.ndarray没有.abs()方法,只有类np.abs()函数

2.1.2、L2损失函数

L2损失函数:均方误差:是目标值与估计值的差值的平方和。缺点:对异常值更敏感。梯度更新方向容易受离群点主导。
L 2 ( y ^ , y ) = ∑ i = 0 m ( y ( i ) − y ^ ( i ) ) 2 L_2(\hat{y},y)=\sum_{i=0}^m(y^{(i)}-\hat{y}^{(i)})^2 L2(y^,y)=i=0m(y(i)y^(i))2
torch.nn.MSELoss(size_average=None, reduce=None, reduction='sum')
torch.sum(torch.pow(src-tgt,2))
np.sum(np.power(src-tgt,2))
L 2 ( y ^ , y ) = 1 N ∑ i = 0 m ( y ( i ) − y ^ ( i ) ) 2 L_2(\hat{y},y)=\frac1N\sum_{i=0}^m(y^{(i)}-\hat{y}^{(i)})^2 L2(y^,y)=N1i=0m(y(i)y^(i))2
torch.nn.MSELoss(size_average=None, reduce=None, reduction='mean'),相当于MSE均方误差。
torch.mean(torch.pow(src-tgt,2))
np.mean(np.power(src-tgt,2))

2.1.3、smooth L1损失函数

smooth L1损失函数:平滑之后的L1损失函数:分段函数,来消除L1的折点不光滑问题。当误差的绝对值较小时采用MSE,当误差的绝对值较大时采用MAE。
S m o o t h L 1 = 0.5 x 2 , ∣ x ∣ < 1 ∣ x ∣ − 0.5 , x < − 1 或者 x > 1 SmoothL_1=\begin{aligned}&0.5x^2,\mid x\mid<1\\&\mid x\mid-0.5,x<-1\text{或者}x>1\end{aligned} SmoothL1=0.5x2,x∣<1x0.5,x<1或者x>1
torch.nn.SmoothL1Loss(size_average=None, reduce=None, reduction='mean', beta=1.0) 上面公式里面的默认beta为1。

Huber Loss:对异常值鲁棒,集MAE和MSE的优势于一身。
在这里插入图片描述
在这里插入图片描述
当预测偏差小于δ时,采用平方误差MSE,
在pytorch中torch.nn.HuberLoss(reduction=‘mean’),pytorch中的smoothL1好像也具有类似的功能,是一样的。

2.1.4、log cosh损失函数:

双曲余弦对数在这里插入图片描述
对于较小的X值,log(cosh(x))约等于(x ** 2) / 2;对于较大的X值,则约等于abs(x) - log(2)。这意味着Log-cosh很大程度上工作原理和平均方误差很像,但偶尔出现错的离谱的预测时对它影响又不是很大。它具备了Huber损失函数的所有优点,但不像Huber损失,它在所有地方都二次可微。
但Log-cosh也不是完美无缺,如果始终出现非常大的偏离目标的预测值时,它就会遭受梯度问题。

2.1.5、RMSE:均方根误差

R M S E = 1 N ∑ i = 1 N ( D p r e d i − D g t i ) 2 \mathrm{RMSE}=\sqrt{\frac1N\sum_{i=1}^N\left(D_{pred}^i-D_{gt}^i\right)^2} RMSE=N1i=1N(DprediDgti)2
深度估计常常采用RMSE作为误差衡量指标。

2.1.6、MAE:平均绝对误差

MAE相对于RMSE更加具有鲁棒性,因为它不会受到平方项的影响,因此对异常值(大误差)不那么敏感,其计算公式如下:
MAE = 1 N ∑ i = 1 N ∣ D p r e d i − D g t i ∣ \text{MAE}=\frac1N\sum_{i=1}^N\lvert D_{pred}^i-D_{gt}^i\rvert MAE=N1i=1NDprediDgti

2.1.7、iRMSE

iRMSE:逆均方根误差,值越大表示性能越好错误,
i R M S E = 1 N ∑ i = 1 N ( 1 D p r e d i − 1 D g t i ) 2 \mathrm{iRMSE}=\sqrt{\frac1N\sum_{i=1}^N(\frac1{D_{pred}^i}-\frac1{D_{gt}^i})^2} iRMSE=N1i=1N(Dpredi1Dgti1)2
iMAE:逆平均绝对误差:
i M A E = 1 N ∑ i = 1 N ∣ 1 D p r e d i − 1 D g t i ∣ \mathrm{iMAE}=\frac1N\sum_{i=1}^N|\frac1{D_{pred}^i}-\frac1{D_{gt}^i}| iMAE=N1i=1NDpredi1Dgti1

2.1.8、REL系列

平均相对误差,REL的值表示平均相对误差的百分比,强调了深度估计的准确性。REL越小,表示模型的深度估计与真实深度的平均相对误差越小,模型性能越好,其计算公式如下:
abs REL:
a b s REL = 1 N ∑ i = 1 N ∣ D p r e d i − D g t i D g t i ∣ abs\text{ REL}=\frac{1}{N}\sum_{i=1}^{N}\lvert\frac{D_{pred}^{i}-D_{gt}^{i}}{D_{gt}^{i}}\rvert abs REL=N1i=1NDgtiDprediDgti
sq REL:
s q REL = 1 N ∑ i = 1 N ( D p r e d i − D g t i ) 2 D g t i sq\text{ REL}=\frac1N\sum_{i=1}^N\frac{\left(D_{pred}^i-D_{gt}^i\right)^2}{D_{gt}^i} sq REL=N1i=1NDgti(DprediDgti)2

2.1.9、 δ \delta δ :阈值精度

1.25 1.25^2 1.25^3定义为:
t h r e s h = max ⁡ ( D g t i D p r e d i , D p r e d i D g t i ) = δ < τ thresh=\max\Bigg(\frac{D_{gt}^i}{D_{pred}^i},\frac{D_{pred}^i}{D_{gt}^i}\Bigg)=\delta<\tau thresh=max(DprediDgti,DgtiDpredi)=δ<τ
对每个像素返回0或1,然后对整幅图取平均,其中 是给定的阈值通常为(1.25, 1.25^2, 1.25^3)。该指标与REL通常为室内数据集常用指标。

2.1.10、log系列

RMSE log:
R M S E log ⁡ = 1 N ∑ i = 1 N ( ln ⁡ ( D p r e d i ) − ln ⁡ ( D g t i ) ) 2 RMSE\log=\sqrt{\frac{1}{N}\sum_{i=1}^{N}\left(\ln\left(D_{pred}^{i}\right)-\ln\left(D_{gt}^{i}\right)\right)^{2}} RMSElog=N1i=1N(ln(Dpredi)ln(Dgti))2
log10:
log ⁡ 10 = 1 N ∑ i = 1 N ∣ log ⁡ 10 ( D p r e d i ) − log ⁡ 10 ( D g t i ) ∣ \log10=\frac1N\sum_{i=1}^N\left|\log_{10}\left(D_{pred}^i\right)-\log_{10}\left(D_{gt}^i\right)\right| log10=N1i=1N log10(Dpredi)log10(Dgti)
si log:
s i log ⁡ = 1 N ∑ i = 1 N ( ln ⁡ ( D p r e d i ) − ln ⁡ ( D g t i ) ) 2 − l a m b d a × ( 1 N ∑ i = 1 N ( ln ⁡ ( D p r e d i ) − ln ⁡ ( D g t i ) ) ) 2 si\log=\sqrt{\frac{1}{N}\sum_{i=1}^{N}\left(\ln\left(D_{pred}^{i}\right)-\ln\left(D_{gt}^{i}\right)\right)^2-lambda\times\left(\frac{1}{N}\sum_{i=1}^{N}\left(\ln\left(D_{pred}^{i}\right)-\ln\left(D_{gt}^{i}\right)\right)\right)^2} silog=N1i=1N(ln(Dpredi)ln(Dgti))2lambda×(N1i=1N(ln(Dpredi)ln(Dgti)))2
lambda通常为0.5

2.2、分类损失

2.2.1、交叉熵损失:

CrossEntropyLoss用于二分类或多分类问题。

  • 信息量: I ( x ) = − log ⁡ ( P ( x ) ) I(x)=-\log(P(x)) I(x)=log(P(x))信息量的大小和事件发生的概率成反比。
  • 信息熵:信息熵是在结果出来之前对可能产生的信息量的期望,要考虑随机变量的所有可能取值, H ( X ) = − Σ i = 1 n p ( x i ) log ⁡ ( p ( x i ) ) H(X)=-\Sigma_{i=1}^{n} p(x_i)\log(p(x_i)) H(X)=Σi=1np(xi)log(p(xi))
  • 相对熵:又被称为KL散度,相对熵等价于两个概率分布的信息的差值:假设 p ( x ) p(x) p(x)为样本真实分布, q ( x ) q(x) q(x)为样本预测分布,则相对熵为: D K L ( p ∣ ∣ q ) = H p q ( X ) − H p p ( X ) = Σ i = 1 n p ( x i ) log ⁡ ( p ( x i ) q ( x i ) ) D_{KL}(p||q) = H_{pq}(X)-H_{pp}(X)=\Sigma_{i=1}^n p(x_i) \log (\frac{p(x_i)}{q(x_i)}) DKL(p∣∣q)=Hpq(X)Hpp(X)=Σi=1np(xi)log(q(xi)p(xi))
    KL散度越小,说明两个分布(真实和预测)越接近,
  • 交叉熵:Cross Entropy
    设p(x)、q(x)分别是离散随机变量X的两个概率分布,其中p(x)是目标分布,q(x)是预测分布,则交叉熵为:
    H ( p , q ) = Σ i p ( x i ) log ⁡ 1 log ⁡ q ( x i ) = − Σ i p ( x i ) log ⁡ q ( x i ) H(p,q)=\Sigma_{i}p(x_i)\log{\frac{1}{\log q(x_i)}}=-\Sigma_{i}p(x_i)\log q(x_i) H(p,q)=Σip(xi)loglogq(xi)1=Σip(xi)logq(xi)
    可以看到交叉熵是把KL散度中的固定的部分给去掉了

2.2.2、Focal Loss

主要是来解决单阶段目标检测中正负样本数量级不平衡问题。基于二分类交叉熵损失函数提出Focal Loss,的一个动态缩放迭代交叉熵损失。Focal Loss降低了容易分类的样本是损失占比,将更多的注意力放在难的、被错误分类的样本上。

loss = F.binary_cross_entropy_with_logits(pred, label, reduction='none')
# binary_cross_entropy_with_logits表示损失函数内部已经带了计算logit的操作,无需在传入这个loss函数之前手动使用sigmoid/softmax将之前的网络的输入映射到[0,1]之间。label通常是独热码,维度大小与pred相同,
pred_prob = pred.sigmoid() # 转为概率
p_t = label * pred_prob + (1-label) * (1-pred_prob)
modulating_factor=(1.0-p_t) ** gamma 
# 对于在0标签处预测的概率比较大,这个因子会比较大,对于在1标签处预测的概率比较小的,这个因子也会比较大,对于概率很接近标签的,这个会比较小,从而动态缩放。
loss *= modulating_factor

BCE:二值交叉损失
在这里插入图片描述
在这里插入图片描述

2.3、目标检测损失函数

2.3.1、IoU Loss交并比损失

目标检测也可以用回归损失,让四个坐标值回归到目标值,但IoU损失是主流。
IoU表示交集与并集的面积比值。
IoU Loss = -ln(交集面积/并集面积)
部分来源于知乎。
在这里插入图片描述

3.2、GIoU Loss:泛化的IoU损失

当预测框与候选框没有重叠时,交集为0,损失为0,此时IoU无法计算两者之间的距离,梯度消失,而且IoU不管两个框的对齐方向问题。GIoU找到两个框最小闭合凸面C,然后再计算C中排除掉A和B后的面积占C原始面积的比值,最后再用原始的IoU减去这个比值得到泛化后的IoU值。
在这里插入图片描述

2.3.3、DIoU

2.3.4、CIoU

2.3.5、EIoU->F-EIoU

3、优化器

来源https://juejin.cn/post/7084409806492008456

一阶优化器:SGD、SDGwith Momentum、NAG(牛顿动量法)、AdaGrad(自适应梯度)、RMSProp(均方差传播)、Adam、Nadam、共轭梯度法
二阶优化器:牛顿法、拟牛顿法、BFGS、L-BFGS
其中:AdaGrad算法,RMSProp算法,Adam算法以及AdaDelta算法是自适应学习率算法

3.1、SGD、BGD、MBGD

假设待优化的模型参数为 θ \theta θ,目标函数(损失函数)为 J ( θ ) J(\theta) J(θ),学习率为 η \eta η,迭代周期epoch为t,则可以得到:
损失函数 J ( θ ) 关于当前参数 θ 的梯度: g t = ∇ θ J ( θ ) 损失函数J(\theta)关于当前参数\theta的梯度:g_t=\nabla_\theta J(\theta) 损失函数J(θ)关于当前参数θ的梯度:gt=θJ(θ)
在梯度下降算法中,沿着梯度的方向不断减小模型参数,参数更新为:
θ t + 1 = θ t − η ⋅ ∇ θ J ( θ ) = θ t − η ⋅ g t \theta_{t+1}=\theta_t-\eta \cdot \nabla_\theta J(\theta)=\theta_t-\eta \cdot g_t θt+1=θtηθJ(θ)=θtηgt
标注的梯度下降每次迭代都要遍历所有样本,这会使得训练过程极其缓慢
SGD:随机梯度下降
在每次迭代中仅使用一个随机选择的训练样本来计算梯度,并更新模型参数,训练成本低,但是不稳定,收敛速度慢,可能会收敛到局部最优解。通常,SGD收敛速度要比BGD快。
BGD:批量梯度下降
使用整个训练数据集所有样本的梯度,根据学习率更新模型参数,收敛方向更稳定,训练很慢,迭代次数相对较少。
MBGD:小批量梯度下降,对SGD和BGD的折中,每次使用batch_size个样本对参数进行更新。在合理的范围内增大batchsize能够确定更准确的收敛方向,减小震荡,增大并行率。但是batchsize过大,会导致迭代次数减小(相同epoch下),需要花费可能更多时间训练。

3.2、SGD with Momentum

参数更新时在一定程度上保留之前更新的方向,同时又利用batch的梯度微调最终的更新方向,SGD只使用了当步参数的梯度,随机性较大,如果将历次迭代的梯度按比例融合,可能更稳定。
假设 m t m_t mt表示 t t t时刻的动量, β \beta β表示动量因子,通常取0.9,即下降的方向只要是此前累计的方向,在SGD的基础上增加动量,则参数更新公式为:
M t = β ⋅ M t − 1 + η ⋅ g t θ t + 1 = θ t − M t M_t = \beta \cdot M_{t-1}+\eta \cdot g_t \\ \theta_{t+1} =\theta_t-M_t Mt=βMt1+ηgtθt+1=θtMt
一阶动量 M t M_t Mt是各个时刻梯度方向的指数移动平均值,约等于最近 1 ( 1 − β ) \frac{1}{(1-\beta)} (1β)1个时刻的梯度向量和的平均值。
动量可以减小震荡,在梯度方向相同时,动量可以加速参数更新,从而加速收敛。前后梯度不一致时能够抑制震荡,越过局部极小值,(加速收敛,减小震荡)

3.3、NAG

M t = β ⋅ M t − 1 + η ⋅ ∇ θ J ( θ − γ ⋅ M t − 1 ) θ t + 1 = θ t − M t M_t=\beta \cdot M_{t-1}+\eta \cdot \nabla_\theta J(\theta-\gamma \cdot M_{t-1}) \\ \theta_{t+1}=\theta_t-M_t Mt=βMt1+ηθJ(θγMt1)θt+1=θtMt
进一步进入nesterov动量,从SGD with Momentum可以看出,无论当前位置的梯度为什么,参数更新都一定会先走一个 β ⋅ M t − 1 \beta \cdot M_{t-1} βMt1,再根据之前位置处的参数小更新一下,于是NAG方法让参数先走 β ⋅ M t \beta \cdot M_t βMt,再根据走之后的位置处的梯度更新。这样如果前方的梯度更大,则迈步更大。

3.4、AdaGard(自适应梯度)

针对SGD中始终使用一个学习率的问题,AdaGard在每次进行参数更新的时候,对于每个参数,初始化一个s=0,然后每次将该参数的梯度平方求和累加到这个变量s上,而在更新这个参数的时候,学习率就变成:
G t = G t − 1 + g t 2 θ t + 1 = θ t − η G t + ϵ ⋅ g t G_t=G_{t-1} + g_t^2 \\ \theta_{t+1}=\theta_{t}-\frac{\eta}{\sqrt{G_t+\epsilon}} \cdot g_t Gt=Gt1+gt2θt+1=θtGt+ϵ ηgt
但是这种方法会存在二阶动量一直累加的问题,学习率迟早要很小。

3.5、RMSprop算法

RMSprop在有些情况下避免AdaGrad算法中学习率不断单调下降以至于过早衰减的缺点。
RMSprop首先计算每次迭代梯度g的平方的指数衰减移动平均Gt。例如 β = 0.9 \beta=0.9 β=0.9
G t = β ⋅ G t − 1 + ( 1 − β ) ⋅ g t 2 G_t=\beta \cdot G_{t-1} + (1-\beta) \cdot g_t^2 Gt=βGt1+(1β)gt2
其中 β \beta β是自定义衰减率。例如0.9。
然后根据指数衰减移动平均来更新参数
θ t + 1 = θ t − η G t + ϵ ⋅ g t \theta_{t+1}=\theta_{t}-\frac{\eta}{\sqrt{G_t+\epsilon}} \cdot g_t θt+1=θtGt+ϵ ηgt

3.6、Adadelta

为了接近AdaGard多次迭代后,学习率逐渐下降至0的问题,AdaGrad在一个窗口w中对梯度进行求和,而不是对梯度平方一直累加,这和RMSprop的做法类似。
但是Adadelta不光考虑了二阶动量,还考虑了一阶的影响。Adadelta实际上是使用更新量的平方的指数加权平均来动态得到代替了全局的标量的学习率,意味着更新量的平方越小,则学习率也就越小。
G t = β ⋅ G t − 1 + ( 1 − β ) ⋅ g t 2 u t = β ⋅ u t − 1 + ( 1 − β ) ⋅ Δ θ t 2 θ t + 1 = θ t − η ⋅ u t + ϵ G t + ϵ ⋅ g t G_t=\beta \cdot G_{t-1} + (1-\beta) \cdot g_t^2 \\ u_t = \beta \cdot u_{t-1} + (1-\beta) \cdot \Delta\theta_t^2 \\ \theta_{t+1} = \theta_{t}-\eta \cdot \frac{\sqrt{u_t+\epsilon}}{\sqrt{G_t+\epsilon}} \cdot g_t Gt=βGt1+(1β)gt2ut=βut1+(1β)Δθt2θt+1=θtηGt+ϵ ut+ϵ gt

3.7、Adam 适应性矩估计

Adam是一种可以替代传统随机梯度下降过程的一阶优化算法,和SDG不同之处在于:

  • SGD保持单一的学习率更新所有权重,学习率在训练过程中并不会改变,Adam通过计算梯度的一阶矩估计和二阶矩估计为不同的参数设计独立的自适应学习率。
    Adam算法计算了梯度的二阶矩均值。和梯度的指数移动均值,超参数beta1和beta2控制了这些移动均值的衰减率。
  • Adam算法结合了RMSprop算法和动量法,不但使用动量作为参数更新方向,而且可以自适应调整学习率来改进梯度下降。
  • Adam的参数:
    η \eta η:学习率,(0.001)
    beta1:一阶矩估计的指数衰减率(0.9)
    beta2:二阶矩估计的指数衰减率(0.999)
    默认参数就可以解决大部分问题。
  • 计算步骤:
    首先计算梯度平方的指数加权平均
    G t = β 2 ⋅ G t − 1 + ( 1 − β 2 ) ⋅ g t 2 G_t=\beta_2 \cdot G_{t-1} + (1-\beta_2) \cdot g_t^2 Gt=β2Gt1+(1β2)gt2
    计算梯度的指数加权平均(动量法)
    M t = β 1 ⋅ M t − 1 + ( 1 − β 1 ) ⋅ g t M_t=\beta_1 \cdot M_{t-1} + (1-\beta_1 ) \cdot g_t Mt=β1Mt1+(1β1)gt
    其中 β 1 \beta_1 β1 β 2 \beta_2 β2分别为两个移动平均的衰减率,0.9和0.999
    然后对偏差进行修正
    M t ^ = M t 1 − β 1 t G t ^ = G t 1 − β 2 t \hat{M_t} = \frac{M_t}{1-\beta_1^t} \\ \hat{G_t} = \frac{G_t}{1-\beta_2^t} Mt^=1β1tMtGt^=1β2tGt
    计算参数更新参数
    θ t + 1 = θ t − η G t ^ + ϵ M t ^ \theta_{t+1} = \theta_t-\frac{\eta}{\sqrt{\hat{G_t}+\epsilon}} \hat{M_t} θt+1=θtGt^+ϵ ηMt^

3.8、Adamw

在Adam中可能会存在不收敛的问题,因为随着二阶动量的不断累加,学习率会越来越小,但是不一定会按照合适的速率缩小,如果在模型收敛之前就已经过于小,则最后收敛不到想要的位置。并且在很多数据集上Adam泛化性并不如SGD with Momentum,这里面一个重要原因就是Adam中L2正则项并不像SGD中那么有效。
AdamW使用了更严谨的权重衰减,其权重衰减只在最后更新公司中使用,不参与动量计算。 λ \lambda λ是正则化系数
M t = β 1 M t − 1 + ( 1 − β 1 ) g t G t = β 2 G t − 1 + ( 1 − β 2 ) g t 2 M t ^ = M t 1 − β 1 t G t ^ = G t 1 − β 2 t θ t + 1 = θ t − η ⋅ ( M t ^ G t ^ + ϵ + λ ⋅ θ t ) M_t=\beta_1 M_{t-1} + (1-\beta_1 ) g_t \\ G_t=\beta_2 G_{t-1} + (1-\beta_2)g_t^2 \\ \hat{M_t} = \frac{M_t}{1-\beta_1^t} \\ \hat{G_t} = \frac{G_t}{1-\beta_2^t} \\ \theta_{t+1} = \theta_t - \eta \cdot (\frac{\hat{M_t}}{\sqrt{\hat{G_t}+\epsilon}}+ \lambda \cdot \theta_t) Mt=β1Mt1+(1β1)gtGt=β2Gt1+(1β2)gt2Mt^=1β1tMtGt^=1β2tGtθt+1=θtη(Gt^+ϵ Mt^+λθt)

3.9、各个优化器特点以及演化对比

GD(梯度下降)/BGD(批量梯度下降):使用全部训练集,沿着梯度反方向以固定学习率更新参数。
缺点:计算全局梯度耗时长;对所有参数使用相同学习率;只根据当前时刻梯度,容易陷入局部最优解。

SGD(随机梯度下降):相较于GD,只使用1个样本的来计算梯度。
优点:对于大数据集可以更快进行更新。
缺点:学习率固定;使用一个样本的梯度,优化过程震荡,需要长时间才能收敛。
MBGD(小批量梯度下降):相较于SGD,使用一个batch的样本的梯度。收敛更稳定。

Momenum(动量优化):在SGD/MBGD基础上引入动量,每次的更新量不是梯度*学习率,而是动量。 M t = β ⋅ M t − 1 + η ⋅ g t M_t = \beta \cdot M_{t-1}+\eta \cdot g_t Mt=βMt1+ηgt
优点:加速收敛,抑制震荡,跳出局部最优解。
缺点:需要人工设置动量参数,学习率固定。

AdaGrad(自适应梯度优化器):自适应学习率,与梯度平方和有关
G t = G t − 1 + g t 2 θ t + 1 = θ t − η G t + ϵ ⋅ g t G_t=G_{t-1} + g_t^2 \\ \theta_{t+1}=\theta_{t}-\frac{\eta}{\sqrt{G_t+\epsilon}} \cdot g_t Gt=Gt1+gt2θt+1=θtGt+ϵ ηgt
但是这种方法会存在二阶动量一直累加的问题,学习率迟早要很小。

RMSProp(均方根传播):相较于AdaGrad,使用指数移动平均来解决学习率一直变小的问题。
G t = β ⋅ G t − 1 + ( 1 − β ) ⋅ g t 2 G_t=\beta \cdot G_{t-1} + (1-\beta) \cdot g_t^2 Gt=βGt1+(1β)gt2
但是模型还是会对初始学习率敏感。

Adadelta:相较于RMSProp,用梯度更新量的平方的指数加权平均,来动态的替代全局标量的学习率,避免了优化器对学习率的敏感。
G t = β ⋅ G t − 1 + ( 1 − β ) ⋅ g t 2 u t = β ⋅ u t − 1 + ( 1 − β ) ⋅ Δ θ t 2 θ t + 1 = θ t − η ⋅ u t + ϵ G t + ϵ ⋅ g t G_t=\beta \cdot G_{t-1} + (1-\beta) \cdot g_t^2 \\ u_t = \beta \cdot u_{t-1} + (1-\beta) \cdot \Delta\theta_t^2 \\ \theta_{t+1} = \theta_{t}-\eta \cdot \frac{\sqrt{u_t+\epsilon}}{\sqrt{G_t+\epsilon}} \cdot g_t Gt=βGt1+(1β)gt2ut=βut1+(1β)Δθt2θt+1=θtηGt+ϵ ut+ϵ gt

Adam(自适应矩估计):结合了Momentum和RMSProp的优点,既保留了动量,又有自适应学习率。和SGD with Momentum相比,自适应学习率可以很大程度上避免学习率选择不当带来的训练震荡或收敛速度慢的问题。

相关文章:

深度学习——激活函数、损失函数、优化器

深度学习——激活函数、损失函数、优化器 1、激活函数1.1、一些常见的激活函数1.1.1、sigmoid1.1.2、softmax1.1.3、tanh1.1.4、ReLU1.1.5、Leaky ReLU1.1.6、PReLU1.1.7、GeLU1.1.8、ELU 1.2、激活函数的特点1.2.1、非线性1.2.2、几乎处处可微1.2.3、计算简单1.2.4、非饱和性1…...

上拉模式下引脚电平与代码读取值的关系

在单片机系统中&#xff0c;引脚的输入模式设置对上拉模式下引脚电平及代码读取值有着关键影响。 当引脚被配置为上拉模式且无外部信号输入时&#xff0c;内部上拉电阻使引脚保持高电平。此时&#xff0c;代码读取该引脚的值为 1。例如在一个简单的电路中&#xff0c;仅设置了…...

UNIX简史

从1991年Linux出现至今&#xff0c;由于众多IT巨头以及技术社区的推动&#xff0c;Linux已经成为非常成熟、可用于各种关键领域的操作系统&#xff0c;适当了解其发展历史&#xff0c;对于理顺其技术流派、从而更好地学习和使用Linux具有重要意义。由于其基于UNIX系统二十多年的…...

python学opencv|读取图像(十三)BGR图像和HSV图像互相转换深入

【1】引言 前序学习过程中&#xff0c;我们偶然发现&#xff1a;如果原始图像是png格式&#xff0c;将其从BGR转向HSV&#xff0c;再从HSV转回BGR后&#xff0c;图像的效果要好于JPG格式。 文章链接为&#xff1a; python学opencv|读取图像&#xff08;十二&#xff09;BGR图…...

ElasticSearch 搜索、排序、分页功能

一、DSL 查询文档 ElasticSearch 的查询依然是基于 json 风格的 DSL 来实现的。 官方文档&#xff1a;https://www.elastic.co/guide/en/elasticsearch/reference/8.15/query-dsl.html 1.1 DSL 查询分类 常见的查询类型包括&#xff1a; 查询所有&#xff1a;查询出所有数…...

MAC虚拟机上安装WDA环境

MAC虚拟机上安装WDA环境 一、MAC虚拟机切换root权限二、macOS上安装xcode若你的macOS系统可以在appstore下载安装若你安装的macOS系统版本太低&#xff0c;无法在appstore上安装xcode 三、macOS上安装WebDriverAgent四、使用xcode配置WDA安装到手机上高版本系统支持 一、MAC虚拟…...

KDD 2025预讲会:10位一作的论文分享与话题思辨|12月18日全天直播

点击蓝字 关注我们 AI TIME欢迎每一位AI爱好者的加入&#xff01; 圆桌思辨&#xff1a;一作们的KDD 2025投稿经验分享与热点探讨 1. KDD 2025 与往年相比有哪些新变化&#xff1f;两次投稿周期的新规则有哪些影响&#xff1f; 2. 第一篇KDD的工作是如何成功被接收的&#xff1…...

Input system手游的控制

手游离不开触屏控制 新的inputsystem 实现过程 安装input system在projectsetting中的player的othersettings中active input handing设置both打开window的analysis的input debugger。在options中设置为simulate touch input from mouse or pen。 增强触摸控制的相关知识 启…...

在 Visual Studio Code 中编译、调试和执行 Makefile 工程 llama2.c

在 Visual Studio Code 中编译、调试和执行 Makefile 工程 llama2.c 1. Installing the extension (在 Visual Studio Code 中安装插件)1.1. Extensions for Visual Studio Code1.2. C/C1.2.1. Pre-requisites 1.3. Makefile Tools 2. Configuring your project (配置项目)2.1.…...

KMP 算法

这里写目录标题 KMP数组计算方式**问题描述****初始准备****逐步推导过程****Step 1: i 1&#xff0c;子串为 ab****Step 2: i 2&#xff0c;子串为 aba****Step 3: i 3&#xff0c;子串为 abab****Step 4: i 4&#xff0c;子串为 ababa****Step 5: i 5&#xff0c;子串为…...

计算机网络中的三大交换技术详解与实现

目录 计算机网络中的三大交换技术详解与实现1. 计算机网络中的交换技术概述1.1 交换技术的意义1.2 三大交换技术简介 2. 电路交换技术2.1 理论介绍2.2 Python实现及代码详解2.3 案例分析 3. 分组交换技术3.1 理论介绍3.2 Python实现及代码详解3.3 案例分析 4. 报文交换技术4.1 …...

echarts图表自定义配置(二)——代码封装

下图是初版&#xff0c;火山图的代码。可以看出&#xff0c;里面的变量&#xff0c;逻辑&#xff0c;函数存在冗余&#xff0c;基本上都是改了参数&#xff0c;同样的get和set&#xff0c;去刷新图表&#xff1b;对于往后继续开发十几二十个图表&#xff0c;会很麻烦。因此需要…...

Serdes技术与Xilinx GT概览

目录 一、前言 二、Serdes技术 2.1 芯片间信号传输 2.2 Serdes技术 三、 Xilinx GT 3.1 7系列器件GT 3.2 Ultrascale GT 3.3 Ultrascale GT 四、参考资料 一、前言 对于芯片间高速信号传输技术&#xff0c;不得不提serdes以及在Xilinx在此基础上的高速收发器GT系列&…...

WEB开发: Node.js路由之由浅入深(三)自动配置路由 - 全栈工程师入门

前面我们一起学习了Node.js路由的两个进阶&#xff0c; &#xff08;1&#xff09;WEB开发&#xff1a; Node.js路由之由浅入深&#xff08;一&#xff09; - 全栈工程师入门 &#xff08;2&#xff09;WEB开发&#xff1a; Node.js路由之由浅入深&#xff08;二&#xff09;…...

6-9 捕获 0 异常(1)

中断号的 处理是这样的。 1、 cpu 根据中断号 去中断向量表 去找 第几个 表。、 2、 而 中断向量表 的内容是 GDT 的选择子。 3、 由于使用是的 平坦模型&#xff0c;所以只需要 将具体的函数给到 中断向量表的 offset 字段就可以了。 接下来 就是 在 代码中定义 中断门的属…...

社区团购创新模式与新兴技术融合的深度探索:基于开源、AI 智能名片、2+1 链动模式与 S2B2C 商城小程序

摘要&#xff1a;本文聚焦于社区团购这一新兴零售业态&#xff0c;深入剖析其“线上预售&#xff0c;线下自提&#xff0c;以销定采&#xff0c;落地集配”的 16 字箴言所蕴含的商业逻辑。详细探讨在物流与信息流层面社区团购的独特优势&#xff0c;并在此基础上研究开源理念、…...

day45 198.打家劫舍 213.打家劫舍II 337.打家劫舍III

198.打家劫舍 相邻的房子不可以打劫&#xff0c;所以递推式需要考虑&#xff1b; 初始化也需要考虑&#xff0c;可以从两个方向入手 方向1&#xff1a;从后往前看&#xff0c;dp[i] dp[i-1] class Solution { public:int rob(vector<int>& nums) {if (nums.size(…...

SQL server学习02-使用T-SQL创建数据库

目录 一&#xff0c; 使用T-SQL创建数据库 1&#xff0c;数据库的存储结构 2&#xff0c;创建数据库的语法结构 1&#xff09;使用T-SQL创建学生成绩管理数据库 二&#xff0c;使用T-SQL修改数据库 1&#xff0c;修改数据库的语法结构 1&#xff09;修改学生成绩管理数…...

绘图方式集合

1. 流程图 1.1 PlantUML 代码绘制流程图 1.1.1 简介 1.1.2 网站 你可以使用以下网站来将 PlantUML 代码转换成可视化的流程图&#xff1a; PlantUML 官方网站 网站地址&#xff1a;https://plantuml.com/plantuml此网站提供了一个在线工具&#xff0c;可以直接输入 PlantUM…...

sqoop导入hdfs,hive

sqoop将mysql中的表导入到hdfs中 sqoop import \ > --connect jdbc:mysql://192.168.52.150/test \ > --username root \ > --password 123456 \ > --table emp \ > --delete-target-dir \ > --target-dir /sqoop_works/emp_1将数据导入hive中&#xff0c;首…...

C语言动态内存管理【进阶--5--】

文章目录 [toc] 动态内存管理一、作用即意义二、动态内存函数的介绍Ⅰ、malloc()函数、free()函数Ⅱ、calloc()函数Ⅲ、realloc()函数 三、常见的动态内存错误Ⅰ、对NULL指针的解引用操作Ⅱ、对动态开辟空间的越界访问Ⅲ、对非动态开辟的内存使用free释放Ⅳ、使用free释放动态开…...

Hadoop其四,片与块,MapReduce原理,Shuffle过程,Combiner

目录 一、关于片和块 二、MapReduce的原理 MapTask执行阶段 ReduceTask的执行流程&#xff1a; 三、Shuffle 过程 map端&#xff1a; reduce端&#xff1a; 环形缓冲区&#xff1a; 四、Combiner 【可有可无】 五、需要记忆的内容 一、关于片和块 假如我现在500M这样…...

引领未来的变革:15种前沿RAG技术及其应用探索

在现代人工智能领域&#xff0c;检索增强生成&#xff08;RAG&#xff09;技术逐渐成为推动各种应用的重要力量。这些技术通过结合信息检索与文本生成&#xff0c;能够更有效地处理和利用信息。本文将详细介绍15种前沿RAG技术及其具体应用实例&#xff0c;以帮助您更好地理解这…...

gradle在IDEA 中无法使用的启动守护线程的问题

最近打开一个比较早的项目&#xff0c;Gradle 配置没有问题&#xff0c;IDEA 打开Java项目却不能初始化守护线程&#xff0c;UI 上只能看到失败&#xff0c;看不到具体原因。 首先尝试了升级最新的gradle 版本8.11, 实际上这个版本在本地命令行都不能正常工作&#xff0c;没有…...

C++小白实习日记——Pollnet,Efvi,UDP,数据类型转换(上)

上周主要是熟悉了一下公司内部一些自定义结构体对应的数据类型&#xff0c;要求&#xff1a;读取文件&#xff0c;将文件中数据转化为定义的结构体中的数据类型&#xff0c;按照时间进行排序&#xff0c;用UDP发送数据&#xff1b;在另一台服务器上接收数据&#xff0c;按照定义…...

git安装教程(Git-2.38.1-64-bit)

目录 一、git下载 二、git安装 1.更改安装路径 2.安装组件 3.选择开始菜单文件夹 4.选择Git默认编辑器 5.决定初始化新项目&#xff08;仓库&#xff09;的主干名字 6.修改Git的环境变量 7.选择SSH执行文件 9.选择HTTPS后端传输 10.配置行尾符号转换 11.配置终端模…...

C# OpenCvSharp DNN 实现百度网盘AI大赛-表格检测第2名方案第三部分-表格方向识别

目录 说明 效果 模型 项目 ​编辑 代码 参考 下载 其他 说明 百度网盘AI大赛-表格检测的第2名方案。 该算法包含表格边界框检测、表格分割和表格方向识别三个部分&#xff0c;首先&#xff0c;ppyoloe-plus-x 对边界框进行预测&#xff0c;并对置信度较高的表格边界…...

selenium 验证码滑块对齐没有验证通过

描述&#xff1a; 最近使用seleniuim采集有滑块验证码的数据&#xff0c;遇到了移动滑块对齐后&#xff0c;还是无法通过验证&#xff0c;经过模拟真人多次移动、控制移动时间(避免过快)一番尝试后、最终通过模拟抖动得以解决 解决办法&#xff1a; 把yoffset的值改为-6~6的…...

【Neo4J】neo4j docker容器下的备份与恢复

文章目录 一. 官网说明1. 操作说明2. 注意事项 二. docker 容器化操作1. 导出&#xff08;备份&#xff09;停止容器执行备份 2. 导入&#xff08;恢复&#xff09;停止容器(如果未停止)执行导入 3. 启动容器 一. 官网说明 https://neo4j.com/docs/operations-manual/current/…...

Java实现雪花算法获取id

Java实现雪花算法获取id 在 Java 中实现雪花算法&#xff08;Snowflake&#xff09;时&#xff0c;通常会设计一个工具类来生成全局唯一的 ID。这个工具类可以封装雪花算法的逻辑&#xff0c;并提供简单的接口来生成 ID。 以下是一个完整的 Java 工具类实现雪花算法的例子&am…...

Leetcode1338:数组大小减半

题目描述&#xff1a; 给你一个整数数组 arr。你可以从中选出一个整数集合&#xff0c;并删除这些整数在数组中的每次出现。 返回 至少 能删除数组中的一半整数的整数集合的最小大小。 代码思路&#xff1a; 这个代码的目的是解决一个特定的问题&#xff1a;给定一个整数数…...

【系统思辨】分散注意

注意力在我们的日常生活和工作中扮演着至关重要的角色。注意力可以提高效率和准确性、减少错误和失误&#xff0c;提升学习效率&#xff0c;促进创造力。与此同时&#xff0c;各种各样的生活事件在分散我们的注意力&#xff0c;并且还有很多分散我们注意的手段&#xff0c;比如…...

微信小程序中 Echarts 的巧妙运用

一、引入 Echarts 的准备工作 在微信小程序中引入 Echarts 需要进行一系列的准备工作。首先&#xff0c;我们可以从 echarts 官网或 GitHub 上下载 echarts-for-weixin 项目。找到其中的 ec-canvas 文件夹&#xff0c;这个文件夹将是我们引入到微信小程序项目中的关键部分。 …...

opencv——图片矫正

图像矫正 图像矫正的原理是透视变换&#xff0c;下面来介绍一下透视变换的概念。 听名字有点熟&#xff0c;我们在图像旋转里接触过仿射变换&#xff0c;知道仿射变换是把一个二维坐标系转换到另一个二维坐标系的过程&#xff0c;转换过程坐标点的相对位置和属性不发生变换&a…...

Gate学习(7)引入体素源

一、从GitHub下载体素源模型源码 下载地址&#xff1a;BenAuer2021/Phantoms-for-Nuclear-Medicine-Imaging-Simulation&#xff1a;用于核医学成像应用的模型&#xff08;闪烁显像、SPECT 和 PET&#xff09; --- BenAuer2021/Phantoms-For-Nuclear-Medicine-Imaging-Simulat…...

腾讯微信Android面试题及参考答案(多张原理图)

Android 应用的启动流程如下: 当用户点击应用图标时,首先会通过 Launcher(桌面启动器)来响应这个操作。Launcher 本身也是一个 Android 应用,它运行在系统中,负责管理和显示桌面上的图标等信息。 系统会检查应用是否已经有进程存在。如果没有,就会通过 Zygote 进程来孵化…...

【Android】View的工作流程

View的工作流程 开始了解一下View的工作流程&#xff0c;就是measure、layout和draw。measure用来测量View的宽高&#xff0c;layout用来确定View的位置&#xff0c;draw则用来绘制View。这一讲我们来看看measure流程&#xff0c;measure流程分为View的measure流程和ViewGroup…...

Linux基础指令

使用 tab 键补全 我们敲的所有的 Linux 命令 , 都可以使用 tab 键来尝试补全 , 加快效率 . 使用 ctrl c 重新输入 如果命令或者目录敲错了 , 可以 ctrl c 取消当前的命令 . ls &#xff1a;列出当前目录中的文件和子目录 语法 &#xff1a; ls [ 选项 ] [ 目录或文…...

Gemini 2.0 Flash重磅发布:多模态AI大模型,赋能实时交互与智能助手新体验

点击访问 chatTools 免费体验GPT最新模型&#xff0c;包括o1推理模型、GPT4o、Claude、Gemini等模型&#xff01; 在AI领域竞争日益激烈的今天&#xff0c;谷歌再次亮剑&#xff0c;推出了新一代至强AI大模型——Gemini 2.0 Flash。这款模型不仅具备强大的多模态输入输出能力&a…...

项目十二 杜甫作品问卷

【项目目标】 理解网格系统的原理。理解媒体查询的工作原理。【項目内容】 使用网格系统进行响应式网页设计。运用媒体查询对不同类型的设备应用不同的样式。【项目步骤】 Bootstrap 框架资源既可以直接从 CDN 服务商服务器中引入,也可以加入本地素材文件夹中给出的资…...

7_Sass Introspection 函数 --[CSS预处理]

Sass 的 Introspection 函数允许开发者检查和操作样式表的内部结构&#xff0c;包括选择器、属性、值等。这些函数提供了对编译过程中 Sass 文件内容的深入访问能力&#xff0c;使得更复杂的逻辑处理成为可能。以下是一些常用的 Sass Introspection 函数及其用法示例&#xff1…...

Qt:Q_GLOBAL_STATIC实现单例(附带单例使用和内存管理)

转载 https://blog.csdn.net/m0_71489826/article/details/142288179 前言 本文主要写Q_GLOBAL_STATIC实现单例以及单例的释放&#xff0c;网上很多教程只有单例的创建&#xff0c;但是并没有告诉我们单例的内存管理&#xff0c;这就很头疼。 正文 使用 Qt 的 Q_GLOBAL_STA…...

HTML/CSS总结

HTML 1.1 标题标签h 为了使网页更具有语义化&#xff0c;我们经常会在页面中用到标题标签&#xff0c;HTML提供了6个等级的标题&#xff0c;即 标题标签语义&#xff1a; 作为标题使用&#xff0c;并且依据重要性递减 其基本语法格式如下&#xff1a; <h1> 标题文本…...

字符串性能对比

效率(1) : String.indexOf与String.contains效率测试_string contains效率-CSDN博客 结论是前者效率高&#xff0c;源码里面conatins是使用indexof 在jdk8中contains直接调用的indexOf(其他版本没有验证),所以要说效率来说肯定是indexOf高,但contains也就多了一层方法栈,so 什…...

【漫话机器学习系列】005.神经网络的结构(architecture on the neural network)

神经网络&#xff08;Neural Network&#xff09;是一种模拟人脑神经系统的计算模型&#xff0c;由大量相互连接的神经元&#xff08;节点&#xff09;组成&#xff0c;广泛应用于深度学习和机器学习领域。以下是神经网络的基本结构及关键组成部分。 1. 神经网络的基本组成 一…...

关卡选择与布局器

unity布局管理器 使用unity布局管理器轻松对关卡选择进行布局。 实现过程 准备普通按钮button设置字体和对应的sprite设置父gameobject&#xff08;levelbase&#xff09; 再创建UI.image&#xff08;selectbackground&#xff09;布局背景和大小gameobject&#xff08;grid…...

数据分析实战—房价特征关系

1.实战内容 &#xff08;1&#xff09; 读取房价特征关系表&#xff08;house_price.npz&#xff09;绘制离地铁站的距离与单位面积的房价的散点图&#xff0c;并对其进行分析&#xff1b; import pandas as pd import numpy as np import warnings warnings.filterwarnings(&…...

@ResponseBody详解

ResponseBody 是 Spring Framework 中的一种注解&#xff0c;用于表示返回的内容应该直接写入 HTTP 响应体&#xff0c;而不是通过视图解析器来渲染一个视图&#xff08;如 JSP 页&#xff09;。当你在控制器的方法上使用 ResponseBody 时&#xff0c;Spring 会将方法的返回值直…...

Harmony Next开发通过bindSheet绑定半模态窗口

示例概述 Harmony Next开发通过bindSheet绑定半模态窗口 知识点 半模态窗口父子组件传值 组件 LoginComponent Component struct LoginComponent {// Prop 父子单项绑定值Prop message:string // Link 父子双向绑定值Link userName:stringLink password:stringLink isSh…...

Redis--高并发分布式结构

目录 一、引言 二、redis 1.什么是redis&#xff1f; 三、基础概念 1.什么是分布式&#xff1f; 2.应用服务和数据库服务分离 3.负载均衡 4.分库分表 5.微服务架构 四、总结 一、引言 本篇文章就简单介绍一下什么是redis&#xff0c;以及一些关于高并发和分布式结构的…...