Python | 从零实现10种优化算法并比较

ops/2024/12/18 3:42:19/

Python | 从零实现10种优化算法并比较

  • 🚀SGD
    • 算法原理
    • 代码实现
    • 可视效果
  • 🚀 Adagrad
    • 算法原理
    • 代码实现
    • 可视效果
  • 🚀 Adadelta
    • 算法原理
    • 代码实现
    • 可视效果
  • 🚀 RMSProp
    • 算法原理
    • 代码实现
    • 可视效果
  • 🚀 Adam
    • 算法原理
    • 代码实现
    • 可视效果
  • 🚀 AdamW
    • 算法原理
    • 代码实现
    • 可视效果
  • 🚀 SparseAdam
    • 算法原理
    • 代码实现
    • 可视效果
  • 🚀 Adamax
    • 算法原理
    • 代码实现
    • 可视效果
  • 🚀 NAdam
    • 算法原理
    • 代码实现
    • 可视效果
  • 🚀 RProp
    • 算法原理
    • 代码实现
    • 可视效果
  • 🚀 代码结构

🚀SGD

算法原理

随机梯度下降(Stochastic Gradient Descent,SGD)是一种基于梯度的优化算法,用于在机器学习和深度学习中最小化目标函数。以下是其基本原理和参数更新数学公式的简要说明:

  • 基本原理: SGD旨在通过迭代的方式,沿着目标函数梯度的反方向更新模型参数,以逐步找到使目标函数最小化的最优参数值。

  • 在每次迭代中,随机选取一个训练样本,计算该样本对应的损失函数关于模型参数的梯度,然后根据这个梯度来更新模型参数。通过不断地重复这个过程,模型参数逐渐向最优解靠近,使得损失函数的值不断减小。

  • 参数更新数学公式:设 θ \theta θ 为模型参数, J ( θ ) J(\theta) J(θ)为目标函数, η \eta η为学习率,在第 t t t次迭代时,随机选取一个样本 ( x i , y i ) (x_i, y_i) (xi,yi),计算该样本损失函数 L ( y i , f ( x i ; θ ) ) L(y_i, f(x_i; \theta)) L(yi,f(xi;θ))关于参数 θ \theta θ的梯度 ∇ L ( y i , f ( x i ; θ ) ) \nabla L(y_i, f(x_i; \theta)) L(yi,f(xi;θ)),则参数更新公式为:
    θ t + 1 = θ t − η ∇ L ( y i , f ( x i ; θ t ) ) \theta_{t + 1}=\theta_t - \eta \nabla L(y_i, f(x_i; \theta_t)) θt+1=θtηL(yi,f(xi;θt))
    其中, θ t \theta_t θt是第 t t t次迭代时的参数值, θ t + 1 \theta_{t + 1} θt+1是第 t + 1 t + 1 t+1次迭代时的参数值。学习率 η \eta η是一个超参数,用于控制参数更新的步长,通常需要根据具体问题进行调整。

代码实现

本文这里实际实现的是GD算法,因为样例优化问题比较简单: f ( x , y ) = 3 x 2 + 4 y 2 f(x,y)=3x^2+4y^2 f(x,y)=3x2+4y2

python">class SGD:def __init__(self, lr=0.01):self.lr = lrdef update(self, w, grad_w):return w - self.lr * grad_w

可视效果

优化的损失函数为: f ( x , y ) = 3 x 2 + 4 y 2 f(x,y)=3x^2+4y^2 f(x,y)=3x2+4y2
在这里插入图片描述
在这里插入图片描述

🚀 Adagrad

算法原理

  • 基本原理:Adagrad根据每个参数的历史梯度平方和来调整学习率,对于频繁出现的参数,其学习率会逐渐减小,而对于不常出现的参数,学习率则相对较大,从而实现了自适应学习率的调整。
  • 参数更新数学公式
    G t , i i = ∑ k = 1 t g k , i 2 G_{t,ii}=\sum_{k = 1}^{t}g_{k,i}^2 Gt,ii=k=1tgk,i2
    θ t + 1 = θ t − η G t , i i + ϵ g t \theta_{t + 1}=\theta_t-\frac{\eta}{\sqrt{G_{t,ii}+\epsilon}}g_t θt+1=θtGt,ii+ϵ ηgt
    其中, g k , i g_{k,i} gk,i是第 k k k步参数 i i i的梯度, G t , i i G_{t,ii} Gt,ii是参数 i i i到第 t t t步为止的梯度平方和, η \eta η是初始学习率, ϵ \epsilon ϵ是一个小常数,用于防止分母为零。

代码实现

python">import numpy as npclass Adagrad:def __init__(self, eps=1e-8):self.eps = epsself.G = Nonedef update(self, w, grad_w):if self.G is None:self.G = np.zeros_like(grad_w)self.G += grad_w ** 2dx = grad_w / (np.sqrt(self.G) + self.eps)return w - dx

可视效果

优化的损失函数为: f ( x , y ) = 3 x 2 + 4 y 2 f(x,y)=3x^2+4y^2 f(x,y)=3x2+4y2
在这里插入图片描述
在这里插入图片描述

🚀 Adadelta

算法原理

  • 基本原理:Adadelta是Adagrad的一种改进算法,旨在解决Adagrad学习率单调递减的问题。它通过引入一个随时间衰减的平均梯度平方项和一个自适应的学习率来调整参数更新步长,使得在训练过程中学习率能够根据问题的复杂度自适应调整。
  • 参数更新数学公式
    E [ g 2 ] t = ρ E [ g 2 ] t − 1 + ( 1 − ρ ) g t 2 E[g^2]_t=\rho E[g^2]_{t - 1}+(1-\rho)g_t^2 E[g2]t=ρE[g2]t1+(1ρ)gt2
    Δ θ t = − E [ Δ θ 2 ] t − 1 + ϵ E [ g 2 ] t + ϵ g t \Delta\theta_t=-\frac{\sqrt{E[\Delta\theta^2]_{t - 1}+\epsilon}}{\sqrt{E[g^2]_t+\epsilon}}g_t Δθt=E[g2]t+ϵ E[Δθ2]t1+ϵ gt
    θ t + 1 = θ t + Δ θ t \theta_{t + 1}=\theta_t+\Delta\theta_t θt+1=θt+Δθt
    其中, g t g_t gt是第 t t t步的梯度, E [ g 2 ] t E[g^2]_t E[g2]t是梯度平方的指数移动平均, ρ \rho ρ是衰减率, Δ θ t \Delta\theta_t Δθt是参数更新量, E [ Δ θ 2 ] t − 1 E[\Delta\theta^2]_{t - 1} E[Δθ2]t1是参数更新量平方的指数移动平均, ϵ \epsilon ϵ是一个小常数,用于防止分母为零。

代码实现

python">import numpy as npclass Adadelta:def __init__(self, rho=0.95, eps=1e-6):self.rho = rhoself.eps = epsself.Eg2 = Noneself.Edx2 = Noneself.delta_x = Nonedef update(self, w, grad_w):if self.Eg2 is None:self.Eg2 = np.zeros_like(grad_w)self.Edx2 = np.zeros_like(w)self.delta_x = np.zeros_like(w)self.Eg2 = self.rho * self.Eg2 + (1 - self.rho) * grad_w ** 2dx = np.sqrt((self.Edx2 + self.eps) / (self.Eg2 + self.eps)) * grad_wself.Edx2 = self.rho * self.Edx2 + (1 - self.rho) * dx ** 2self.delta_x = -dxreturn w + self.delta_x

可视效果

在这里插入图片描述
在这里插入图片描述

🚀 RMSProp

算法原理

  • 基本原理:RMSProp通过对梯度平方的指数移动平均来调整学习率,使得学习率能够根据参数的重要性和梯度的变化情况自适应调整,在一定程度上解决了Adagrad中学习率单调递减的问题,提高了训练的稳定性和收敛速度。
  • 参数更新数学公式
    E [ g 2 ] t = ρ E [ g 2 ] t − 1 + ( 1 − ρ ) g t 2 E[g^2]_t=\rho E[g^2]_{t - 1}+(1-\rho)g_t^2 E[g2]t=ρE[g2]t1+(1ρ)gt2
    θ t + 1 = θ t − η E [ g 2 ] t + ϵ g t \theta_{t + 1}=\theta_t-\frac{\eta}{\sqrt{E[g^2]_t+\epsilon}}g_t θt+1=θtE[g2]t+ϵ ηgt
    其中,各参数含义与Adadelta中的类似。

代码实现

python">import numpy as npclass RMSProp:def __init__(self, lr=0.01, rho=0.9, eps=1e-8):self.lr = lrself.rho = rhoself.eps = epsself.Eg2 = Nonedef update(self, w, grad_w):if self.Eg2 is None:self.Eg2 = np.zeros_like(grad_w)self.Eg2 = self.rho * self.Eg2 + (1 - self.rho) * grad_w ** 2dx = self.lr * grad_w / (np.sqrt(self.Eg2) + self.eps)return w - dx

可视效果

在这里插入图片描述
在这里插入图片描述

🚀 Adam

算法原理

  • 基本原理:Adam结合了Adagrad和RMSProp的优点,通过计算梯度的一阶矩估计(均值)和二阶矩估计(方差)来调整学习率,能够在训练初期利用较大的学习率快速收敛,在后期根据梯度的变化情况自适应地调整学习率,从而提高训练的稳定性和收敛速度。
  • 参数更新数学公式
    m t = β 1 m t − 1 + ( 1 − β 1 ) g t m_t=\beta_1m_{t - 1}+(1-\beta_1)g_t mt=β1mt1+(1β1)gt
    v t = β 2 v t − 1 + ( 1 − β 2 ) g t 2 v_t=\beta_2v_{t - 1}+(1-\beta_2)g_t^2 vt=β2vt1+(1β2)gt2
    m ^ t = m t 1 − β 1 t \hat{m}_t=\frac{m_t}{1-\beta_1^t} m^t=1β1tmt
    v ^ t = v t 1 − β 2 t \hat{v}_t=\frac{v_t}{1-\beta_2^t} v^t=1β2tvt
    θ t + 1 = θ t − η v ^ t + ϵ m ^ t \theta_{t + 1}=\theta_t-\frac{\eta}{\sqrt{\hat{v}_t}+\epsilon}\hat{m}_t θt+1=θtv^t +ϵηm^t
    其中, m t m_t mt是一阶矩估计, v t v_t vt是二阶矩估计, β 1 \beta_1 β1 β 2 \beta_2 β2是指数衰减率, m ^ t \hat{m}_t m^t v ^ t \hat{v}_t v^t是偏差修正后的一阶矩估计和二阶矩估计, η \eta η是学习率, ϵ \epsilon ϵ是一个小常数,用于防止分母为零。

代码实现

python">import numpy as npclass Adam:def __init__(self, lr=0.01, beta1=0.9, beta2=0.999, eps=1e-8):self.lr = lrself.beta1 = beta1self.beta2 = beta2self.eps = epsself.m = Noneself.v = Noneself.t = 0def update(self, w, grad_w):self.t += 1if self.m is None:self.m = np.zeros_like(grad_w)self.v = np.zeros_like(grad_w)self.m = self.beta1 * self.m + (1 - self.beta1) * grad_wself.v = self.beta2 * self.v + (1 - self.beta2) * grad_w ** 2m_hat = self.m / (1 - self.beta1 ** self.t)v_hat = self.v / (1 - self.beta2 ** self.t)dx = self.lr * m_hat / (np.sqrt(v_hat) + self.eps)return w - dx

可视效果

在这里插入图片描述
在这里插入图片描述

🚀 AdamW

算法原理

  • 基本原理:AdamW在Adam的基础上,对权重衰减进行了更合理的处理,将权重衰减从优化器的参数更新中分离出来,直接作用于参数本身,而不是像传统的方法那样将权重衰减与学习率耦合在一起,从而在一定程度上提高了模型的泛化能力和训练效果。
  • 参数更新数学公式:与Adam类似,只是在更新参数时多了一项权重衰减项:
    θ t + 1 = θ t − η v ^ t + ϵ m ^ t − λ θ t \theta_{t + 1}=\theta_t-\frac{\eta}{\sqrt{\hat{v}_t}+\epsilon}\hat{m}_t-\lambda\theta_t θt+1=θtv^t +ϵηm^tλθt
    其中, λ \lambda λ是权重衰减系数,其他参数含义与Adam中相同。

代码实现

python">import numpy as npclass AdamW:def __init__(self, lr=0.001, beta1=0.9, beta2=0.999, eps=1e-8, weight_decay=0.01):self.lr = lrself.beta1 = beta1self.beta2 = beta2self.eps = epsself.weight_decay = weight_decayself.m = Noneself.v = Noneself.t = 0def update(self, w, grad_w):self.t += 1if self.m is None:self.m = np.zeros_like(grad_w)self.v = np.zeros_like(grad_w)self.m = self.beta1 * self.m + (1 - self.beta1) * grad_wself.v = self.beta2 * self.v + (1 - self.beta2) * grad_w ** 2m_hat = self.m / (1 - self.beta1 ** self.t)v_hat = self.v / (1 - self.beta2 ** self.t)# 加入权重衰减项update = (self.lr * m_hat / (np.sqrt(v_hat) + self.eps)) + self.weight_decay * wreturn w - update

可视效果

在这里插入图片描述
在这里插入图片描述

🚀 SparseAdam

算法原理

  • 基本原理:SparseAdam是Adam的一种变体,专门用于处理稀疏数据。它在计算梯度的一阶矩估计和二阶矩估计时,只对非零梯度进行更新,从而提高了计算效率,同时也能在一定程度上保证模型的训练效果。
  • 参数更新数学公式:与Adam类似,但在计算 m t m_t mt v t v_t vt时只考虑非零梯度:
    m t = β 1 m t − 1 + ( 1 − β 1 ) g t m_t=\beta_1m_{t - 1}+(1-\beta_1)g_t mt=β1mt1+(1β1)gt
    v t = β 2 v t − 1 + ( 1 − β 2 ) g t 2 v_t=\beta_2v_{t - 1}+(1-\beta_2)g_t^2 vt=β2vt1+(1β2)gt2
    m ^ t = m t 1 − β 1 t \hat{m}_t=\frac{m_t}{1-\beta_1^t} m^t=1β1tmt
    v ^ t = v t 1 − β 2 t \hat{v}_t=\frac{v_t}{1-\beta_2^t} v^t=1β2tvt
    θ t + 1 = θ t − η v ^ t + ϵ m ^ t \theta_{t + 1}=\theta_t-\frac{\eta}{\sqrt{\hat{v}_t}+\epsilon}\hat{m}_t θt+1=θtv^t +ϵηm^t
    其中, g t g_t gt为稀疏梯度,其他参数含义与Adam中相同。

代码实现

python">import numpy as npclass SparseAdam:def __init__(self, lr=0.01, beta1=0.9, beta2=0.999, eps=1e-8):self.lr = lrself.beta1 = beta1self.beta2 = beta2self.eps = epsself.m = Noneself.v = Noneself.t = 0def update(self, w, grad_w):self.t += 1if self.m is None:self.m = {}self.v = {}for index in np.ndindex(grad_w.shape):if index not in self.m:self.m[index] = np.zeros(1)self.v[index] = np.zeros(1)g = grad_w[index]self.m[index] = self.beta1 * self.m[index] + (1 - self.beta1) * gself.v[index] = self.beta2 * self.v[index] + (1 - self.beta2) * g ** 2m_hat = self.m[index] / (1 - self.beta1 ** self.t)v_hat = self.v[index] / (1 - self.beta2 ** self.t)dx = self.lr * m_hat / (np.sqrt(v_hat) + self.eps)w[index] -= dxreturn w

可视效果

在这里插入图片描述
在这里插入图片描述

🚀 Adamax

算法原理

  • 基本原理:Adamax是Adam的一种变体,它对Adam中的二阶矩估计进行了修改,使用了无穷范数来代替原来的 L 2 L_2 L2范数,在一些情况下可能具有更好的性能和稳定性。
  • 参数更新数学公式
    m t = β 1 m t − 1 + ( 1 − β 1 ) g t m_t=\beta_1m_{t - 1}+(1-\beta_1)g_t mt=β1mt1+(1β1)gt
    u t = max ⁡ ( β 2 u t − 1 , ∣ g t ∣ ) u_t=\max(\beta_2u_{t - 1},\vert g_t\vert) ut=max(β2ut1,gt)
    m ^ t = m t 1 − β 1 t \hat{m}_t=\frac{m_t}{1-\beta_1^t} m^t=1β1tmt
    θ t + 1 = θ t − η u t m ^ t \theta_{t + 1}=\theta_t-\frac{\eta}{u_t}\hat{m}_t θt+1=θtutηm^t
    其中, m t m_t mt β 1 \beta_1 β1 m ^ t \hat{m}_t m^t的含义与Adam中相同, u t u_t ut是无穷范数的指数移动平均, ∣ g t ∣ \vert g_t\vert gt是第 t t t步梯度的绝对值, η \eta η是学习率。

代码实现

python">import numpy as npclass Adamax:def __init__(self, lr=0.01, beta1=0.9, beta2=0.999, eps=1e-8):self.lr = lrself.beta1 = beta1self.beta2 = beta2self.eps = epsself.m = Noneself.u = Noneself.t = 0def update(self, w, grad_w):self.t += 1if self.m is None:self.m = np.zeros_like(grad_w)self.u = np.zeros_like(grad_w)self.m = self.beta1 * self.m + (1 - self.beta1) * grad_wself.u = np.maximum(self.beta2 * self.u, np.abs(grad_w))m_hat = self.m / (1 - self.beta1 ** self.t)dx = self.lr * m_hat / (self.u + self.eps)return w - dx

可视效果

在这里插入图片描述
在这里插入图片描述

🚀 NAdam

算法原理

  • 基本原理:NAdam是在Adam的基础上结合了Nesterov加速梯度(NAG)的思想,通过对未来梯度的近似估计来调整参数更新的方向,使得参数更新能够更快速地向最优解收敛,进一步提高了训练的效率和收敛速度。
  • 参数更新数学公式
    m t = β 1 m t − 1 + ( 1 − β 1 ) g t m_t=\beta_1m_{t - 1}+(1-\beta_1)g_t mt=β1mt1+(1β1)gt
    m ^ t = m t 1 − β 1 t \hat{m}_t=\frac{m_t}{1-\beta_1^t} m^t=1β1tmt
    g t ′ = β 1 m t − 1 1 − β 1 t + ( 1 − β 1 ) g t g_t^\prime=\frac{\beta_1m_{t - 1}}{1-\beta_1^t}+(1-\beta_1)g_t gt=1β1tβ1mt1+(1β1)gt
    v t = β 2 v t − 1 + ( 1 − β 2 ) g t 2 v_t=\beta_2v_{t - 1}+(1-\beta_2)g_t^2 vt=β2vt1+(1β2)gt2
    v ^ t = v t 1 − β 2 t \hat{v}_t=\frac{v_t}{1-\beta_2^t} v^t=1β2tvt
    θ t + 1 = θ t − η v ^ t + ϵ g t ′ \theta_{t + 1}=\theta_t-\frac{\eta}{\sqrt{\hat{v}_t}+\epsilon}g_t^\prime θt+1=θtv^t +ϵηgt
    其中,各参数含义与Adam中类似。

代码实现

python">import numpy as npclass NAdam:def __init__(self, lr=0.01, beta1=0.9, beta2=0.999, eps=1e-8):self.lr = lrself.beta1 = beta1self.beta2 = beta2self.eps = epsself.m = Noneself.v = Noneself.t = 0def update(self, w, grad_w):self.t += 1if self.m is None:self.m = np.zeros_like(grad_w)self.v = np.zeros_like(grad_w)self.m = self.beta1 * self.m + (1 - self.beta1) * grad_wself.v = self.beta2 * self.v + (1 - self.beta2) * grad_w ** 2m_hat = self.beta1 * self.m / (1 - self.beta1 ** self.t) + (1 - self.beta1) * grad_w / (1 - self.beta1 ** self.t)v_hat = self.v / (1 - self.beta2 ** self.t)dx = self.lr * m_hat / (np.sqrt(v_hat) + self.eps)return w - dx

可视效果

在这里插入图片描述
在这里插入图片描述

🚀 RProp

算法原理

  • 基本原理:RProp基于梯度的符号来调整参数更新的步长,而不依赖于梯度的大小。如果当前梯度与上一次梯度的符号相同,则增加步长;如果符号相反,则减小步长。这种方法可以在一定程度上避免梯度消失或爆炸问题,提高训练的稳定性和收敛速度。
  • 参数更新数学公式
    Δ θ t = { − η + Δ θ t − 1 , g t g t − 1 > 0 − η − Δ θ t − 1 , g t g t − 1 < 0 Δ θ t − 1 , g t g t − 1 = 0 \Delta\theta_t=\begin{cases}-\eta^+\Delta\theta_{t - 1},&g_tg_{t - 1}>0\\-\eta^-\Delta\theta_{t - 1},&g_tg_{t - 1}<0\\\Delta\theta_{t - 1},&g_tg_{t - 1}=0\end{cases} Δθt= η+Δθt1,ηΔθt1,Δθt1,gtgt1>0gtgt1<0gtgt1=0
    θ t + 1 = θ t + Δ θ t \theta_{t + 1}=\theta_t+\Delta\theta_t θt+1=θt+Δθt
    其中, η + \eta^+ η+ η − \eta^- η分别是步长增加和减小的因子, g t g_t gt是第 t t t步的梯度, Δ θ t \Delta\theta_t Δθt是参数更新量。

代码实现

python">import numpy as npclass RProp:def __init__(self, lr_plus=1.2, lr_minus=0.5, delta_max=50, delta_min=1e-6, initial_delta=0.1):self.lr_plus = lr_plusself.lr_minus = lr_minusself.delta_max = delta_maxself.delta_min = delta_minself.initial_delta = initial_deltaself.delta = Noneself.sign_grad_prev = Nonedef update(self, w, grad_w):if self.delta is None:self.delta = np.ones_like(grad_w) * self.initial_deltaself.sign_grad_prev = np.sign(grad_w)sign_grad = np.sign(grad_w)self.delta *= (sign_grad == self.sign_grad_prev) * self.lr_plus + (sign_grad!= self.sign_grad_prev) * self.lr_minusself.delta = np.minimum(self.delta_max, np.maximum(self.delta_min, self.delta))self.sign_grad_prev = sign_graddx = -self.delta * sign_gradreturn w + dx

可视效果

在这里插入图片描述
在这里插入图片描述

🚀 代码结构

github项目链接

preject|--optim|--result|--main.py
python">import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3Dfrom optim import Adadelta, Adagrad, Adam, Adamax, AdamW, NAdam, RMSProp, RProp, SGD, SparseAdam# 定义二维损失函数
def loss_function(x, y):return 3 * x ** 2 + 4 * y ** 2# 计算损失函数关于x和y的偏导数(针对单个样本的情况)
def gradient(x, y):grad_x = 6 * xgrad_y = 8 * yreturn np.array([grad_x, grad_y])def train(optimizer_name, num_iterations=500):# 初始参数params = np.array([4.5, 4.5])x, y = params[0], params[1]# 创建优化器实例if optimizer_name == "Adadelta":optimizer = Adadelta()elif optimizer_name == "Adagrad":optimizer = Adagrad()elif optimizer_name == "Adam":optimizer = Adam()elif optimizer_name == "Adamax":optimizer = Adamax()elif optimizer_name == "AdamW":optimizer = AdamW()elif optimizer_name == "NAdam":optimizer = NAdam()elif optimizer_name == "RMSProp":optimizer = RMSProp()elif optimizer_name == "RProp":optimizer = RProp()elif optimizer_name == "SGD":optimizer = SGD()elif optimizer_name == "SparseAdam":optimizer = SparseAdam()else:raise Exception("Not Support This Optimizer!")# 用于存储每次迭代的x、y和损失值,方便可视化x_history = []y_history = []loss_history = []for _ in range(num_iterations):grads = gradient(x, y)params = np.array([x, y])updated_params = optimizer.update(params, grads)x, y = updated_params[0], updated_params[1]loss = loss_function(x, y)x_history.append(x)y_history.append(y)loss_history.append(loss)# 创建3D图形对象fig = plt.figure()ax = fig.add_subplot(111, projection='3d')# 生成用于绘制损失函数曲面的网格数据x_range = np.linspace(-5, 5, 100)y_range = np.linspace(-5, 5, 100)X, Y = np.meshgrid(x_range, y_range)Z = loss_function(X, Y)# 绘制损失函数曲面ax.plot_surface(X, Y, Z, alpha=0.5, cmap='viridis')# 绘制参数x、y变化以及对应损失函数值的散点图ax.plot(x_history, y_history, loss_history, c='r', marker='.', label=f'{optimizer_name} Optimization Path')# 设置坐标轴标签ax.set_xlabel('x')ax.set_ylabel('y')ax.set_zlabel('Loss')# 设置图形标题ax.set_title(f'Parameter and Loss Change with {optimizer_name}')# 添加图例ax.legend()# 显示图形plt.savefig(f'result\\{optimizer_name}.png')plt.close()# 可视化损失下降过程plt.plot(loss_history)plt.xlabel('Iteration')plt.ylabel('Loss')plt.title(f'Loss Decrease with {optimizer_name}')# 显示图形plt.savefig(f'result\\{optimizer_name}_loss.png')plt.close()if __name__ == "__main__":names = ["Adadelta", "Adagrad", "Adam", "Adamax", "AdamW", "NAdam", "RMSProp", "RProp", "SGD", "SparseAdam"]for name in names:train(optimizer_name=name)

http://www.ppmy.cn/ops/142800.html

相关文章

GeoWave实现简单的时空范围查询(HBase数据库)

前言 上一篇文章中利用GeoWave导入矢量数据到HBase/Accumulo数据库-CSDN博客&#xff0c;我介绍了如何利用GeoWave导入数据到HBase/Accumulo数据库中&#xff0c;本文&#xff0c;我将介绍如何使用GeoWave实现简单的时空范围查询。 代码 HBaseRequiredOptions hBaseRequiredO…

HiveQL命令(一)- 数据库操作

文章目录 前言一、数据库操作1. 创建数据库1.1 语法及解释1.2 创建数据库示例 2. 查看数据库2.1 查看所有数据库2.2 查看数据库信息2.2.1 语法及解释2.2.2 查看数据库信息示例 3. 切换数据库3.1 语法3.2 示例 4. 修改数据库4.1 语法4.2 示例 5. 删除数据库5.1 语法及解释5.2 示…

网络安全与信息安全的区别

在平常中&#xff0c;很多同学和刚入门的红客们总是将网安和信安搞混淆&#xff0c;网络安全和信息安全是两个相关但不同的概念。在现代社会中&#xff0c;随着信息化程度的不断提升&#xff0c;二者的界限逐渐模糊&#xff0c;但它们依然有明确的区分。 1. 网络安全&#xff…

Ubuntu 18.04无有线图表且无法设置有线网络

问题背景&#xff1a; 今天在登陆自己的虚拟机Ubuntu系统的时候突然出现 有线连接无法连接的问题&#xff0c;有线连接的图标变为没有了&#xff0c;无法点击网络菜单的Setting模块选项。我的虚拟机有线网络连接方式是NAT方式。 没有如下有线连接图标 解决方法&#xff1a; …

Linux(网络协议和管理)

后面也会持续更新&#xff0c;学到新东西会在其中补充。 建议按顺序食用&#xff0c;欢迎批评或者交流&#xff01; 缺什么东西欢迎评论&#xff01;我都会及时修改的&#xff01; 在这里真的很感谢这位老师的教学视频让迷茫的我找到了很好的学习视频 王晓春老师的个人空间…

Elasticsearch 集群部署

Elasticsearch 是一个分布式的搜索和分析引擎&#xff0c;广泛应用于日志分析、全文搜索、实时数据分析等场景。它以其高性能、高可用性和易用性而著称。本文档将引导您完成一个基本的 Elasticsearch 集群配置&#xff0c;包括节点间的通信、客户端访问、安全设置等关键步骤。我…

#. 判断元素是否存在传统题1000ms256MiB

题目描述 有一个集合M是这样生成的&#xff1a; (1) 已知k是集合M的元素&#xff1b;(2) 如果y是M的元素&#xff0c;那么&#xff0c;2y1和3y1都是M的元素&#xff1b;(3) 除了上述二种情况外&#xff0c;没有别的数能够成为M的一个元素。 问题&#xff1a;任意给定kk和xx&…

【OJ题解】面试题三步问题

个人主页: 起名字真南的CSDN博客 个人专栏: 【数据结构初阶】 &#x1f4d8; 基础数据结构【C语言】 &#x1f4bb; C语言编程技巧【C】 &#x1f680; 进阶C【OJ题解】 &#x1f4dd; 题解精讲 目录 **题目链接****解题思路****1. 问题分析****2. 递归思路****3. 优化方案&a…