深入浅出梯度下降与反向传播

文章目录

  • 1. 前言
  • 2. 基本概念
    • 2.1 一元函数的导数
    • 2.2 偏导数
    • 2.3 方向导数
    • 2.4 梯度
    • 2.5 均方误差
  • 3. 梯度下降
    • 3.1 梯度下降的公式
    • 3.2 梯度下降的类型(优化器)
  • 4. 反向传播
    • 4.1 反向传播的基本步骤
    • 4.2 反向传播的数学推导
  • 5. 实战
    • 5.1 手动求导
    • 5.2 自动求导
    • 5.3 过程可视化

1. 前言

  在深度学习中,梯度下降和反向传播是两个至关重要的概念。它们共同作用于优化神经网络,使其能够从数据中学习到有用的模式。尽管它们是深度学习的核心,但很多人对这两个概念仍然感到困惑。本博客将深入讲解梯度下降和反向传播的基本原理,并通过一个简单的示例来加以说明。

2. 基本概念

2.1 一元函数的导数

  如果有一个函数 f ( x ) f(x) f(x),它的导数 f ′ ( x ) f^′(x) f(x) 给出了函数在点 x 0 x_0 x0 处沿着 x x x 轴的变化速率,即:
f ′ ( x 0 ) = lim ⁡ Δ x → 0 f ( x 0 + Δ x ) − f ( x 0 ) Δ x f ^\prime (x_0) = \lim_{\Delta x \to 0} \frac {f(x_0 + \Delta x) - f(x_0)} {{\Delta x}} f(x0)=Δx0limΔxf(x0+Δx)f(x0)  这个导数告诉我们,沿着 x x x轴方向,函数的变化快慢情况。

2.2 偏导数

  对于多变量函数 f ( x 1 , x 2 , … , x n ) f(x_1, x_2, \dots, x_n) f(x1,x2,,xn),偏导数描述了函数在某一维度(即某个变量)上变化的速率。例如,函数 f ( x , y ) = x 2 + y 2 f(x, y) = x^2 + y^2 f(x,y)=x2+y2 的偏导数为:
∂ f ∂ x = 2 x , ∂ f ∂ y = 2 y \frac{\partial f}{\partial x} = 2x, \quad \frac{\partial f}{\partial y} = 2y xf=2x,yf=2y  这些偏导数分别表示函数在 x x x轴方向和 y y y轴方向的变化速率。

2.3 方向导数

  描述了一个多变量函数在某一点沿任意给定方向的变化率。对于一个函数 f ( x 1 , x 2 , … , x n ) f(x_1, x_2, \dots, x_n) f(x1,x2,,xn),在点 x 0 \mathbf{x_0} x0 处沿着单位向量 v \mathbf{v} v 方向的方向导数表示为:
D v f ( x 0 ) = ∇ f ( x 0 ) ⋅ v D_{\mathbf{v}} f(\mathbf{x_0}) = \nabla f(\mathbf{x_0}) \cdot \mathbf{v} Dvf(x0)=f(x0)v其中, ∇ f ( x 0 ) \nabla f(\mathbf{x_0}) f(x0) 是函数在点 x 0 \mathbf{x_0} x0 的梯度。
  方向导数的几何意义:方向导数给出了函数在某一点沿某个方向的变化速率。它可以看作是沿着某个方向的切线变化率,而不仅仅是沿坐标轴的变化率。
  即在某一点 x 0 \mathbf{x_0} x0,如果我们沿着某个方向 v \mathbf{v} v 走,方向导数告诉我们,沿着这个方向走时,函数值变化的快慢。如果方向导数为正,说明函数值在增加;如果为负,说明函数值在减少;如果为零,说明函数值在这个方向上没有变化。

2.4 梯度

  在一个多变量的标量函数 f ( x 1 , x 2 , … , x n ) f(x_1, x_2, \dots, x_n) f(x1,x2,,xn) 中,梯度是一个向量,表示函数在某一点的最速上升方向。梯度不仅告诉我们函数的变化率,还告诉我们该变化率最大的方向。具体来说,梯度是函数的所有偏导数组成的向量:
∇ f ( x 1 , x 2 , … , x n ) = ( ∂ f ∂ x 1 , ∂ f ∂ x 2 , … , ∂ f ∂ x n ) \nabla f(x_1, x_2, \dots, x_n) = \left( \frac{\partial f}{\partial x_1}, \frac{\partial f}{\partial x_2}, \dots, \frac{\partial f}{\partial x_n} \right) f(x1,x2,,xn)=(x1f,x2f,,xnf)  梯度的方向:梯度的方向指向函数值增加最快的方向。
  梯度的大小:梯度的模长(即向量的长度)表示沿着这个方向,函数变化的速率。

  可以把梯度看作是一个“指示器”,它告诉我们在某一点,函数增长最快的方向。换句话说,梯度指向了“上坡”的方向。

2.5 均方误差

  均方误差(Mean Squared Error, MSE),是一种常用的衡量模型预测值与实际值之间差异的指标,尤其是回归任务中,MSE的计算公式如下:
M S E = 1 n ∑ i = 1 n ( y i − y ^ i ) 2 MSE = \frac {1} {n} \sum _{i=1} ^ n (y_i - \hat y_i) ^ 2 MSE=n1i=1n(yiy^i)2其中, n n n是样本数量, y i y_i yi是第 i i i个样本的真实值, y ^ i \hat y_i y^i是模型对第 i i i个样本的预测值。

  均方误差也叫做最小二乘法。

3. 梯度下降

  梯度下降(Gradient Descent, GD)是一种优化算法,用于最小化(或最大化)一个函数,通常用来训练机器学习模型。在神经网络中,我们的目标是通过调整模型的参数(例如权重和偏置)来最小化损失函数。损失函数衡量了模型的预测与实际标签之间的差异,目标是让这个损失函数的值尽可能小。
  梯度下降的核心思想是,沿着损失函数的梯度(偏导数)下降,不断更新参数,直到达到最小值。

3.1 梯度下降的公式

  梯度下降的更新规则如下:
θ = θ − η ⋅ ∇ θ L ( θ ) \theta = \theta - \eta \cdot \nabla_\theta L(\theta) θ=θηθL(θ)其中:
   θ \theta θ 是模型的参数(例如权重和偏置)。
   η \eta η 是学习率(learning rate),控制每次更新的步长。
   ∇ θ L ( θ ) \nabla_\theta L(\theta) θL(θ) 是损失函数 L L L 关于参数 θ \theta θ 的梯度。
  梯度 ∇ θ L ( θ ) \nabla_\theta L(\theta) θL(θ) 告诉我们,沿着哪个方向更新参数能使损失函数下降得更快。

3.2 梯度下降的类型(优化器)

  1. 批量梯度下降(Batch Gradient Descent):每次使用整个数据集来计算梯度和更新参数。虽然准确性高,但计算开销大,尤其是在数据量很大的时候。
  2. 随机梯度下降(Stochastic Gradient Descent, SGD):每次只用一个样本来计算梯度和更新参数。虽然更新速度快,但可能会导致参数更新不稳定。
  3. 小批量梯度下降(Mini-Batch Gradient Descent):每次使用数据集中的一个小批量样本来计算梯度和更新参数。这种方法结合了批量和随机梯度下降的优点。
  当然,还有很多类型的优化,比如AdamRMSpropAdaW等,这里不再细述。

4. 反向传播

  反向传播(Back Propagation, BP)是用于计算神经网络中每一层的梯度的算法。它是梯度下降的一部分,特别用于计算和传播每个参数对损失函数的贡献。
  反向传播算法依赖于链式法则(Chain Rule),通过链式法则可以将损失函数对模型参数的梯度逐层传播回去,从而更新每一层的参数。

  即从输出层一步步传播到输入层。

4.1 反向传播的基本步骤

假设我们有一个包含多个层的神经网络,每一层都有权重 W W W 和偏置 b b b。反向传播的步骤如下:
  1. 前向传播:从输入层开始,将输入数据传递到输出层,并计算出预测值。
  2. 计算损失:根据模型的输出与真实标签计算损失函数。
  3. 反向传播:
    (1)计算输出层的梯度,即损失函数关于输出的偏导数。
    (2)逐层计算隐藏层的梯度,即损失函数关于每一层的输入、权重和偏置的偏导数。
  4. 更新权重和偏置:根据梯度下降规则更新每一层的权重和偏置。

4.2 反向传播的数学推导

  假设神经网络有两层,每层的输出分别为 a 1 a_1 a1 a 2 a_2 a2,损失函数为 L L L。反向传播的目标是计算 ∂ L ∂ W 1 \frac{\partial L}{\partial W_1} W1L ∂ L ∂ W 2 \frac{\partial L}{\partial W_2} W2L,即每一层权重的梯度。
  1. 输出层梯度计算:
∂ L ∂ a 2 = ∂ L ∂ y ⋅ ∂ y ∂ a 2 \frac{\partial L}{\partial a_2} = \frac{\partial L}{\partial y} \cdot \frac{\partial y}{\partial a_2} a2L=yLa2y其中 y y y是输出层的预测值。
  2. 隐藏层梯度计算:
∂ L ∂ a 1 = ∂ L ∂ a 2 ⋅ ∂ a 2 ∂ a 1 \frac{\partial L}{\partial a_1} = \frac{\partial L}{\partial a_2} \cdot \frac{\partial a_2}{\partial a_1} a1L=a2La1a2然后,我们使用链式法则计算每一层的权重梯度。
  3. 参数更新:根据计算出来的梯度使用梯度下降更新权重和偏置。

5. 实战

5.1 手动求导

  我们来构建一个简单的神经网络,做一个线性回归:

在这里插入图片描述

  模型的输入为2维数据,输出为1维数据,该模型的函数表达式可以表示为:
y ∗ = w 5 ⋅ ( w 1 ⋅ x 1 + w 3 ⋅ x 2 ) + w 6 ⋅ ( w 2 ⋅ x 1 + w 4 ⋅ x 2 ) y^* = w_5 \cdot (w_1 \cdot x_1 + w_3 \cdot x_2) + w_6 \cdot (w_2 \cdot x_1 + w_4 \cdot x_2) y=w5(w1x1+w3x2)+w6(w2x1+w4x2)  我们使用MSE来作为损失函数,来优化我们的网络,即
L o s s = 1 n ∑ i = 1 n ( y i − y i ∗ ) 2 Loss = \frac {1} {n} \sum _{i=1} ^ n (y_i - y^*_i) ^ 2 Loss=n1i=1n(yiyi)2
  假设初始时模型的权重为:
w 1 = 1.0 , w 2 = 0.5 , w 3 = 0.5 , w 4 = 0.7 w_1=1.0,w_2=0.5,w_3=0.5,w_4=0.7 w1=1.0w2=0.5w3=0.5w4=0.7 w 5 = 1.0 , w 6 = 2.0 w_5=1.0,w_6=2.0 w5=1.0w6=2.0  已知一个样本数据:
x 1 = 0.5 , x 2 = 1.0 , y = 0.8 x_1=0.5,x_2=1.0,y=0.8 x1=0.5x2=1.0y=0.8  按照上述公式,计算一次前向传播,得到 y ∗ = 2.9 y^*=2.9 y=2.9,与真实值 y y y 的偏差可以通过 l o s s loss loss 计算得到, l o s s = ( y − y ∗ ) 2 = 4.41 loss = (y - y^*) ^ 2 = 4.41 loss=(yy)2=4.41。然后我们通过梯度下降的方式来更新 w 5 w_5 w5,需要先计算出在点 ( x 1 , x 2 ) (x_1,x_2) (x1,x2)的梯度:
∇ = ∂ L ∂ w 1 = ∂ L ∂ y ∗ ⋅ ∂ y ∗ ∂ w 5 \nabla = \frac {\partial L} {\partial w_1} = \frac {\partial L} {\partial y^*} \cdot \frac {\partial y^*} {\partial w_5} =w1L=yLw5y ∂ L ∂ y ∗ = − 2 ( y − y ∗ ) = 4.2 \frac {\partial L} {\partial y^*} = -2 (y- y^*) = 4.2 yL=2(yy)=4.2 ∂ y ∗ ∂ w 5 = w 1 ⋅ x 1 + w 3 ⋅ x 2 = 1.0 \frac {\partial y^*} {\partial w_5} = w_1 \cdot x_1 + w_3 \cdot x_2 = 1.0 w5y=w1x1+w3x2=1.0
  所以梯度为:
∂ L ∂ w 1 = 4.2 \frac {\partial L} {\partial w_1} = 4.2 w1L=4.2  假设,学习率为 0.01 0.01 0.01,根据梯度下降算法 θ = θ − η ⋅ ∇ θ L ( θ ) \theta = \theta - \eta \cdot \nabla_{\theta} L(\theta) θ=θηθL(θ) 更新 w 5 w5 w5:
w 5 = w 5 − η ∂ L ∂ w 5 = 0.958 w_5 = w_5 - \eta \frac {\partial L} {\partial w_5} = 0.958 w5=w5ηw5L=0.958  同理,可以更新 w 1 w_1 w1
∂ y ∗ ∂ w 1 = w 5 x 1 = 0.5 \frac {\partial y^*} {\partial w_1} = w_5x_1 = 0.5 w1y=w5x1=0.5 ∂ L ∂ w 1 = ∂ L ∂ y ∗ ⋅ ∂ y ∗ ∂ w 1 = 2.1 \frac {\partial L} {\partial w_1} = \frac {\partial L} {\partial y^*} \cdot \frac {\partial y^*} {\partial w_1} = 2.1 w1L=yLw1y=2.1 w 1 = w 1 − η ∂ L ∂ w 1 = 0.979 w_1 = w_1 - \eta \frac {\partial L} {\partial w_1} = 0.979 w1=w1ηw1L=0.979

5.2 自动求导

  将上面模型的表达式形式化,即
y ∗ = ( x T ⋅ W h ) ⋅ W o y* = (x^T \cdot W_h) \cdot W_o y=(xTWh)Wo其中,
x = [ x 1 x 2 ] , W h = [ w 1 w 2 w 3 w 4 ] , W o = [ w 5 w 6 ] x = \begin{bmatrix} x_1 \\ x_2\end{bmatrix},W_h = \begin{bmatrix} w_{1} & w_{2} \\ w_{3} & w_{4} \end{bmatrix},W_o = \begin{bmatrix} w_{5} & w_{6} \end{bmatrix} x=[x1x2]Wh=[w1w3w2w4]Wo=[w5w6]  这样,我们就可以使用pytorch来构建上述神经网络了,具体如下:

# -*- coding: utf-8 -*-
# Author  : liyanpeng
# Email   : yanpeng.li@cumt.edu.cn
# Datetime: 2024/11/29 17:38
# Filename: chain_rule.py
import torch
import torch.nn as nn
import torch.optim as optimdef func_y():x1 = torch.tensor(0.5, dtype=torch.float32)x2 = torch.tensor(1.0, dtype=torch.float32)w1 = torch.tensor(1.0, dtype=torch.float32)w2 = torch.tensor(0.5, dtype=torch.float32)w3 = torch.tensor(0.5, dtype=torch.float32)w4 = torch.tensor(0.7, dtype=torch.float32)w5 = torch.tensor(1.0, dtype=torch.float32)w6 = torch.tensor(2.0, dtype=torch.float32)y = w5 * (w1 * x1 + w2 * x2) + w6 * (w3 * x1 + w4 * x2)print(y)class SimpleNeuralNetwork(nn.Module):def __init__(self):super().__init__()self.linear1 = nn.Linear(in_features=2, out_features=2, bias=False)self.linear2 = nn.Linear(in_features=2, out_features=1, bias=False)self.linear1.weight.data = torch.tensor([[1.0, 0.5], [0.5, 0.7]], dtype=torch.float32)self.linear2.weight.data = torch.tensor([[1.0, 2.0]], dtype=torch.float32)def forward(self, x):x = self.linear1(x)y = self.linear2(x)return ydef grad_hook(grad):print('grad:', grad[0][0])if __name__ == '__main__':x = torch.tensor([0.5, 1.0], dtype=torch.float32)y = torch.tensor(0.8, dtype=torch.float32)model = SimpleNeuralNetwork()criterion = nn.MSELoss()optimizer = optim.SGD(model.parameters(), lr=0.01)hook_list = []for name, param in model.named_parameters():if param.requires_grad:hook = param.register_hook(grad_hook)hook_list.append(hook)y_pred = model(x)loss = criterion(y_pred, y)optimizer.zero_grad()   # 清空梯度loss.backward()         # 反向传播optimizer.step()        # 更新权重for hook in hook_list:hook.remove()print('更新后的w1:', model.linear1.weight.data[0, 0])print('更新后的w5:', model.linear2.weight.data[0, 0])

  打印结果如下,与手动计算的结果一致:

grad: tensor(4.2000)
grad: tensor(2.1000)
更新后的w1: tensor(0.9790)
更新后的w5: tensor(0.9580)

5.3 过程可视化

  再加入一些可视化代码,看一下权重更新的轨迹:

# -*- coding: utf-8 -*-
# Author  : liyanpeng
# Email   : yanpeng.li@cumt.edu.cn
# Datetime: 2024/11/29 17:38
# Filename: chain_rule.py
import torch
import torch.nn as nn
import torch.optim as optim
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as npif __name__ == '__main__':x = torch.tensor([0.5, 1.0], dtype=torch.float32)y = torch.tensor(0.8, dtype=torch.float32)model = SimpleNeuralNetwork()criterion = nn.MSELoss()optimizer = optim.SGD(model.parameters(), lr=0.01)loss_list = []w1_list = []w2_list = []for epoch in range(5):y_pred = model(x)loss = criterion(y_pred, y)optimizer.zero_grad()   # 清空梯度loss.backward()         # 反向传播optimizer.step()        # 更新权重loss_list.append(loss.item())w1_list.append(model.linear1.weight.data[0, 0].item())w2_list.append(model.linear2.weight.data[0, 0].item())fig = plt.figure(figsize=(8, 6))# 3D曲面图和等高线图ax1 = fig.add_subplot(111, projection='3d')ax1.set_title("3D Loss Surface with Contours and Trajectory")# 将损失值、权重映射到X, Y, Z轴ax1.plot_trisurf(w1_list, w2_list, loss_list, cmap='viridis', alpha=0.7)# 生成网格数据,用于绘制等高线图w1_range = np.linspace(min(w1_list), max(w1_list), 100)w2_range = np.linspace(min(w2_list), max(w2_list), 100)W1, W2 = np.meshgrid(w1_range, w2_range)np.random.seed(42)x_train = np.random.rand(100, 2)noise = np.random.randn(100, 1)# f(x, y) = 2x^2 + y^2 - 0.7 + noisey_train = 2 * x_train[:, 0] * x_train[:, 0] + x_train[:, 1] * x_train[:, 1] - 0.7 + noise# 计算每个网格点的损失值loss_grid = np.zeros(W1.shape)for i in range(W1.shape[0]):for j in range(W1.shape[1]):model.linear1.weight.data[0, 0] = W1[i, j]model.linear2.weight.data[0, 0] = W2[i, j]y_pred = model(torch.tensor(x_train, dtype=torch.float32))loss_grid[i, j] = criterion(y_pred, torch.tensor(y_train, dtype=torch.float32)).item()# 绘制等高线图ax1.contour(W1, W2, loss_grid, levels=20, cmap='viridis', offset=min(loss_list))# 绘制权重更新轨迹ax1.plot(w1_list, w2_list, loss_list, 'k-', marker='o', markersize=5, label="Weight Update Trajectory")ax1.plot(w1_list, w2_list, [min(loss_list)] * len(w1_list), 'r-', marker='o', markersize=5, label="Trajectory on Contours")# 在等高线图上标记权重更新的坐标for i in range(len(w1_list)):ax1.text(w1_list[i], w2_list[i], min(loss_list),f'({w1_list[i]:.4f}, {w2_list[i]:.4f})',color='red', fontsize=8, ha='center', va='center')ax1.set_xlabel('Linear1 Weight (First Element)')ax1.set_ylabel('Linear2 Weight (First Element)')ax1.set_zlabel('Loss')ax1.legend()plt.tight_layout()plt.show()

  绘制的效果图如下:

在这里插入图片描述
  损失函数从右侧至左侧逐渐收敛,最右侧的点是我们第一次更新时 w 1 w_1 w1 w 2 w_2 w2的权重。

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

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

相关文章

gitlab-runner的卸载与安装

如果你使用rpm方式安装gitlab-runner,则可以参考本教程。 卸载 停止和卸载gitlab-runner 停止 gitlab-runner stopchkconfig gitlab-runner off卸载 gitlab-runner uninstall删除rpm包 查询出rpm包名,根据包名删除rpm。 [rootEuler02 ~]# rpm -qa …

2024年12月31日Github流行趋势

项目名称:free-programming-books 项目地址url:https://github.com/EbookFoundation/free-programming-books项目语言:HTML历史star数:344575今日star数:432项目维护者:vhf, eshellman, davorpa, MHM5000, …

基于深度学习的视觉检测小项目(二) 环境和框架搭建

一、环境和框架要求 SAM的环境要求: Python>3.7 PyTorch>1.7 torchvision>0.8 YOLO V8的环境要求:YOLO集成在ultralytics库中,ultralytics库的环境要求: Python>3.7 PyTorch>1.10.0 1、确定pytorch版本…

深度学习——损失函数汇总

1. 连续值损失函数 总结:主要使用胡贝儿损失函数,应用于连续数值的预测之间的误差损失,参考地址 import torch import torch.nn as nna = torch.tensor([[1, 2], [3, 4]], dtype=torch.float) b = torch.tensor([[3, 5], [8, 6]], dtype=torch.float)loss_fn1 = torch.nn.M…

【分布式数据库与数据存储方案】详解

分布式数据库与数据存储方案 一、分布式数据库概述 (一)概念 分布式数据库是一种将数据分散存储在多个物理节点上的数据库系统,这些节点通过网络进行连接和通信,对外呈现出一个统一的逻辑数据库,用户或应用程序可以像…

TB1801D 线性驱动 LED 恒流芯片

1、产品概述 TB1801D是一款专为12V灯珠设计的汽车灯专用的低压差恒流芯片,输出电流恒流精度≤3%,外围结构简单。TB1801D 内置 130℃过温保护电路,可在各种散热条件下将 LED 灯珠温度控制在 140℃以内。TB1801D 内置 100V 的功率 M…

HTML——38.Span标签和字符实体

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>span标签和字符实体</title><style type"text/css">h1{text-align: center;}p{text-indent: 2em;}span{color: red;}</style></head><…

纯血鸿蒙ArkUI线性布局详解

线性布局说明 线性布局&#xff08;LinearLayout&#xff09;是开发中最常用的布局&#xff0c;通过线性容器Row和Column构建。线性布局是其他布局的基础&#xff0c;其子元素在线性方向上&#xff08;水平方向和垂直方向&#xff09;依次排列。线性布局的排列方向由所选容器组…

Debian-linux运维-docker安装和配置

腾讯云搭建docker官方文档&#xff1a;https://cloud.tencent.com/document/product/213/46000 阿里云安装Docker官方文档&#xff1a;https://help.aliyun.com/zh/ecs/use-cases/install-and-use-docker-on-a-linux-ecs-instance 天翼云常见docker源配置指导&#xff1a;htt…

【网络安全实验室】脚本关实战详情

难道向上攀爬的那条路&#xff0c;不是比站在顶峰更让人热血澎湃吗 1.key又又找不到了 点击链接&#xff0c;burp抓包&#xff0c;发送到重放模块&#xff0c;点击go 得到key 2.快速口算 python3脚本 得到key 3.这个题目是空的 试了一圈最后发现是 4.怎么就是不弹出key呢…

极品飞车6的游戏手柄设置

极品飞车&#xff0c;既可以用键盘来控制车辆的前进、后退、左转、右转、加速与减速&#xff0c;也可以使用游戏手柄来操作车辆的运行。需要注意的是&#xff0c;极品飞车虽然支持手柄&#xff0c;但是仅支持常见的北通、罗技还有部分Xbox系列的手柄&#xff0c;至于其他的PS4手…

安科瑞防孤岛保护装置助力光储充系统安全运行

安科瑞 吕梦怡 ​1.孤岛效应是指在电网供电系统中出现的一种异常情况。 当公共电网因故障停电或者其他原因断电时&#xff0c;原本接入电网的分布式发电系统&#xff08;如太阳能电站、风力发电场&#xff09;如果没有及时与电网断开&#xff0c;就会继续向其周围的一部分用电…

联通 路由器 创维SK-WR9551X 联通华盛VS010 组mesh 和 锐捷X32 PRO 无缝漫游

前言 联通路由器&#xff1a;联通创维SK-WR9551X&#xff0c;联通华盛VS010组mesh&#xff0c;并与锐捷X32 PRO混合组网&#xff0c;开启无限漫游。 1、mesh ≠ 无缝漫游 mesh是实现路由器快速组网的一种方式&#xff0c;通过mesh组网后可以实现无缝漫游。 mesh组网的设备要…

Druid连接Oracle数据库,连接失效导致SQL无法执行

原始配置&#xff1a; type: com.alibaba.druid.pool.DruidDataSource druid:initial-size: 5max-active: 25min-idle: 5max-wait: 10000testWhileIdle: truetestOnBorrow: falsetestOnReturn: falsetimeBetweenEvictionRunsMillis: 2000minEvictableIdleTimeMillis: 600000ma…

JVM调优(内存、GC、JVM参数)

内存调优 常用监控工具 Top命令 top命令是linux下用来查看系统信息的一个命令&#xff0c;它提供给我们去实时地去查看系统的资源&#xff0c;比如执行时的进程、线程和系统参数等信息。进程使用的内存为RES&#xff08;常驻内存&#xff09;- SHR&#xff08;共享内存&…

Cursor登录按钮点击没反应

问题 系统&#xff1a;Windows11 Cursor&#xff1a;Cursor 0.44.9 当安装Cursor打开进行登录时&#xff0c;点击Sign in没反应 解决方案 1.打开window11的设置 2.点击应用中的默认应用 3.在设置应用程序的默认值中搜索Google&#xff08;没有Google浏览器的尝试下载一个&a…

强化学习(1)

Reinforcement Learning Goal-directed learing from ineraction with the environment. 1. Basic Element 基本元素 1.1 Agent 玩家 1.2 Environment 1.3 Goal 2. Main Element 主要元素 2.1 State 2.2 Action 状态与行为往复 2.3 Reward 目标&#xff1a;最大化总…

异步请求在TypeScript网络爬虫中的应用

异步请求的重要性 异步请求是现代网络应用中不可或缺的一部分&#xff0c;特别是在网络爬虫领域。它允许爬虫在等待网络响应的同时继续执行其他任务&#xff0c;从而提高效率和性能。在JavaScript和TypeScript中&#xff0c;异步请求可以通过多种方式实现&#xff0c;包括回调…

OpenLinkSaas使用手册-项目外部资源管理

在软件项目开发过程中&#xff0c;会依赖很多外部系统&#xff0c;比如服务器&#xff0c;代码仓库&#xff0c;CI/CD&#xff0c;构件仓库等等。 OpenLinkSaas可以在右侧工具栏中的服务列表中&#xff0c;添加这些外部资源。 进入外部服务列表 代码仓库 一个软件项目可能会…

自建私有云相册:Docker一键部署Immich,照片视频备份利器

自建私有云相册&#xff1a;Docker一键部署Immich&#xff0c;照片视频备份利器 前言 随着人们手机、PC、平板等电子产品多样&#xff0c;我们拍摄和保存的照片和视频数量也在不断增加。如何高效地管理和备份这些珍贵的记忆成为了一个重要的问题。 传统的云备份虽然方便&…