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

【PyTorch】动态调整学习率 torch.optim.lr_scheduler.StepLR 调度器

文章目录

  • 1. torch.optim.lr_scheduler.StepLR 官方文档详解
  • 2. 使用示例
    • 2.1 官方提供使用示例
    • 2.2 自己写代码测试方法
      • 2.2.1 get_last_lr() 方法
      • 2.2.2 state_dict() 方法
      • 2.2.3 load_state_dict() 保存和加载调度器
  • 3. 思考
    • 3.1 为什么需要state_dict()
    • 3.2 get_lr() 与 get_last_lr() 的输出不一致问题

在深度学习中,学习率调度器(Learning Rate Scheduler) 是用来动态调整学习率的工具。它的主要目的是在训练过程中自动调整学习率,以提高训练的效率和效果。之所以称其为“调度器”,是因为它控制着学习率的调整和更新,类似于调度一个过程或者任务,它按照某种策略和规则来“调度”学习率,本文将详细介绍pytorch中动态调整学习率方法之一 torch.optim.lr_scheduler.StepLR

官方文档链接:
https://pytorch.ac.cn/docs/stable/generated/torch.optim.lr_scheduler.StepLR.html#torch.optim.lr_scheduler.StepLR

1. torch.optim.lr_scheduler.StepLR 官方文档详解

官方文档定义:

class torch.optim.lr_scheduler.StepLR(optimizer, step_size, gamma=0.1, last_epoch=-1, verbose='deprecated')

每隔 step_size 个 epochs 将每个参数组的学习率衰减 gamma 倍。
请注意,这种衰减可能与来自此调度程序外部的学习率的其他更改同时发生。当 last_epoch=-1 时,将初始 lr 设置为 lr。

参数:

  • o p t i m i z e r optimizer optimizer (优化器) : 包装的优化器
  • s t e p _ s i z e ( i n t ) step\_size(int) step_size(int) : 学习率衰减周期
  • g a m m a ( f l o a t ) gamma (float) gamma(float) : 学习率衰减的乘法因子, 默认值:0.1
  • l a s t _ e p o c h ( i n t ) last\_epoch (int) last_epoch(int) : 最后一个 epoch 的索引, 默认值:-1 表示从头开始
  • v e r b o s e ( b o o l ∣ s t r ) verbose (bool | str) verbose(boolstr): 如果为 True,则为每次更新打印一条消息到标准输出, 默认值:False。

注意:

  • 自版本 2.2 起不推荐使用: v e r b o s e verbose verbose 已弃用。请使用 g e t _ l a s t _ l r ( ) get\_last\_lr() get_last_lr()访问学习率

其它:

  • g e t _ l a s t _ l r ( ) get\_last\_lr() get_last_lr() : 返回当前调度程序计算的最后一个学习率, 返回类型 L i s t [ f l o a t ] List[float] List[float]
  • g e t _ l r ( ) get\_lr() get_lr() : 计算每个组的学习率
  • l o a d _ s t a t e _ d i c t ( s t a t e _ d i c t ) load\_state\_dict(state\_dict) load_state_dict(state_dict) : 加载调度程序的状态,参数: s t a t e _ d i c t ( d i c t ) state\_dict (dict) state_dict(dict) 调度程序状态,应为 s t a t e _ d i c t ( ) state\_dict() state_dict() 调用返回的对象。
  • p r i n t _ l r ( i s _ v e r b o s e , g r o u p , l r , e p o c h = N o n e ) print\_lr(is\_verbose, group, lr, epoch=None) print_lr(is_verbose,group,lr,epoch=None) : 显示当前学习率。
  • s t a t e _ d i c t ( ) state\_dict() state_dict() : 将调度程序的状态作为 d i c t dict dict 返回,它包含 s e l f . _ _ d i c t _ _ self.\_\_dict\_\_ self.__dict__ 中每个变量的条目,这些变量不是优化器。
  • s t e p ( e p o c h = N o n e ) step(epoch=None) step(epoch=None) : 执行一步操作,即更新一次学习率

注意:

  • 自版本 2.4 起不推荐使用: p r i n t _ l r ( ) print\_lr() print_lr() 已弃用。请使用 g e t _ l a s t _ l r ( ) get\_last\_lr() get_last_lr() 访问学习率。

2. 使用示例

2.1 官方提供使用示例

  • 假设初始 l r = 0.05 lr = 0.05 lr=0.05 s t e p _ s i z e = 30 step\_size=30 step_size=30 g a m m a = 0.1 gamma=0.1 gamma=0.1,即每 30 个 epoch后,将学习率乘以 0.1
  • e p o c h < 30 epoch< 30 epoch<30 时, l r = 0.05 lr = 0.05 lr=0.05 ,即 l r = l r lr=lr lr=lr
  • 30 < = e p o c h < 60 30 <= epoch < 60 30<=epoch<60 l r = 0.005 lr = 0.005 lr=0.005,即 l r n e w = l r o l d ∗ g a m m a = 0.05 ∗ 0.1 = 0.005 lr_{new}=lr_{old}*gamma=0.05*0.1=0.005 lrnew=lroldgamma=0.050.1=0.005
  • 60 < = e p o c h < 90 60 <= epoch < 90 60<=epoch<90 l r = 0.0005 lr = 0.0005 lr=0.0005,即 l r n e w = l r o l d ∗ g a m m a = 0.005 ∗ 0.1 = 0.0005 lr_{new}=lr_{old}*gamma=0.005*0.1=0.0005 lrnew=lroldgamma=0.0050.1=0.0005
# Assuming optimizer uses lr = 0.05 for all groups
# lr = 0.05     if epoch < 30
# lr = 0.005    if 30 <= epoch < 60
# lr = 0.0005   if 60 <= epoch < 90
# ...
scheduler = StepLR(optimizer, step_size=30, gamma=0.1)
for epoch in range(100):train(...)validate(...)scheduler.step()

2.2 自己写代码测试方法

2.2.1 get_last_lr() 方法

  • 用于返回调度器计算的 最后一个学习率。这个学习率是在调度器(scheduler)调整之后的当前学习率
  • 如果优化器中有多个参数组, g e t _ l a s t _ l r ( ) get\_last\_lr() get_last_lr() 返回的是一个列表,每个元素对应一个参数组的学习率
  • 如果优化器中只有一个参数组, g e t _ l a s t _ l r ( ) get\_last\_lr() get_last_lr() 返回一个只有一个元素的列表
import torch
from torch import nn
from torch import optim
net = nn.Linear(3,4)
def train():optimizer = optim.Adam(net.parameters(), lr=0.1)scheduler = optim.lr_scheduler.StepLR(optimizer, step_size = 1, gamma=0.1)for epoch in range(0, 10):print(epoch, scheduler.get_last_lr())optimizer.step()scheduler.step()
if __name__ == "__main__":train()

代码输出:

0 [0.1]
1 [0.010000000000000002]
2 [0.0010000000000000002]
3 [0.00010000000000000003]
4 [1.0000000000000004e-05]
5 [1.0000000000000004e-06]
6 [1.0000000000000005e-07]
7 [1.0000000000000005e-08]
8 [1.0000000000000005e-09]
9 [1.0000000000000006e-10]

2.2.2 state_dict() 方法

  • s t a t e _ d i c t ( ) state\_dict() state_dict() 是一个非常重要的函数,它能够返回一个包含模型或优化器状态的字典(dict)。对于学习率调度器来说, s t a t e _ d i c t ( ) state\_dict() state_dict() 返回调度器的状态,包括它的参数和变量,用于保存和恢复调度器的状态等

代码示例:

import torch
from torch import nn
from torch import optimnet = nn.Linear(3,4)def train():optimizer = optim.Adam(net.parameters(), lr=0.1)scheduler = optim.lr_scheduler.StepLR(optimizer, step_size = 1, gamma=0.1)for epoch in range(10):print(epoch, scheduler.state_dict())optimizer.step()scheduler.step()if __name__ == "__main__":train()

代码输出:

0 {'step_size': 1, 'gamma': 0.1, 'base_lrs': [0.1], 'last_epoch': 0, 'verbose': False, '_step_count': 1, '_get_lr_called_within_step': False, '_last_lr': [0.1]}
1 {'step_size': 1, 'gamma': 0.1, 'base_lrs': [0.1], 'last_epoch': 1, 'verbose': False, '_step_count': 2, '_get_lr_called_within_step': False, '_last_lr': [0.010000000000000002]}   
2 {'step_size': 1, 'gamma': 0.1, 'base_lrs': [0.1], 'last_epoch': 2, 'verbose': False, '_step_count': 3, '_get_lr_called_within_step': False, '_last_lr': [0.0010000000000000002]}  
3 {'step_size': 1, 'gamma': 0.1, 'base_lrs': [0.1], 'last_epoch': 3, 'verbose': False, '_step_count': 4, '_get_lr_called_within_step': False, '_last_lr': [0.00010000000000000003]} 
4 {'step_size': 1, 'gamma': 0.1, 'base_lrs': [0.1], 'last_epoch': 4, 'verbose': False, '_step_count': 5, '_get_lr_called_within_step': False, '_last_lr': [1.0000000000000004e-05]} 
5 {'step_size': 1, 'gamma': 0.1, 'base_lrs': [0.1], 'last_epoch': 5, 'verbose': False, '_step_count': 6, '_get_lr_called_within_step': False, '_last_lr': [1.0000000000000004e-06]} 
6 {'step_size': 1, 'gamma': 0.1, 'base_lrs': [0.1], 'last_epoch': 6, 'verbose': False, '_step_count': 7, '_get_lr_called_within_step': False, '_last_lr': [1.0000000000000005e-07]} 
7 {'step_size': 1, 'gamma': 0.1, 'base_lrs': [0.1], 'last_epoch': 7, 'verbose': False, '_step_count': 8, '_get_lr_called_within_step': False, '_last_lr': [1.0000000000000005e-08]} 
8 {'step_size': 1, 'gamma': 0.1, 'base_lrs': [0.1], 'last_epoch': 8, 'verbose': False, '_step_count': 9, '_get_lr_called_within_step': False, '_last_lr': [1.0000000000000005e-09]} 
9 {'step_size': 1, 'gamma': 0.1, 'base_lrs': [0.1], 'last_epoch': 9, 'verbose': False, '_step_count': 10, '_get_lr_called_within_step': False, '_last_lr': [1.0000000000000006e-10]}

输出详解:

  • step_size: 该值表示每隔多少个 epoch 学习率就会发生变化。在例子中, s t e p _ s i z e = 1 step\_size = 1 step_size=1,意味着每经过 1 个 epoch,学习率都会更新一次
  • gamma: 这是学习率更新的衰减因子。每次调用 s c h e d u l e r . s t e p ( ) scheduler.step() scheduler.step() 时,当前的学习率将会乘以 g a m m a gamma gamma。例子中, g a m m a = 0.1 gamma = 0.1 gamma=0.1,意味着每次更新学习率时,学习率将减少为原来的 10%
  • base_lrs: 这是每个参数组的初始学习率(在调度器调整之前的学习率)。这里的 [ 0.1 ] [0.1] [0.1]表示模型的初始学习率是 0.1。如果有多个参数组,这里会是一个列表,列出每个参数组的初始学习率
  • last_epoch: 这是上一个 epoch 的编号,用来确定学习率更新时的参考点。 l a s t _ e p o c h = 0 last\_epoch = 0 last_epoch=0 表示调度器刚刚初始化,学习率还没有更新过。通常,last_epoch 用来恢复训练时从哪个 epoch 开始更新学习率
  • verbose: 该参数控制调度器是否在学习率更新时打印详细信息。 v e r b o s e = F a l s e verbose = False verbose=False 表示调度器在更新学习率时不会打印信息。如果设置为 T r u e True True,则每次更新学习率时都会打印一条日志。
  • _step_count: 这个内部变量跟踪调度器已经调用了多少次 step()。在例子中, _ s t e p _ c o u n t = 1 \_step\_count = 1 _step_count=1,表示调度器已经调用过一次 s t e p ( ) step() step(),即更新过一次学习率
  • _get_lr_called_within_step: 是一个内部标志,表示是否在 step() 方法内部调用了 get_lr()。通常不需要关注这个值,它帮助调度器管理内部逻辑
  • _last_lr: 这是调度器最近一次计算的学习率。这个列表保存了每个参数组的学习率。在你的例子中, _ l a s t _ l r = [ 0.1 ] \_last\_lr = [0.1] _last_lr=[0.1],表示当前学习率是 0.1。这会在 scheduler.step() 后更新为新的学习率。

2.2.3 load_state_dict() 保存和加载调度器

可以将 state_dict() 保存到文件中,然后在以后恢复。如下是一个保存和加载学习率调度器状态的例子:

保存调度器状态:

# 保存调度器的 state_dict
torch.save(scheduler.state_dict(), 'scheduler_state.pth')

加载调度器状态:

# 加载调度器的 state_dict
scheduler.load_state_dict(torch.load('scheduler_state.pth'))

通过这种方式,可以在训练中断后恢复学习率调度器的状态,并继续进行训练。

保存调度器状态示例:

epoch = 5 时,保存调度器状态:

import torch
from torch import nn
from torch import optim
net = nn.Linear(3,4)
def train():optimizer = optim.Adam(net.parameters(), lr=0.1)scheduler = optim.lr_scheduler.StepLR(optimizer, step_size = 1, gamma=0.1)for epoch in range(10):if epoch == 5:torch.save(scheduler.state_dict(), 'scheduler_state.pth')breakoptimizer.step()scheduler.step()if __name__ == "__main__":train()

加载调度器状态示例:

import torch
from torch import nn
from torch import optimnet = nn.Linear(3,4)def train():optimizer = optim.Adam(net.parameters(), lr=0.1)scheduler = optim.lr_scheduler.StepLR(optimizer, step_size = 1, gamma=0.1)scheduler.load_state_dict(torch.load("scheduler_state.pth"))for epoch in range(3):print(epoch, scheduler.state_dict())optimizer.step()scheduler.step()if __name__ == "__main__":train()

代码输出:

0 {'step_size': 1, 'gamma': 0.1, 'base_lrs': [0.1], 'last_epoch': 5, 'verbose': False, '_step_count': 6, '_get_lr_called_within_step': False, '_last_lr': [1.0000000000000004e-06]}
1 {'step_size': 1, 'gamma': 0.1, 'base_lrs': [0.1], 'last_epoch': 6, 'verbose': False, '_step_count': 7, '_get_lr_called_within_step': False, '_last_lr': [0.010000000000000002]}
2 {'step_size': 1, 'gamma': 0.1, 'base_lrs': [0.1], 'last_epoch': 7, 'verbose': False, '_step_count': 8, '_get_lr_called_within_step': False, '_last_lr': [0.0010000000000000002]}

可以看到:

  • last_epoch 从 5 开始
  • _step_count 从6 开始
  • _last_lr 从 1e-6 开始

说明是从上次终断的状态继续运行

3. 思考

3.1 为什么需要state_dict()

  • 保存和恢复训练: 当你希望在训练中断后恢复训练时,你可以保存模型和调度器的 state_dict(),然后在恢复时加载它们,确保学习率调度器从上次停止的地方继续工作,而不是从头开始。
  • 调试和分析:通过 state_dict() 可以查看学习率的变化,帮助你调试和分析训练过程中调度器的行为。

3.2 get_lr() 与 get_last_lr() 的输出不一致问题

测试代码:

import torch
from torch import nn
from torch import optimnet = nn.Linear(3,4)def train():optimizer = optim.Adam(net.parameters(), lr=0.1)scheduler = optim.lr_scheduler.StepLR(optimizer, step_size = 1, gamma=0.1)for epoch in range(3):print(epoch, scheduler.get_lr())print(epoch, scheduler.get_last_lr())print([group["lr"] for group in optimizer.param_groups])print("==========================================")optimizer.step()scheduler.step()if __name__ == "__main__":train()

代码输出:

0 [0.1]
0 [0.1]
[0.1]
==========================================
1 [0.0010000000000000002]
1 [0.010000000000000002]
[0.010000000000000002]
==========================================
2 [0.00010000000000000003]
2 [0.0010000000000000002]
[0.0010000000000000002]
==========================================

不知道为什么从 epoch > 0 之后,get_lr() 每次都比 get_last_lr() 提前一步更新,但是通过查看 optimizer.param_groups 的学习率与 get_last_lr() 一致。

get_lr()函数源码:

def get_lr(self):if not self._get_lr_called_within_step:warnings.warn("To get the last learning rate computed by the scheduler, ""please use `get_last_lr()`.", UserWarning)if (self.last_epoch == 0) or (self.last_epoch % self.step_size != 0):return [group['lr'] for group in self.optimizer.param_groups]return [group['lr'] * self.gammafor group in self.optimizer.param_groups]

我们可以看到在源码中当:if (self.last_epoch == 0) or (self.last_epoch % self.step_size != 0),返回值为[group['lr'] for group in self.optimizer.param_groups], 否则的话返回值为[group['lr'] * self.gamma for group in self.optimizer.param_groups],因此可以很好的解释上面的现象,但是Pytorch为什么要这样做呢??目前没有找到相关资料,可以评论区留言讨论!

get_last_lr() 函数源码:

def get_last_lr(self):""" Return last computed learning rate by current scheduler."""return self._last_lr

相关文章:

【PyTorch】动态调整学习率 torch.optim.lr_scheduler.StepLR 调度器

文章目录 1. torch.optim.lr_scheduler.StepLR 官方文档详解2. 使用示例2.1 官方提供使用示例2.2 自己写代码测试方法2.2.1 get_last_lr() 方法2.2.2 state_dict() 方法2.2.3 load_state_dict() 保存和加载调度器 3. 思考3.1 为什么需要state_dict()3.2 get_lr() 与 get_last_l…...

完全二叉树的节点个数

给你一棵 完全二叉树 的根节点 root &#xff0c;求出该树的节点个数。 完全二叉树 的定义如下&#xff1a;在完全二叉树中&#xff0c;除了最底层节点可能没填满外&#xff0c;其余每层节点数都达到最大值&#xff0c;并且最下面一层的节点都集中在该层最左边的若干位置。若最…...

在销售管理中,客户跟进时会出现什么问题?如何解决?

客户跟进表是销售工作中重要的一部分&#xff0c;用于记录与客户的每次沟通、执行计划和合作动态。然而&#xff0c;在实际使用中&#xff0c;客户跟进表经常会出现一些问题&#xff0c;导致效率低下甚至客户流失。本文就从常见问题出发&#xff0c;一一提供措施&#xff0c;让…...

【代码随想录|动态规划】

一、动态规划理论基础 |、动态规划包含题目类型 &#xff08;1&#xff09;背包问题 &#xff08;2&#xff09;打家劫舍 &#xff08;3&#xff09;股票问题 &#xff08;4&#xff09;子序列问题 ||、做一道题需要掌握&#xff08;动态规划5步曲&#xff09;&#xff1…...

时间敏感网络与工业通信的融合:光路科技电力专用交换机和TSN工业交换机亮相EP电力展

12月7日&#xff0c;第三十一届中国国际电力设备及技术展览会&#xff08;EP Shanghai 2024&#xff09;暨上海国际储能技术应用展览会在上海新国际博览中心圆满落幕。本届展会以“数字能源赋能新质生产力”为主题&#xff0c;系统地呈现了电力设备行业在技术融合、转型升级及上…...

初识Linux · 系统编程done

目录 前言&#xff1a; 死锁 可重入函数 读写锁 自旋锁 前言&#xff1a; 本文作为Linux系统编程的收尾工作&#xff0c;介绍的是些零碎的概念&#xff0c;比如死锁&#xff0c;可重入函数&#xff0c;自旋锁&#xff0c;读写锁等&#xff0c;其中死锁概念要重要些&#…...

JavaScript函数式编程: 实现不可变数据结构

# JavaScript函数式编程: 实现不可变数据结构 什么是不可变数据结构 在计算机编程中&#xff0c;不可变数据结构指的是数据一旦创建就不可更改或者修改。这意味着我们不能在原始数据上进行增删改操作&#xff0c;而是需要创建一个新的数据结构来代替原始数据进行操作。 为什么要…...

union find算法 c++

1.原理参考 labuladong-fucking-algorithm/算法思维系列/UnionFind算法详解.md at master jiajunhua/labuladong-fucking-algorithm GitHub 2.初级模式 #include <iostream>class UF {public:// 记录连通分量/* 构造函数&#xff0c;n 为图的节点总数 */UF(int n) {…...

路径规划 | 改进的人工势场法APF算法进行路径规划(Matlab)

目录 效果一览基本介绍程序设计参考文献 效果一览 基本介绍 改进的人工势场法&#xff08;APF&#xff09;路径规划算法 在路径规划中&#xff0c;人工势场法&#xff08;APF&#xff09;是一种常见的方法&#xff0c;但传统的APF算法容易陷入局部极小值&#xff0c;导致路径规…...

ES语句——DSL(kibana语句)

一、查询操作 查看当前索引的数据结构 _mapping Get ai-open-log*/_mapping 查询当前索引下的文档数以及分片信息 _count Get ai-open-log*/_count { "count": 12345, //当前索引下的文档总数 "_shards": { //分片信息 "total&…...

y3编辑器教学5:触发器2 案例演示

文章目录 一、探索1.1 ECA1.1.1 ECA的定义1.1.2 使用触发器实现瞬间移动效果 1.2 变量1.2.1 什么是变量1.2.2 使用变量存储碎片收集数量并展现 1.3 if语句&#xff08;魔法效果挂接&#xff09;1.3.1 地形设置1.3.2 编写能量灌注逻辑1.3.3 编写能量灌注后&#xff0c;实现传送逻…...

MVC配置文件及位置

配置文件位置 默认位置 WEB-INF目录下&#xff0c;文件名&#xff1a;<servlet-name>-servlet.xml <?xml version"1.0" encoding"UTF-8"?> <web-app xmlns"http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi"http://www.w3.…...

【razor】echo搭配relay功能分析

echo 要搭配relay 实现作者说relay在linux上跑,可以模拟丢包、延迟目前没看到如何模拟。relay监听9200,有俩作用 echopeer1 发relay,replay 把peer1的包给peer2 ,实现p2p能力。 接收端:采集后发送发给relay的 接收端的地址就是自己,的地址就是本地的9200,因此是让relay接…...

C++类的运算符重载

目标 让自定义的类直接使用运算符运算 代码 头文件及类定义 #include <iostream>using namespace std; class Complex {int rel;int vir; public:void show(){cout <<"("<<this->rel<<","<<this->vir<<&quo…...

Motionface RTASR 离线实时语音识别直播字幕使用教程

软件使用场景&#xff1a; 直播、视频会议、课堂教学等需要实时字幕的场景。 1&#xff1a;系统要求 软件运行支持32位/64位windows 10/11系统&#xff0c;其他硬件要求无&#xff0c;无显卡也能实时识别字幕。 2&#xff1a;下载安装 链接:百度网盘 请输入提取码 提取码&#…...

【论文阅读】相似误差订正方法在风电短期风速预报中的应用研究

文章目录 概述&#xff1a;摘要1. 引言2. 相似误差订正算法&#xff08;核心&#xff09;3. 订正实验3.1 相似因子选取3.2 相似样本数试验3.3 时间窗时长实验 4. 订正结果分析4.1 评估指标对比4.2 风速曲线对比4.3 分风速段订正效果评估4.4 风速频率统计 5. 结论与讨论 概述&am…...

learn-(Uni-app)输入框u-search父子组件与input输入框(防抖与搜索触发)

1.父子组件u-search &#xff08;1&#xff09;父组件 <!-- 父组件 --> <template> <div><searchBar change"change" search"search"></searchBar> </div> </template> <script> // 子组件搜索 import…...

UNIX数据恢复—UNIX系统常见故障问题和数据恢复方案

UNIX系统常见故障表现&#xff1a; 1、存储结构出错&#xff1b; 2、数据删除&#xff1b; 3、文件系统格式化&#xff1b; 4、其他原因数据丢失。 UNIX系统常见故障解决方案&#xff1a; 1、检测UNIX系统故障涉及的设备是否存在硬件故障&#xff0c;如果存在硬件故障&#xf…...

c#动态更新替换json节点

需求项目json作为主模板&#xff0c;会应用到多个子模版&#xff0c;当后续项目变更只需要修改主模板中节点&#xff0c;并且能够动态更新到原来的子模版中去。 主模板示例&#xff1a; {"A": {"A1": "","A2": false,"A3"…...

kubernetes的可靠性测试或者故障测试有哪些?

kubernetes的可靠性测试或者故障测试有哪些? 在 Kubernetes (K8s) 集群中,可靠性测试和故障性测试旨在确保系统能够稳定运行并具备应对各种故障的能力。这些测试主要针对集群的组件、应用程序和基础设施。以下是详细的测试内容和方法: 一、可靠性测试 1. 高可用性测试 目…...

datax和datax-web打包成docker运行

概述 datax和datax-web从一台机器迁移到另一台时&#xff0c;要重新搭建一套运行环境&#xff0c;比较麻烦&#xff1b;打包成docker镜像后迁移就方便多了; 因为我的mysql版本是8&#xff0c;需要在datax的read和write中手动添加8的jdbc驱动 所以我先各自下载好了datax和data…...

ThreadLocal原理解析

ThreadLocal原理解析 本篇将带大家了解ThreadLocal的使用方法&#xff0c;并且深度剖析其原理和作用&#xff0c;通过阅读源码的方式&#xff0c;进一步了解其内部原理 ThreadLocal 是 Java 提供的一个工具类&#xff0c;用于为每个线程维护一个独立的变量副本。每个线程可以访…...

Android 分析 Activity 与 Fragment 的区别,部分使用的差异

一、基本概念 Activity&#xff1a;Activity 是应用中单独一个界面的一个组件&#xff0c;通常一个 Activity 对应一个界面&#xff08;或屏幕&#xff09;。Activity 控制了一个应用界面的生命周期&#xff0c;并且能够处理用户的输入和交互。 Fragment&#xff1a;Fragment …...

前端(Ajax)

1.客户端请求 向https://jsonplaceholder.typicode.com/users发送get请求 const xhr new XMLHttpRequest();console.log(xhr.readyState);xhr.open(get, https://jsonplaceholder.typicode.com/users)console.log(xhr.readyState);xhr.send();console.log(xhr.readyState);xh…...

【C++】约瑟夫环问题:深度解析与高级优化

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 &#x1f4af;前言约瑟夫环问题&#xff1a;深度解析与高级优化&#x1f4af;题目描述&#x1f4af;解决方案详解直接模拟法&#xff08;基于 C 实现&#xff09;代码解析示例执行过程 &#x1f4af;高级优…...

总结拓展十七:SAP 采购订单行项目“交货“页签解析

《 SAP采购订单行项目“交货”页签字段解析》 在 SAP 系统的采购流程中&#xff0c;采购订单行项目的“交货”页签承载着关键的信息&#xff0c;其中的字段更是对整个交货环节的精准描述和把控的重要元素。理解和正确解析这些字段&#xff0c;对于确保采购流程的顺利进行、优化…...

作业Day2: 多文件编译; 思维导图

目录 ①文件代码 及其所需头文件分析 main.c文件 1.h文件 1.c文件 ②运行结果&#xff1a; ③代码分析 结构体成员 数据类型的设定&#xff1a; 信息录入函数 信息删除 成绩排序 信息显示 自定义初始化函数 ④思维导图&#xff1a;​编辑 ①文件代码 及其所需头文…...

Kioptrix Level 1通关攻略

目录 修改靶机Kioptrix:Level 1 的网络模式 探测靶机IP地址 得到端口信息 扫描TCP端口 扫描UDP端口 脚本扫描 指纹探测 漏洞探测 目录枚举扫描 发现利用脚本 执行exp链接shell 修改靶机Kioptrix:Level 1 的网络模式 Kioptrix: Level 1靶机的默认网络模式是桥接&#x…...

01 下载opencv并配置vs开发环境

01 下载opencv并配置vs开发环境 01 下载windows版本的opencv 下载地址&#xff1a;点击 ​​ WIndows版本的是编译好的代码。 当然国外网站下载很慢&#xff0c;可以通过我分享的网盘链接下载 opencv-4.10.0-windows.exe https://www.alipan.com/s/wV7z4YsmXgN 点击链接保…...

Ubuntu22.04 docker如何发布镜像(和用git差不多)

在dockerhub上创建远程仓库&#xff1a;https://hub.docker.com/ 将本地镜像打tag&#xff0c;并修改成可以上传到 dockerhub 的形式 # 查看本地镜像# 修改镜像 ## docker tag 镜像名称:标签 新的镜像名称&#xff08;要和远程仓库dockerhub上的一致&#xff09;:新的标签pus…...

【Golang】——Gin 框架中的模板渲染详解

Gin 框架支持动态网页开发&#xff0c;能够通过模板渲染结合数据生成动态页面。在这篇文章中&#xff0c;我们将一步步学习如何在 Gin 框架中配置模板、渲染动态数据&#xff0c;并结合静态资源文件创建一个功能完整的动态网站。 文章目录 1. 什么是模板渲染&#xff1f; 1.1 概…...

React的局限性是什么?

性能&#xff1a; 虚拟 DOM 虽然提高了渲染性能&#xff0c;但在某些情况下可能会造成性能瓶颈&#xff0c;尤其是在处理大量数据或复杂更新时。对于非UI任务&#xff08;如计算密集型操作&#xff09;&#xff0c;React 本身并不擅长。 学习曲线&#xff1a; 对于初学者来说&a…...

【Vulkan入门】09-CreateFrameBuffer

目录 先叨叨git信息关键代码VulkanEnv::FindHostVisitbaleMemoryTypeIndex()TestPipeLine::CreateFramebuffers() 与网上大多数文章不同&#xff0c;其他文章基本上都使用窗口框架&#xff08;X11、GLFW、WSL等&#xff09;提供的surface来显示Vulkan渲染出的图像。我认为那样会…...

罗技键鼠更换新台式机无蓝牙通过接收器安装

优联驱动下载&#xff1a; http://support.logitech.com.cn/zh_cn/software/unifying &#xff08;下载安装后按照步骤一步步操作&#xff0c;匹配后即可使用&#xff09; 向京东客服反馈后提供的驱动下载安装连接 有问题欢迎评论沟通~...

深入了解Modbus TCP协议:介绍、原理解析与应用示例

深入了解Modbus TCP协议&#xff1a;介绍、原理解析与应用示例 在工业自动化领域&#xff0c;设备之间的通信与数据交换至关重要。Modbus协议作为一种经典的通信协议&#xff0c;因其简单、开放和易于实现的特点&#xff0c;被广泛应用于各种工业设备之间的数据传输。而Modbus…...

vue2 项目中实现动态代理,服务器上通过nginx部署 实现动态代理

一、前言&&原理 前言&#xff1a;vue2 项目中&#xff0c;请求接口是从表格的当前获取的&#xff0c;也就是接口ip:端口号:路经不确定&#xff0c;要实现点击表格当前行请求对应的接口 实现原理&#xff1a;将实际要请求的ip等信息存在请求头中&#xff0c;用的时候再…...

OpenGL 几何着色器高级应用

几何着色器高级应用 概念回顾 几何着色器(Geometry Shader)是 OpenGL 管线中的可选着色器阶段,位于顶点着色器(Vertex Shader) 和光栅化阶段 之间。 其核心功能是基于输入的图元(如点、线或三角形),生成新的图元,或对输入的图元进行修改。 几何着色器的执行是以图元…...

QT JSON文件解析

参考博客 https://blog.csdn.net/cpp_learner/article/details/118421096 1 打开文件&#xff0c;读取全部内容 QFile file("../Json/js.json"); if (!file.open(QFile::ReadOnly | QFile::Text)) {qDebug() << "cant open error!";return; }// 读…...

c++中string字符串与其他类型的转换

一、string 转换成其他类型 1、转换为整数 使用std::stoi&#xff08;适用于int&#xff09;、std::stol&#xff08;适用于long&#xff09;、std::stoll&#xff08;适用于long long&#xff09;、std::stoul&#xff08;适用于unsigned long&#xff09;和std::stoull&…...

aws(学习笔记第十七课) SQS Amazon Simple Queue Service服务

aws(学习笔记第十七课) SQS Amazon Simple Queue Service服务 学习内容&#xff1a; 使用SQS Amazon Simple Queue Service服务整体代码&#xff08;nodejs的通常工程&#xff09;代码动作 1. 使用SQS Amazon Simple Queue Service服务 利用应用程序来学习SQS 创建S3$ aws s…...

【FAQ】HarmonyOS SDK 闭源开放能力 —Push Kit(8)

1.问题描述&#xff1a; 在AGC中&#xff0c;推送服务的消息回执新建成功后&#xff0c;有一个有效期 1&#xff0c;这个有效期是什么意思&#xff0c;过期后&#xff0c;会影响什么呢&#xff1f; 2&#xff0c;这个有效期是否可以修改成一直不过期&#xff1f; 解决方案&…...

mysql 的 binlog 原理

binlog的作用:binlog的三种格式Statement-Based Replication (SBR)&#xff1a;Row-Based Replication (RBR)&#xff1a;Mixed-Based Replication (MBR)&#xff1a; 总结&#xff1a;如何选择:如何配置binlog? binlog的作用: 数据恢复: 如果mysql的数据丢失了,又没有备份数…...

Android显示系统(10)- SurfaceFlinger内部结构

一、前言: 之前讲述了native层如何使用SurfaceFlinger,我们只是看到了简单的API调用,从本文开始,我们逐步进行SurfaceFlinger内部结构的分析。话不多说,莱茨狗~ 二、类图: 2.1、总体架构: 先看下SurfaceFlinger的关键成员和我们BootAnimation侧关键成员如何对应起来…...

独家首发 | 基于多级注意力机制的并行预测模型

往期精彩内容&#xff1a; 时序预测&#xff1a;LSTM、ARIMA、Holt-Winters、SARIMA模型的分析与比较 全是干货 | 数据集、学习资料、建模资源分享&#xff01; EMD变体分解效果最好算法——CEEMDAN&#xff08;五&#xff09;-CSDN博客 拒绝信息泄露&#xff01;VMD滚动分…...

Burp suite2 (泷羽sec)

声明 学习视频来自B站UP主 泷羽sec,如涉及侵泷羽sec权马上删除文章。 笔记只是方便各位师傅学习知识,以下网站只涉及学习内容,其他的都与本人无关,切莫逾越法律红线,否则后果自负 这节课旨在扩大自己在网络安全方面的知识面&#xff0c;了解网络安全领域的见闻&#xff0c;了…...

npm或yarn包配置地址源

三种方法 1.配置.npmrc 文件 在更目录新增.npmrc文件 然后写入需要访问的包的地址 2.直接yarn.lock文件里面修改地址 简单粗暴 3.yarn install 的时候添加参数 设置包的仓库地址 yarn config set registry https://registry.yarnpkg.com 安装&#xff1a;yarn install 注意…...

Referer头部在网站反爬虫技术中的运用

网站数据的安全性和完整性至关重要。爬虫技术&#xff0c;虽然在数据收集和分析中发挥着重要作用&#xff0c;但也给网站管理员带来了挑战。为了保护网站数据不被恶意爬取&#xff0c;反爬虫技术应运而生。本文将探讨HTTP头部中的Referer字段在反爬虫技术中的应用&#xff0c;并…...

Next.js授权管理教程:深入掌握Session管理

更多有关Next.js教程&#xff0c;请查阅&#xff1a; 【目录】Next.js 独立开发系列教程-CSDN博客 目录 引言 1. Session管理的基本概念 1.1 什么是Session管理&#xff1f; 1.2 Session与Cookie 1.3 使用Session的优点 2. 在Next.js中管理Session 2.1 使用cookie存储Se…...

Python+OpenCV系列:滤波器的魔力

滤波器是图像处理领域中不可或缺的工具。无论是去除噪声、锐化图像还是提取特征&#xff0c;滤波器都扮演着重要角色。本篇将从简单到复杂&#xff0c;带你快速掌握 PythonOpenCV 中的滤波器使用技巧。 什么是滤波器&#xff1f; 滤波器是一种对图像像素值进行计算、平滑或增强…...

代码随想录算法训练营day41|动态规划买卖股票问题

今天的三题买卖股票问题&#xff0c;实际上解题方法都大同小异&#xff0c;思路也和昨天的树形dp有相似之处&#xff0c;都是用一个dp数组的不同下标来记录不同的状态。其中第一题是只买卖一次&#xff0c;可以用贪心的方法&#xff0c;找出左边的最小值和右边的最大值&#xf…...