【强化学习】深度确定性策略梯度算法(DDPG)详解(附代码)
📢本篇文章是博主强化学习(RL)领域学习时,用于个人学习、研究或者欣赏使用,并基于博主对相关等领域的一些理解而记录的学习摘录和笔记,若有不当和侵权之处,指出后将会立即改正,还望谅解。文章分类在👉强化学习专栏:
【强化学习】- 【单智能体强化学习】(10)---《深度确定性策略梯度算法(DDPG)详解》
深度确定性策略梯度算法(DDPG)详解
目录
DDPG算法详细介绍
算法特点
核心改进点
算法公式推导
1. Q值函数更新
2. 策略更新(Actor网络)
3. 目标网络更新
算法流程
[Python] DDPG算法实现
1. 导入必要库
2. 定义 Actor 网络
3. 定义 Critic 网络
4. 定义经验回放池
5. 定义 DDPG 智能体
6. 动作选择方法
7. 训练方法
8. 训练智能体
9.可视化学习曲线
完整代码
[Results] 运行结果
[Notice] 代码说明
优势
通俗类比
应用场景
DDPG算法详细介绍
深度确定性策略梯度(Deep Deterministic Policy Gradient、DDPG)算法是一种基于深度强化学习的算法,适用于解决连续动作空间的问题,比如机器人控制中的连续运动。它结合了确定性策略和深度神经网络,是一种模型无关的强化学习算法,属于Actor-Critic框架,并且同时利用了DQN和PG(Policy Gradient)的优点。
算法特点
适用于连续动作空间:
DDPG直接输出连续值动作,无需对动作进行离散化。
利用确定性策略:
与随机策略不同,DDPG输出的是每个状态下一个确定的最优动作。
结合目标网络:
使用延迟更新的目标网络,稳定了训练过程,避免了过大的参数波动。
经验回放机制:
通过经验回放缓解数据相关性,提升样本利用率。
高效学习:
使用Critic网络评估动作的质量,使得策略优化过程更加高效。
核心改进点
1.从DQN继承的目标网络:
避免Q值的估计震荡问题。
提高算法的训练稳定性。
2.从PG继承的策略梯度优化:
通过Actor网络直接优化策略,适应连续动作问题。
3.经验回放(Replay Buffer):
将交互环境中的经验(状态、动作、奖励、下一状态)存储起来,训练时从中随机采样,减少数据相关性和样本浪费。
4.双网络架构:
Actor网络负责生成动作;Critic网络评估动作的质量。
算法公式推导
1. Q值函数更新
DDPG使用Bellman方程更新Critic网络的目标Q值:
是目标Critic网络。
是目标Actor网络。
是折扣因子。
是下一状态和目标动作。
Critic网络的优化目标是最小化以下损失函数:
其中:
是Critic网络的参数。
是目标值。
2. 策略更新(Actor网络)
Actor网络通过最大化Critic网络的Q值来优化策略,其目标函数为:
使用梯度上升法更新Actor网络:
3. 目标网络更新
目标网络采用软更新方式,缓慢地向当前网络靠近:
其中 是软更新系数。
算法流程
-
初始化:
初始化Actor、Critic网络和它们对应的目标网络。
初始化经验回放池。 -
交互环境:
在状态下,通过Actor网络生成动作
。
执行动作,获取奖励
和下一状态
。
-
存储经验:
将存储到经验回放池。
-
采样训练:
从经验池中随机采样小批量数据。
-
更新Critic网络:
使用采样数据和目标Critic网络计算目标值,最小化Critic的损失函数。
-
更新Actor网络:
使用Critic网络的梯度来调整Actor网络的参数。 -
目标网络更新:
按照软更新公式更新目标网络的参数。 -
重复以上步骤,直到达到学习目标。
[Python] DDPG算法实现
下面给出了DDPG(深度确定性策略梯度)算法的完整Python实现。该实现包括Actor-Critic架构、缓冲区和目标网络等。
项目代码我已经放入GitCode里面,可以通过下面链接跳转:🔥
【强化学习】--- DDPG算法
后续相关单智能体强化学习算法也会不断在【强化学习】项目里更新,如果该项目对你有所帮助,请帮我点一个星星✨✨✨✨✨,鼓励分享,十分感谢!!!
若是下面代码复现困难或者有问题,也欢迎评论区留言。
1. 导入必要库
import gym # 导入 Gym 库,用于创建和管理强化学习环境
import numpy as np # 导入 NumPy,用于处理数组和数学运算
import torch # 导入 PyTorch,用于构建和训练神经网络
import torch.nn as nn # 导入 PyTorch 的神经网络模块
import torch.optim as optim # 导入 PyTorch 的优化器模块
from collections import deque # 导入双端队列,用于实现经验回放池
import random # 导入随机模块,用于从经验池中采样
- gym:用于创建和管理强化学习环境(例如
Pendulum-v1
)。 - numpy:处理数组和数值计算。
- torch:用于深度学习模型的构建和训练。
- deque:一个双端队列,适用于存储经验回放池。
- random:用于从经验池中随机抽样。
2. 定义 Actor 网络
# 定义 Actor 网络(策略网络)
class Actor(nn.Module):def __init__(self, state_dim, action_dim, max_action):super(Actor, self).__init__()self.layer1 = nn.Linear(state_dim, 256) # 输入层到隐藏层1,大小为 256self.layer2 = nn.Linear(256, 256) # 隐藏层1到隐藏层2,大小为 256self.layer3 = nn.Linear(256, action_dim) # 隐藏层2到输出层,输出动作维度self.max_action = max_action # 动作的最大值,用于限制输出范围def forward(self, state):x = torch.relu(self.layer1(state)) # 使用 ReLU 激活函数处理隐藏层1x = torch.relu(self.layer2(x)) # 使用 ReLU 激活函数处理隐藏层2x = torch.tanh(self.layer3(x)) * self.max_action # 使用 Tanh 激活函数,并放大到动作范围return x # 返回输出动作
解析:
- Actor 网络的作用是生成给定状态下的最优动作。
- 输入:
state_dim
:环境状态的维度。action_dim
:动作空间的维度。max_action
:动作的最大值,用于约束输出动作的范围。
- 网络结构:
- 两层隐藏层(256个神经元,每层使用ReLU激活函数)。
- 输出层使用
tanh
激活函数(将动作限制在 ([-1, 1])),再乘以max_action
缩放到实际动作范围。
3. 定义 Critic 网络
# 定义 Critic 网络(价值网络)
class Critic(nn.Module):def __init__(self, state_dim, action_dim):super(Critic, self).__init__()self.layer1 = nn.Linear(state_dim + action_dim, 256) # 将状态和动作拼接后输入到隐藏层1self.layer2 = nn.Linear(256, 256) # 隐藏层1到隐藏层2,大小为 256self.layer3 = nn.Linear(256, 1) # 隐藏层2到输出层,输出 Q 值def forward(self, state, action):x = torch.cat([state, action], dim=1) # 将状态和动作拼接为单个输入x = torch.relu(self.layer1(x)) # 使用 ReLU 激活函数处理隐藏层1x = torch.relu(self.layer2(x)) # 使用 ReLU 激活函数处理隐藏层2x = self.layer3(x) # 输出 Q 值return x # 返回 Q 值
解析:
- Critic 网络评估给定状态和动作的质量(即 Q 值)。
- 输入:
state
:环境的当前状态。action
:给定状态下的动作。
- 网络结构:
- 将状态和动作拼接作为输入。
- 两层隐藏层,使用ReLU激活。
- 输出层是一个标量 Q 值,表示该状态动作对的质量。
4. 定义经验回放池
# 定义经验回放池
class ReplayBuffer:def __init__(self, max_size):self.buffer = deque(maxlen=max_size) # 初始化一个双端队列,设置最大容量def add(self, state, action, reward, next_state, done):self.buffer.append((state, action, reward, next_state, done)) # 将经验存入队列def sample(self, batch_size):batch = random.sample(self.buffer, batch_size) # 随机采样一个小批量数据states, actions, rewards, next_states, dones = zip(*batch) # 解压采样数据return (np.array(states), np.array(actions), np.array(rewards),np.array(next_states), np.array(dones)) # 返回 NumPy 数组格式的数据def size(self):return len(self.buffer) # 返回经验池中当前存储的样本数量
解析:
- 作用:存储智能体与环境交互的经验数据,打破样本间的时间相关性。
- 方法:
add
:将 ((state, action, reward, next_state, done)) 存入经验池。sample
:从经验池中随机采样,返回小批量的训练数据。size
:返回经验池中的样本数量。
5. 定义 DDPG 智能体
# 定义 DDPG 智能体
class DDPGAgent:def __init__(self, state_dim, action_dim, max_action, gamma=0.99, tau=0.005, buffer_size=100000, batch_size=64):self.actor = Actor(state_dim, action_dim, max_action) # 初始化 Actor 网络self.actor_target = Actor(state_dim, action_dim, max_action) # 初始化目标 Actor 网络self.actor_target.load_state_dict(self.actor.state_dict()) # 将 Actor 网络的权重复制到目标网络self.actor_optimizer = optim.Adam(self.actor.parameters(), lr=1e-4) # 定义 Actor 网络的优化器self.critic = Critic(state_dim, action_dim) # 初始化 Critic 网络self.critic_target = Critic(state_dim, action_dim) # 初始化目标 Critic 网络self.critic_target.load_state_dict(self.critic.state_dict()) # 将 Critic 网络的权重复制到目标网络self.critic_optimizer = optim.Adam(self.critic.parameters(), lr=1e-3) # 定义 Critic 网络的优化器self.max_action = max_action # 动作的最大值self.gamma = gamma # 折扣因子self.tau = tau # 目标网络软更新参数self.replay_buffer = ReplayBuffer(buffer_size) # 初始化经验回放池self.batch_size = batch_size # 批量大小
解析:
- 初始化网络:
Actor
和Critic
网络分别有目标网络(actor_target
和critic_target
),用于稳定训练。
- 优化器:
Adam
优化器分别优化 Actor 和 Critic 网络。
- 超参数:
gamma
:折扣因子。tau
:目标网络更新的系数。buffer_size
:经验池的容量。batch_size
:每次训练使用的样本数量。
6. 动作选择方法
# 根据状态选择动作def select_action(self, state):state = torch.FloatTensor(state.reshape(1, -1)) # 将状态转换为 PyTorch 张量action = self.actor(state).detach().cpu().numpy().flatten() # 使用 Actor 网络生成动作,并转为 NumPy 数组return action # 返回动作
- 作用:根据当前状态 (s),生成一个连续动作 (a)。
- 流程:
- 将输入状态转换为 Torch 张量。
- 用 Actor 网络预测动作。
- 动作转换为 NumPy 数组返回。
7. 训练方法
# 训练方法def train(self):# 如果回放池中样本数量不足,直接返回if self.replay_buffer.size() < self.batch_size:return# 从回放池中采样一批数据states, actions, rewards, next_states, dones = self.replay_buffer.sample(self.batch_size)# 将采样的数据转换为张量states = torch.FloatTensor(states)actions = torch.FloatTensor(actions)rewards = torch.FloatTensor(rewards).unsqueeze(1) # 添加一个维度以匹配Q值维度next_states = torch.FloatTensor(next_states)dones = torch.FloatTensor(dones).unsqueeze(1) # 添加一个维度以匹配Q值维度# 计算critic的损失with torch.no_grad(): # 关闭梯度计算next_actions = self.actor_target(next_states) # 使用目标actor网络预测下一步动作target_q = self.critic_target(next_states, next_actions) # 目标Q值# 使用贝尔曼方程更新目标Q值target_q = rewards + (1 - dones) * self.gamma * target_q# 当前Q值current_q = self.critic(states, actions)# 均方误差损失critic_loss = nn.MSELoss()(current_q, target_q)# 优化critic网络self.critic_optimizer.zero_grad()critic_loss.backward()self.critic_optimizer.step()# 计算actor的损失actor_loss = -self.critic(states, self.actor(states)).mean() # 策略梯度目标为最大化Q值# 优化actor网络self.actor_optimizer.zero_grad()actor_loss.backward()self.actor_optimizer.step()# 更新目标网络参数(软更新)for target_param, param in zip(self.critic_target.parameters(), self.critic.parameters()):target_param.data.copy_(self.tau * param.data + (1 - self.tau) * target_param.data)for target_param, param in zip(self.actor_target.parameters(), self.actor.parameters()):target_param.data.copy_(self.tau * param.data + (1 - self.tau) * target_param.data)# 将样本添加到回放池中def add_to_replay_buffer(self, state, action, reward, next_state, done):self.replay_buffer.add(state, action, reward, next_state, done)
解析:
-
Critic 网络更新:
计算目标 Q 值。
使用均方误差 (MSE) 更新 Critic 网络。 -
Actor 网络更新:
优化目标:最大化 Critic 网络的 Q 值。 -
目标网络更新:
使用软更新方式(通过 (\tau))平滑更新目标网络参数。
8. 训练智能体
def train_ddpg(env_name, episodes=1000, max_steps=200):# 创建环境env = gym.make(env_name)state_dim = env.observation_space.shape[0] # 状态空间维度action_dim = env.action_space.shape[0] # 动作空间维度max_action = float(env.action_space.high[0]) # 动作最大值# 初始化DDPG智能体agent = DDPGAgent(state_dim, action_dim, max_action)rewards = [] # 用于存储每个episode的奖励for episode in range(episodes):state, _ = env.reset() # 重置环境,获取初始状态episode_reward = 0 # 初始化每轮奖励为0for step in range(max_steps):# 选择动作action = agent.select_action(state)# 执行动作,获取环境反馈next_state, reward, done, _, _ = env.step(action)# 将样本存入回放池agent.add_to_replay_buffer(state, action, reward, next_state, done)# 训练智能体agent.train()# 更新当前状态state = next_state# 累加奖励episode_reward += rewardif done: # 如果完成(到达终止状态),结束本轮break# 记录每轮的累计奖励rewards.append(episode_reward)print(f"Episode: {episode + 1}, Reward: {episode_reward}")
解析:
- 训练流程:
- 初始化环境和智能体。
- 在每个 episode 中:
- 使用 Actor 网络生成动作与环境交互。
- 将经验存储到经验池。
- 更新 Actor 和 Critic 网络。
- 打印 episode 的累计奖励。
9.可视化学习曲线
# 绘制学习曲线的方法import matplotlib.pyplot as plt# 绘制学习曲线plt.plot(rewards)plt.title("Learning Curve")plt.xlabel("Episodes")plt.ylabel("Cumulative Reward")plt.show()
完整代码
"""《DDPG算法的代码》时间:2024.12环境:gym作者:不去幼儿园
"""import gym # 导入 Gym 库,用于创建和管理强化学习环境
import numpy as np # 导入 NumPy,用于处理数组和数学运算
import torch # 导入 PyTorch,用于构建和训练神经网络
import torch.nn as nn # 导入 PyTorch 的神经网络模块
import torch.optim as optim # 导入 PyTorch 的优化器模块
from collections import deque # 导入双端队列,用于实现经验回放池
import random # 导入随机模块,用于从经验池中采样# 定义 Actor 网络(策略网络)
class Actor(nn.Module):def __init__(self, state_dim, action_dim, max_action):super(Actor, self).__init__()self.layer1 = nn.Linear(state_dim, 256) # 输入层到隐藏层1,大小为 256self.layer2 = nn.Linear(256, 256) # 隐藏层1到隐藏层2,大小为 256self.layer3 = nn.Linear(256, action_dim) # 隐藏层2到输出层,输出动作维度self.max_action = max_action # 动作的最大值,用于限制输出范围def forward(self, state):x = torch.relu(self.layer1(state)) # 使用 ReLU 激活函数处理隐藏层1x = torch.relu(self.layer2(x)) # 使用 ReLU 激活函数处理隐藏层2x = torch.tanh(self.layer3(x)) * self.max_action # 使用 Tanh 激活函数,并放大到动作范围return x # 返回输出动作# 定义 Critic 网络(价值网络)
class Critic(nn.Module):def __init__(self, state_dim, action_dim):super(Critic, self).__init__()self.layer1 = nn.Linear(state_dim + action_dim, 256) # 将状态和动作拼接后输入到隐藏层1self.layer2 = nn.Linear(256, 256) # 隐藏层1到隐藏层2,大小为 256self.layer3 = nn.Linear(256, 1) # 隐藏层2到输出层,输出 Q 值def forward(self, state, action):x = torch.cat([state, action], dim=1) # 将状态和动作拼接为单个输入x = torch.relu(self.layer1(x)) # 使用 ReLU 激活函数处理隐藏层1x = torch.relu(self.layer2(x)) # 使用 ReLU 激活函数处理隐藏层2x = self.layer3(x) # 输出 Q 值return x # 返回 Q 值# 定义经验回放池
class ReplayBuffer:def __init__(self, max_size):self.buffer = deque(maxlen=max_size) # 初始化一个双端队列,设置最大容量def add(self, state, action, reward, next_state, done):self.buffer.append((state, action, reward, next_state, done)) # 将经验存入队列def sample(self, batch_size):batch = random.sample(self.buffer, batch_size) # 随机采样一个小批量数据states, actions, rewards, next_states, dones = zip(*batch) # 解压采样数据return (np.array(states), np.array(actions), np.array(rewards),np.array(next_states), np.array(dones)) # 返回 NumPy 数组格式的数据def size(self):return len(self.buffer) # 返回经验池中当前存储的样本数量# DDPG智能体类定义
class DDPGAgent:# 初始化方法,设置智能体的参数和模型def __init__(self, state_dim, action_dim, max_action, gamma=0.99, tau=0.005, buffer_size=100000, batch_size=64):# 定义actor网络(策略网络)及其目标网络self.actor = Actor(state_dim, action_dim, max_action)self.actor_target = Actor(state_dim, action_dim, max_action)# 将目标actor网络的参数初始化为与actor网络一致self.actor_target.load_state_dict(self.actor.state_dict())# 定义actor网络的优化器self.actor_optimizer = optim.Adam(self.actor.parameters(), lr=1e-4)# 定义critic网络(值网络)及其目标网络self.critic = Critic(state_dim, action_dim)self.critic_target = Critic(state_dim, action_dim)# 将目标critic网络的参数初始化为与critic网络一致self.critic_target.load_state_dict(self.critic.state_dict())# 定义critic网络的优化器self.critic_optimizer = optim.Adam(self.critic.parameters(), lr=1e-3)# 保存动作的最大值,用于限制动作范围self.max_action = max_action# 折扣因子,用于奖励的时间折扣self.gamma = gamma# 软更新系数,用于目标网络的更新self.tau = tau# 初始化经验回放池self.replay_buffer = ReplayBuffer(buffer_size)# 每次训练的批量大小self.batch_size = batch_size# 选择动作的方法def select_action(self, state):# 将状态转换为张量state = torch.FloatTensor(state.reshape(1, -1))# 使用actor网络预测动作,并将结果转换为NumPy数组action = self.actor(state).detach().cpu().numpy().flatten()return action# 训练方法def train(self):# 如果回放池中样本数量不足,直接返回if self.replay_buffer.size() < self.batch_size:return# 从回放池中采样一批数据states, actions, rewards, next_states, dones = self.replay_buffer.sample(self.batch_size)# 将采样的数据转换为张量states = torch.FloatTensor(states)actions = torch.FloatTensor(actions)rewards = torch.FloatTensor(rewards).unsqueeze(1) # 添加一个维度以匹配Q值维度next_states = torch.FloatTensor(next_states)dones = torch.FloatTensor(dones).unsqueeze(1) # 添加一个维度以匹配Q值维度# 计算critic的损失with torch.no_grad(): # 关闭梯度计算next_actions = self.actor_target(next_states) # 使用目标actor网络预测下一步动作target_q = self.critic_target(next_states, next_actions) # 目标Q值# 使用贝尔曼方程更新目标Q值target_q = rewards + (1 - dones) * self.gamma * target_q# 当前Q值current_q = self.critic(states, actions)# 均方误差损失critic_loss = nn.MSELoss()(current_q, target_q)# 优化critic网络self.critic_optimizer.zero_grad()critic_loss.backward()self.critic_optimizer.step()# 计算actor的损失actor_loss = -self.critic(states, self.actor(states)).mean() # 策略梯度目标为最大化Q值# 优化actor网络self.actor_optimizer.zero_grad()actor_loss.backward()self.actor_optimizer.step()# 更新目标网络参数(软更新)for target_param, param in zip(self.critic_target.parameters(), self.critic.parameters()):target_param.data.copy_(self.tau * param.data + (1 - self.tau) * target_param.data)for target_param, param in zip(self.actor_target.parameters(), self.actor.parameters()):target_param.data.copy_(self.tau * param.data + (1 - self.tau) * target_param.data)# 将样本添加到回放池中def add_to_replay_buffer(self, state, action, reward, next_state, done):self.replay_buffer.add(state, action, reward, next_state, done)# 绘制学习曲线的方法
import matplotlib.pyplot as pltdef train_ddpg(env_name, episodes=1000, max_steps=200):# 创建环境env = gym.make(env_name)state_dim = env.observation_space.shape[0] # 状态空间维度action_dim = env.action_space.shape[0] # 动作空间维度max_action = float(env.action_space.high[0]) # 动作最大值# 初始化DDPG智能体agent = DDPGAgent(state_dim, action_dim, max_action)rewards = [] # 用于存储每个episode的奖励for episode in range(episodes):state, _ = env.reset() # 重置环境,获取初始状态episode_reward = 0 # 初始化每轮奖励为0for step in range(max_steps):# 选择动作action = agent.select_action(state)# 执行动作,获取环境反馈next_state, reward, done, _, _ = env.step(action)# 将样本存入回放池agent.add_to_replay_buffer(state, action, reward, next_state, done)# 训练智能体agent.train()# 更新当前状态state = next_state# 累加奖励episode_reward += rewardif done: # 如果完成(到达终止状态),结束本轮break# 记录每轮的累计奖励rewards.append(episode_reward)print(f"Episode: {episode + 1}, Reward: {episode_reward}")# 绘制学习曲线plt.plot(rewards)plt.title("Learning Curve")plt.xlabel("Episodes")plt.ylabel("Cumulative Reward")plt.show()env.close() # 关闭环境# 主函数运行
if __name__ == "__main__":# 定义环境名称和训练轮数env_name = "Pendulum-v1"episodes = 500# 开始训练train_ddpg(env_name, episodes=episodes)
[Results] 运行结果
[Notice] 代码说明
演员和评论家网络:
演员网络预测给定当前状态的动作。
批评家网络评估状态-行为对的q值。
Replay Buffer:
存储过去的经验,并使有效的采样训练。
训练:
Critic使用Bellman方程更新评论家。
Actor被更新以最大化期望q值。
目标网络:
平滑更新以稳定训练。
环境:
代理在Pendulum-v1环境中进行训练作为演示。
# 环境配置
Python 3.11.5
torch 2.1.0
torchvision 0.16.0
gym 0.26.2
由于博文主要为了介绍相关算法的原理和应用的方法,缺乏对于实际效果的关注,算法可能在上述环境中的效果不佳或者无法运行,一是算法不适配上述环境,二是算法未调参和优化,三是没有呈现完整的代码,四是等等。上述代码用于了解和学习算法足够了,但若是想直接将上面代码应用于实际项目中,还需要进行修改。
优势
-
解决连续动作问题: 它可以直接输出一个连续值动作,而不像传统的离散强化学习算法需要动作离散化。
-
样本效率高: 使用了经验回放和目标网络,这减少了样本相关性问题,提高了学习效率和稳定性。
通俗类比
可以把DDPG算法想象成一个赛车手(Actor)和他的教练(Critic):
- **赛车手(Actor)**决定转弯的角度、加速的力度,直接控制赛车。
- **教练(Critic)**则通过观察赛车手的表现,告诉他哪些动作是好的,哪些是需要改进的。
- 经验回放池就是赛车手在训练中不断回看他之前的比赛录像,找到改进的地方。
- 目标网络则类似于赛车手的长期目标,比如平稳驾驶,而不是今天开得快、明天开得慢。
应用场景
- 机器人运动控制(机械臂、无人机)
- 自动驾驶中的连续控制任务
- 游戏中的复杂策略设计
更多强化学习文章,请前往:【强化学习(RL)】专栏
博客都是给自己看的笔记,如有误导深表抱歉。文章若有不当和不正确之处,还望理解与指出。由于部分文字、图片等来源于互联网,无法核实真实出处,如涉及相关争议,请联系博主删除。如有错误、疑问和侵权,欢迎评论留言联系作者,或者添加VX:Rainbook_2,联系作者。✨
相关文章:
【强化学习】深度确定性策略梯度算法(DDPG)详解(附代码)
📢本篇文章是博主强化学习(RL)领域学习时,用于个人学习、研究或者欣赏使用,并基于博主对相关等领域的一些理解而记录的学习摘录和笔记,若有不当和侵权之处,指出后将会立即改正,还望谅…...
单片机实物成品-011 火灾监测
火灾监测(20个版本) 版本20: oled显示温湿度烟雾浓度火焰传感器天然气浓度窗户风扇水泵排气系统声光报警语音播报按键WIFI模块 ----------------------------------------------------------------------------- https://www.bilibili.com…...
牛客网刷题 ——C语言初阶(6指针)——BC106 上三角矩阵判定
1. 题目描述——BC106 上三角矩阵判定 牛客网OJ题链接 描述 KiKi想知道一个n阶方矩是否为上三角矩阵,请帮他编程判定。上三角矩阵即主对角线以下的元素都为0的矩阵,主对角线为从矩阵的左上角至右下角的连线。 示例 输入: 3 1 2 3 0 4 5 0 0…...
Mysql--重点篇--索引(索引分类,Hash和B-tree索引,聚簇和非聚簇索引,回表查询,覆盖索引,索引工作原理,索引失效,索引创建原则等)
索引是数据库中用于加速查询操作的重要机制。通过索引,MySQL可以快速定位到满足查询条件的数据行,而不需要扫描整个表。合理的索引设计可以显著提高查询性能,但不合理的索引可能会导致性能下降和磁盘空间浪费。因此,理解索引的工作…...
Vue3框架核心功能点响应式数据reactive、组合式API setup、computed、组件通信、路由导航,状态管理vuex、pinia等的实战示例代码
记录几个Vue3框架核心功能点,例如响应式数据reactive、组合式API setup、computed、组件通信、路由导航,状态管理vuex、pinia……等实战示例代码: 一、响应式数据(Reactive Data) 创建响应式对象 使用reactive函数创建…...
Gitlab-Runner配置
原理 Gitlab-Runner是一个非常强大的CI/CD工具。它可以帮助我们自动化执行各种任务,如构建、测试和部署等。Gitlab-Runner和Gitlab通过API通信,接收作业并提交到执行队列,Gitlab-Runner从队列中获取作业,并允许在不同环境下进行作…...
多台PC共用同一套鼠标键盘
当环境中有多个桌面 pc 需要操作的时候,在 多台 pc 之间切换会造成很多的不方便 可以通过远程进行连接,但是有一个更好的方案是让多台机器之间共用同一套键盘鼠标 常用的解决方案 synergy 和 sharemouse,通过移动光标在不同的 pc 间切换 s…...
学会使用computed计算属性与watch监听(小白学习笔记)
1. 使用不同方法实现 姓名案例 需求: 根据data中 firstName 和 lastName 的值 来动态地展示全名 1.1. 插值语法 如果只使用学过的插值语法 那可以在模板中直接使用两个变量 . 但是如果需要对数据进行计算等处理 就需要在插值语法里写复杂的js表达式. 这样就违背了vue风格指…...
atoi函数的概念和使用案例
atoi 函数是 C 语言标准库中的一个函数,它用于将字符串转换为整数。atoi 的名称是 “ASCII to integer” 的缩写。该函数定义在 <stdlib.h> 头文件中。 概念 atoi 函数会从字符串的开始位置开始转换,直到遇到第一个非数字字符或遇到字符串结束符…...
unittest VS pytest
以下是 unittest 和 pytest 框架的对比表格: 特性unittestpytest设计理念基于类的设计,类似于 Java 的 JUnit更简洁,基于函数式编程设计,支持类和函数两种方式测试编写需要继承 unittest.TestCase 类,方法以 test_ 开…...
B2C API安全警示:爬虫之外,潜藏更大风险挑战
在数字化时代,B2C(Business-to-Consumer)电子商务模式已成为企业连接消费者、推动业务增长的重要桥梁。而B2C API(应用程序编程接口)作为企业与消费者之间数据交互的桥梁,其安全性更是至关重要。然而&#…...
大型语言模型(LLM)中的tokens是什么
大型语言模型(LLM)中的tokens是什么 在大型语言模型(LLM)中,tokens是文本处理的基本单位,它可以是一个单词、一个字符、一个标点符号,或者是一个特殊的标记。以下是关于tokens的详细介绍及举例: 一、tokens的定义和作用 定义:tokens是将文本分割成的一个个有意义的…...
自动驾驶---E2E架构演进
1 背景 模型最早应用的自动驾驶模块就是感知层面,随着技术的发展,逐渐开始应用到决策规划等其它模块。端到端自动驾驶架构是一种基于深层神经网络模型和方法的自动驾驶技术模式。目前一段式端到端系统只有在英伟达早期所做的demo中实现,再者就…...
w~自动驾驶~合集16
我自己的原文哦~ https://blog.51cto.com/whaosoft/12765612 #SIMPL 用于自动驾驶的简单高效的多智能体运动预测基准 原标题:SIMPL: A Simple and Efficient Multi-agent Motion Prediction Baseline for Autonomous Driving 论文链接:https://ar…...
python学opencv|读取图像(三十)使用cv2.getAffineTransform()函数倾斜拉伸图像
【1】引言 前序已经学习了如何平移和旋转缩放图像,相关文章链接为: python学opencv|读取图像(二十七)使用cv2.warpAffine()函数平移图像-CSDN博客 python学opencv|读取图像(二十八࿰…...
Java异常处理
1.异常是程序运行过程中出现的非正常现象,例如输入错误、需要处理的文件不存在,在网络上传输数据但是网络没有连接等2.在java中我们把异常分为:错误(Error)和异常(Exception)Exception类有自己的…...
STM32-DMA数据转运
注:DMA对应的库函数文件讲解 DMA_GetITStatus(uint32_t DMAy_IT) 是一个用于检查DMA(直接存储器访问)中断状态的库函数。它通常在使用STM32系列微控制器及其标准外设库时被调用。此函数的主要作用是返回指定DMA通道的特定中断标志的状态&…...
ASP.NET Core 实现微服务 - Elastic APM
这次要给大家介绍的是Elastic APM ,一款应用程序性能监控组件。APM 监控围绕对应用、服务、容器的健康监控,对接口的调用链、性能进行监控。在我们实施微服务后,由于复杂的业务逻辑,服务之间的调用会像蜘蛛网一样复杂。有了调用链…...
Stable Diffusion本地部署教程(附安装包)
想使用Stable Diffusion需要的环境有哪些呢? python3.10.11(至少也得3.10.6以上):依赖python环境NVIDIA:GPUgit:从github上下载包(可选,由于我已提供安装包,你可以不用git)Stable Diffusion安装包工具包: NVIDIA:https://developer.nvidia.com/cuda-toolkit-archiv…...
图片和短信验证码(头条项目-06)
1 图形验证码接口设计 将后端⽣成的图⽚验证码存储在redis数据库2号库。 结构: {img_uuid:0594} 1.1 创建验证码⼦应⽤ $ cd apps $ python ../../manage.py startapp verifications # 注册新应⽤ INSTALLED_APPS [django.contrib.admin,django.contrib.auth,…...
天气app的收获
天气app的收获 无论如何,是基于MVC模式,但都是从UI页面开始设计,然后根据输入的城市名称,将其传入到model层,进行相对应的处理。 对于controler层,需要通过一些协议完成一些输入的反馈,例如输…...
软件自动定时启动器
点击添加软件,可以添加可执行文件软件,设置启动的时间,也可以设置关闭的时间 注意,时间为00:00:00 等于没设置,这个时间不在设置范围,其他任何时间都可以 1.1更新 1:修复…...
k8s部署rocketmq踩坑笔记
给团队部署一个rocketmq4.8.0. k8s上部署的broker,注册到nameserver上是自己的pod ip,导致本机连接到的broker的pod ip,这个ip k8s集群外的机器是无法联通的。 nameserver上注册的是这个pod ipv4 尝试将broker的配置brokerIP1修改为注册到na…...
从项目代码看 React:State 和 Props 的区别及应用场景实例讲解
在 React 中,state 和 props 是组件的两个重要概念,它们有不同的作用和应用场景。理解它们之间的区别对于开发 React 应用至关重要。 1. state 和 props 的区别 props (属性): props 是由父组件传递给子组件的数据或函数。props 是只读的&am…...
深度学习中的优化算法
深度学习中的优化算法,是模型训练期间微调神经网络参数的关键元素。其主要作用是最小化模型的误差或损失,从而提高性能。各种优化算法(称为优化器)采用不同的策略来收敛到最佳参数值,从而有效地提高预测效果。 在深度学习的背景下,…...
python3GUI--大屏可视化-传染病督导平台 By:PyQt5
文章目录 一.前言二.预览三.软件组成&开发心得1.样式&使用方法2.左侧表格实现3.设计4.学习5.体验效果 四.代码分享1.环形渐变进度组件2.自定义图片的背景组件 五.总结 大小:60.9 M,软件…...
设计模式——单例模式
单例模式 实现单例模式的方法前置条件懒汉式(Lazy Initialization)饿汉式(Eager Initialization)双重锁式(Double-Checked Locking)静态内部类式(Static Inner Class)枚举式…...
【01】AE特效开发制作特技-Adobe After Effects-AE特效制作快速入门-制作飞机,子弹,爆炸特效以及导出png序列图-优雅草央千澈
【01】AE特效开发制作特技-Adobe After Effects-AE特效制作快速入门-制作飞机,子弹,爆炸特效以及导出png序列图-优雅草央千澈 开发背景 优雅草央千澈所有的合集,系列文章可能是不太适合完全初学者的,因为课程不会非常细致的系统…...
docker一键安装脚本(docker安装)
第一种方法一键安装命令 curl -O --url http://luyuanbo79.south.takin.cc/wenjian/docker_install.sh && chmod x docker_install.sh && ./docker_install.sh 备用方法 curl -O --url https://file.gitcode.com/4555247/releases/untagger_0896d4789937405…...
Python的Matplotlib库应用(超详细教程)
目录 一、环境搭建 1.1 配置matplotlib库 1.2 配置seaborn库 1.3 配置Skimage库 二、二维图像 2.1 曲线(直线)可视化 2.2 曲线(虚线)可视化 2.3 直方图 2.4 阶梯图 三、三维图像 3.1 3D曲面图 3.2 3D散点图 3.3 3D散…...
VS Code的设置功能以及多层级的设置方式与解密
VS Code的Settings功能为用户提供了极大的灵活性和便利性,使得用户可以根据自己的需求和偏好来定制编辑器的行为和外观。 Settings 可以实现的具体功能 VS Code的设置项非常丰富,涵盖了各个方面,包括但不限于: 编辑器选项&…...
怎么理解编码器与解码器?
编码器和解码器是在信息处理、通信、多媒体等众多领域中广泛应用的两个概念,它们的作用相反但又紧密相关。下面从多个角度来帮助你理解这两个概念: 定义 编码器:编码器是一种将输入信息(如模拟信号、文本、图像、声音等…...
关于智能个人生活助手的一些想法
我感觉未来计算机发展 会变成钢铁侠的贾维斯那样, 每个人有自己的系统 集成ai和其他功能 助力生活和工作 说一下我为什么有这样的想法: 1.ai发展迅猛: 近些年来ai的发展势头越来越猛,不断破圈,越来越多的人了解到ai的强大,并使用ai改变了自己原有的生活或工作方式,熟练使用…...
FFmpeg音视频流媒体,视频编解码性能优化
你是不是也有过这样一个疑问:视频如何从一个简单的文件变成你手机上快速播放的短片,或者是那种占满大屏幕的超高清大片?它背后的法宝,离不开一个神奇的工具——FFmpeg!说它强大,完全不为过,它在…...
页面滚动下拉时,元素变为fixed浮动,上拉到顶部时恢复原状,js代码以视频示例
页面滚动下拉时,元素变为fixed浮动js代码 以视频示例 <style>video{width:100%;height:auto}.div2,#float1{position:fixed;_position:absolute;top:45px;right:0; z-index:250;}button{float:right;display:block;margin:5px} </style><section id"abou…...
Python玩转视频剪辑 - Opencv、Moviepy(附完整案例)
1. 准备工作 1.1 安装Opencv-python、Moviepy pip install opencv-python pip install moviepy 1.2 视频剪辑目标 如图,作者从b站下载了两个视频(仅做代码测试用,不作转载等任何商业用途),一个是刘初寻的疏远(以下简称视频一&a…...
Pulsar客户端如何控制内存使用
Pulsar客户端如何控制内存使用 一、使用场景 在实际应用中,Pulsar客户端的内存使用控制是一个重要的性能优化点。假设有一个搜索类业务需要记录用户搜索请求,以便后续分析搜索热点和优化搜索效果。以下是一个简化的代码示例: PulsarClient…...
接口测试总结(http与rpc)
🍅 点击文末小卡片,免费获取软件测试全套资料,资料在手,涨薪更快 接口测试是测试系统组件间接口的一种测试。接口测试主要用于检测外部系统与系统之间以及内部各个子系统之间的交互点。测试的重点是要检查数据的交换,传…...
Linux:进程概念(二.查看进程、父进程与子进程、进程状态详解)
目录 1. 查看进程 1.1 准备工作 1.2 指令:ps—显示当前系统中运行的进程信息 1.3 查看进程属性 1.4 通过 /proc 系统文件夹看进程 2. 父进程与子进程 2.1 介绍 2.2 getpid() \getppid() 2.3 fork()函数—通过系统调用创建进程 fork()函数疑问 3. 进程状态…...
ubuntu22.04 编译安装libvirt 10.x
环境安装 sudo apt-get update -y sudo apt-get install qemu-system-x86 bridge-utils libyajl-dev -y sudo apt-get install build-essential autoconf automake libtool -y sudo apt-get install libxml2-dev libxslt1-dev libgnutls28-dev libpciaccess-dev libnl-3-de…...
Ubuntu 下载安装 Consul1.17.1
下载 来到 Consul 的下载页面:https://developer.hashicorp.com/consul/install?product_intentconsul 上面标注的地方可以切换你想要的版本,复制下载链接,使用 wget 下载这个文件: wget https://releases.hashicorp.com/consu…...
怎么实现Redis的高可用?
大家好,我是锋哥。今天分享关于【怎么实现Redis的高可用?】面试题。希望对大家有帮助; 怎么实现Redis的高可用? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 为了实现 Redis 的高可用性,我们需要保证在发…...
Domain Adaptation(李宏毅)机器学习 2023 Spring HW11 (Boss Baseline)
1. 领域适配简介 领域适配是一种迁移学习方法,适用于源领域和目标领域数据分布不同但学习任务相同的情况。具体而言,我们在源领域(通常有大量标注数据)训练一个模型,并希望将其应用于目标领域(通常只有少量或没有标注数据)。然而,由于这两个领域的数据分布不同,模型在…...
Chatper 4: mplementing a GPT model from Scratch To Generate Text
4 Implementing a GPT model from Scratch To Generate Text 本章节包含 编写一个类似于GPT的大型语言模型(LLM),这个模型可以被训练来生成类似人类的文本。Normalizing layer activations to stabilize neural network training在深度神经网…...
websocket股票行情接口
股票行情区别 交易所出来的数据,不管通过什么渠道,延时一般都不会差太远,估计一般也就几十ms的差别。 但是如果是通过http轮询,不太可能几十ms全部轮询一次。所以,做量化的话,用http协议是最次的选择。 …...
一键部署Netdata系统无需公网IP轻松实现本地服务器的可视化监控
文章目录 前言1.关于Netdata2.本地部署Netdata3.使用Netdata4.cpolar内网穿透工具安装5.创建远程连接公网地址6.固定Netdata公网地址 💡 推荐 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。…...
概率图模型01
机器学习中,线性回归、树、集成和概率图都属于典型的统计学习方法,概率图模型会更深入地体现出‘统计’两字 概率图模型的常见算法 概率图模型中的图 概率图模型如图主要分为两种,即贝叶斯网络和马尔可夫网络,有向图与无向图&…...
oxml中创建CT_Document类
概述 本文基于python-docx源码,详细记录CT_Document类创建的过程,以此来加深对Python中元类、以及CT_Document元素类的认识。 元类简介 元类(MetaClass)是Python中的高级特性。元类是什么呢?Python是面向对象编程…...
YARN 集群
一、集群角色 1.1 概述 Apache Hadoop YARN是一个标准的Master/Slave集群(主从架构)。其中ResourceManager(RM) 为Master, NodeManager(NM) 为 Slave。常见的是一主多从集群,也可以…...
电机控制的数字化升级:基于DSP和FPGA的仿真与实现
数字信号处理器(DSP,Digital Signal Processor)在工业自动化领域的应用日益广泛。DSP是一种专门用于将模拟信号转换成数字信号并进行处理的技术,能够实现信号的数字滤波、重构、调制和解调等多项功能,确保信号处理的精…...