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

【RL Latest Tech】分层强化学习:Option-Critic架构算法

        📢本篇文章是博主强化学习RL领域学习时,用于个人学习、研究或者欣赏使用,并基于博主对相关等领域的一些理解而记录的学习摘录和笔记,若有不当和侵权之处,指出后将会立即改正,还望谅解。文章分类在👉强化学习专栏:

       【强化学习】(22)---《分层强化学习:Option-Critic架构算法》

分层强化学习:Option-Critic架构算法

目录

1. 基本概念

2. Option-Critic框架的核心要素

2.1 选项(Option)

2.2 Intra-Option Q-Learning

2.3 选项的终止条件

3. Option-Critic算法工作流程

[Python] Option-Critic实现

算法训练代码

测试和可视化代码

[Notice]  注意事项

4. Option-Critic的优势

5. 相关的挑战

6. 总结


        分层强化学习(Hierarchical Reinforcement Learning, HRL)通过将复杂问题分解为更小的子问题,显著提高了强化学习算法在解决高维状态空间和长期目标任务中的效率。Option-Critic架构是分层强化学习中一种非常有影响力的方法,专门用于自动发现和优化子策略(称为“Option”)。它是在经典的Options框架基础上提出的,用来处理分层决策问题,特别是可以在没有明确的子目标定义的情况下自动学习子策略。


1. 基本概念

        在Option-Critic架构中,最核心的思想是使用 “选项” 来建模高级行为策略。每个选项代表一段策略或行为,负责特定的子任务。具体地说,选项包括三个部分:

  1. 初始条件(Initiation set):智能体可以选择该选项的状态集合。
  2. 内部策略(Intra-option policy):智能体在选项激活时的行动策略,即在特定状态下采取的行动。
  3. 终止条件(Termination condition):定义选项何时终止或结束。

        在这种架构下,智能体不再直接学习每个状态下的单一动作,而是学习 何时选择选项以及如何在选项内行动。这使得学习更加抽象化和高效化。


2. Option-Critic框架的核心要素

2.1 选项(Option)
  • 选项 是智能体可以执行的一个序列动作,这些动作组成一个子策略。选项不仅包含具体的操作步骤,还包含 何时开始选项 以及 何时终止选项
  • 在每一个时间步,智能体可以选择:执行一个基础动作或选择一个更高级别的选项。在选项内,智能体执行动作直到达到终止条件,然后选择新的选项。
2.2 Intra-Option Q-Learning

Option-Critic框架引入了 Intra-Option Q-Learning 算法,用于更新选项的内部策略。在传统的强化学习中,Q-learning用于评估在特定状态下选择某个动作的价值。而在Option-Critic中,Intra-Option Q-Learning则用于评估 在选项内 如何选择动作。具体步骤如下:

  1. 对于每个选项,有一个内部策略(\pi),它定义了在选项激活时的动作选择方式。
  2. Q函数(Q(s, o))代表在状态(s)选择选项(o)的期望回报。
  3. 当智能体在执行选项时,内部策略根据当前状态选择具体动作,并且根据Intra-Option Q-Learning规则更新Q值。
2.3 选项的终止条件

        选项的终止条件决定了何时退出当前选项并返回上层策略。例如,一个选项可能在达到某个目标状态时终止,或者在经过一定的时间步数后自动终止。终止条件的优化同样是Option-Critic框架中的一个关键部分。


3. Option-Critic算法工作流程

Option-Critic算法通过以下步骤完成学习过程:

  1. 选项初始化:初始化选项的初始条件、内部策略和终止条件。
  2. 执行过程
    • 智能体基于当前状态和Q值函数选择某个选项。
    • 执行选项的内部策略,在环境中采取具体行动,直到终止条件触发。
  3. Q值更新:使用Intra-Option Q-Learning更新每个选项的Q值函数。
  4. 策略更新:同时更新选项的内部策略和终止条件,使得智能体能够更好地进行决策。
  5. 重复以上过程,直至收敛。

[Python] Option-Critic实现

        🔥若是下面代码复现困难或者有问题,欢迎评论区留言;需要以整个项目形式的代码,请在评论区留下您的邮箱📌,以便于及时分享给您(私信难以及时回复)。

        Option-Critic架构在CartPole环境中的Python代码,使用了OpenAI GymPyTorch进行实现。

步骤:

  1. 设置 CartPole 环境。
  2. 定义选项的策略网络
  3. 定义用于估计每个选项值的Q 网络
  4. 实现选项内策略梯度终止梯度
  5. 创建经验回放缓冲区,用于存储和采样经验。
  6. 使用时间差分学习策略梯度训练智能体。
  7. 测试和可视化智能体的表现。

算法训练代码

"""《Option-Critic实现》时间:2024.10.01环境:CartPole 作者:不去幼儿园
"""
import gym
import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
from collections import deque
import random# 超参数调整
GAMMA = 0.98  # 稍微减少折扣因子,减少远期奖励影响
LEARNING_RATE = 0.0005  # 降低学习率,提高训练的稳定性
BATCH_SIZE = 128  # 增加批次大小以稳定训练
MEMORY_SIZE = 20000  # 增大经验回放缓冲区
EPSILON_DECAY = 0.99  # 减慢 epsilon 的衰减速度
MIN_EPSILON = 0.05  # 增大最小 epsilon,保持一定探索
NUM_OPTIONS = 2
NUM_EPISODES = 1000  # 增加训练回合数# 修改后的网络结构
class CriticNetwork(nn.Module):def __init__(self, state_dim, num_options):super(CriticNetwork, self).__init__()self.fc1 = nn.Linear(state_dim, 256)  # 增加隐藏层神经元数量self.fc2 = nn.Linear(256, num_options)def forward(self, state):x = torch.relu(self.fc1(state))return self.fc2(x)class IntraOptionPolicyNetwork(nn.Module):def __init__(self, state_dim, num_options, action_dim):super(IntraOptionPolicyNetwork, self).__init__()self.fc1 = nn.Linear(state_dim, 256)  # 增加神经元数量self.fc2 = nn.Linear(256, num_options * action_dim)self.num_options = num_optionsself.action_dim = action_dimdef forward(self, state, option):x = torch.relu(self.fc1(state))policy_logits = self.fc2(x)option_policy = policy_logits.view(-1, self.num_options, self.action_dim)return option_policy[:, option, :]class TerminationNetwork(nn.Module):def __init__(self, state_dim, num_options):super(TerminationNetwork, self).__init__()self.fc1 = nn.Linear(state_dim, 256)  # 增加神经元数量self.fc2 = nn.Linear(256, num_options)def forward(self, state):x = torch.relu(self.fc1(state))termination_probs = torch.sigmoid(self.fc2(x))return termination_probs# 经验回放缓冲区
class ReplayBuffer:def __init__(self, capacity):self.buffer = deque(maxlen=capacity)def push(self, state, option, action, reward, next_state, done):self.buffer.append((state, option, action, reward, next_state, done))def sample(self, batch_size):states, options, actions, rewards, next_states, dones = zip(*random.sample(self.buffer, batch_size))return np.stack(states), options, actions, rewards, np.stack(next_states), donesdef size(self):return len(self.buffer)# 选择动作
def select_action(policy_net, state, option, epsilon):if random.random() < epsilon:return random.choice([0, 1])  # CartPole 动作空间为 2(0 或 1)else:state = torch.FloatTensor(state).unsqueeze(0)action_probs = torch.softmax(policy_net(state, option), dim=-1)return torch.argmax(action_probs).item()# Option-Critic 智能体
class OptionCriticAgent:def __init__(self, state_dim, action_dim, num_options):self.policy_net = IntraOptionPolicyNetwork(state_dim, num_options, action_dim)self.q_net = CriticNetwork(state_dim, num_options)self.termination_net = TerminationNetwork(state_dim, num_options)self.optimizer_policy = optim.Adam(self.policy_net.parameters(), lr=LEARNING_RATE)self.optimizer_q = optim.Adam(self.q_net.parameters(), lr=LEARNING_RATE)self.optimizer_term = optim.Adam(self.termination_net.parameters(), lr=LEARNING_RATE)self.epsilon = 1.0self.num_options = num_optionsself.memory = ReplayBuffer(MEMORY_SIZE)def train(self, batch_size):if self.memory.size() < batch_size:returnstates, options, actions, rewards, next_states, dones = self.memory.sample(batch_size)states = torch.FloatTensor(states)next_states = torch.FloatTensor(next_states)rewards = torch.FloatTensor(rewards)options = torch.LongTensor(options)actions = torch.LongTensor(actions)dones = torch.FloatTensor(dones)# 更新 Q 函数q_values = self.q_net(states)next_q_values = self.q_net(next_states).detach()target_q_values = rewards + GAMMA * next_q_values.max(1)[0] * (1 - dones)loss_q = nn.functional.mse_loss(q_values.gather(1, options.unsqueeze(1)).squeeze(), target_q_values)self.optimizer_q.zero_grad()loss_q.backward()self.optimizer_q.step()# 更新选项内策略for option in range(self.num_options):policy_logits = self.policy_net(states, option)action_probs = torch.softmax(policy_logits, dim=-1)log_action_probs = torch.log(action_probs)policy_loss = -log_action_probs.gather(1, actions.unsqueeze(1)).mean()self.optimizer_policy.zero_grad()policy_loss.backward()self.optimizer_policy.step()# 更新终止概率terminations = self.termination_net(states)termination_loss = nn.functional.binary_cross_entropy(terminations.gather(1, options.unsqueeze(1)).squeeze(),dones)self.optimizer_term.zero_grad()termination_loss.backward()self.optimizer_term.step()def remember(self, state, option, action, reward, next_state, done):self.memory.push(state, option, action, reward, next_state, done)# 训练智能体
env = gym.make('CartPole-v1')
state_dim = env.observation_space.shape[0]
action_dim = env.action_space.nagent = OptionCriticAgent(state_dim, action_dim, NUM_OPTIONS)for episode in range(NUM_EPISODES):state, _ = env.reset()option = random.choice(range(NUM_OPTIONS))  # 随机选择一个选项done = Falseepisode_reward = 0while not done:action = select_action(agent.policy_net, state, option, agent.epsilon)next_state, reward, done, _, __ = env.step(action)agent.remember(state, option, action, reward, next_state, done)agent.train(BATCH_SIZE)# 选项终止时选择新选项if random.random() < agent.termination_net(torch.FloatTensor(state))[option].item():option = random.choice(range(NUM_OPTIONS))state = next_stateepisode_reward += rewardagent.epsilon = max(MIN_EPSILON, agent.epsilon * EPSILON_DECAY)print(f"Episode {episode + 1}: Total Reward: {episode_reward}")env.close()# Option-Critic 智能体
class OptionCriticAgent:def __init__(self, state_dim, action_dim, num_options):self.policy_net = IntraOptionPolicyNetwork(state_dim, num_options, action_dim)self.q_net = CriticNetwork(state_dim, num_options)self.termination_net = TerminationNetwork(state_dim, num_options)self.optimizer_policy = optim.Adam(self.policy_net.parameters(), lr=LEARNING_RATE)self.optimizer_q = optim.Adam(self.q_net.parameters(), lr=LEARNING_RATE)self.optimizer_term = optim.Adam(self.termination_net.parameters(), lr=LEARNING_RATE)self.epsilon = 1.0self.num_options = num_optionsself.memory = ReplayBuffer(MEMORY_SIZE)def train(self, batch_size):if self.memory.size() < batch_size:returnstates, options, actions, rewards, next_states, dones = self.memory.sample(batch_size)states = torch.FloatTensor(states)next_states = torch.FloatTensor(next_states)rewards = torch.FloatTensor(rewards)options = torch.LongTensor(options)actions = torch.LongTensor(actions)dones = torch.FloatTensor(dones)# 更新 Q 函数q_values = self.q_net(states)next_q_values = self.q_net(next_states).detach()target_q_values = rewards + GAMMA * next_q_values.max(1)[0] * (1 - dones)loss_q = nn.functional.mse_loss(q_values.gather(1, options.unsqueeze(1)).squeeze(), target_q_values)self.optimizer_q.zero_grad()loss_q.backward()self.optimizer_q.step()# 更新选项内策略for option in range(self.num_options):policy_logits = self.policy_net(states, option)action_probs = torch.softmax(policy_logits, dim=-1)log_action_probs = torch.log(action_probs)policy_loss = -log_action_probs.gather(1, actions.unsqueeze(1)).mean()self.optimizer_policy.zero_grad()policy_loss.backward()self.optimizer_policy.step()# 更新终止概率terminations = self.termination_net(states)termination_loss = nn.functional.binary_cross_entropy(terminations.gather(1, options.unsqueeze(1)).squeeze(),dones)self.optimizer_term.zero_grad()termination_loss.backward()self.optimizer_term.step()def remember(self, state, option, action, reward, next_state, done):self.memory.push(state, option, action, reward, next_state, done)# 在 CartPole 环境中训练智能体
env = gym.make('CartPole-v1')
state_dim = env.observation_space.shape[0]
action_dim = env.action_space.nagent = OptionCriticAgent(state_dim, action_dim, NUM_OPTIONS)for episode in range(NUM_EPISODES):state, _ = env.reset()option = random.choice(range(NUM_OPTIONS))  # 初始化为随机选项done = Falseepisode_reward = 0while not done:action = select_action(agent.policy_net, state, option, agent.epsilon)next_state, reward, done, _, __ = env.step(action)agent.remember(state, option, action, reward, next_state, done)agent.train(BATCH_SIZE)if random.random() < agent.termination_net(torch.FloatTensor(state))[option].item():option = random.choice(range(NUM_OPTIONS))  # 终止当前选项并选择新选项state = next_stateepisode_reward += rewardagent.epsilon = max(MIN_EPSILON, agent.epsilon * EPSILON_DECAY)print(f"Episode {episode + 1}: Total Reward: {episode_reward}")env.close()

测试和可视化代码

        要在 CartPole 环境中测试 Option-Critic 模型并显示动画,需要利用 gym 库中的 render() 方法。以下代码演示了如何在训练完模型后进行测试,并实时显示动画。

import gym
import torch# 测试 Option-Critic 模型并显示动画
def test_option_critic(agent, env, num_episodes=5):for episode in range(num_episodes):state, _ = env.reset()option = random.choice(range(agent.num_options))  # 随机选择一个选项done = Falseepisode_reward = 0env.render()  # 初始化渲染环境while not done:env.render()  # 渲染环境,显示动画action = select_action(agent.policy_net, state, option, epsilon=0.0)  # 使用已学策略选择动作next_state, reward, done, _, __ = env.step(action)# 检查选项是否应终止,并在终止时重新选择新选项if random.random() < agent.termination_net(torch.FloatTensor(state))[option].item():option = random.choice(range(agent.num_options))state = next_stateepisode_reward += rewardprint(f"测试 Episode {episode + 1}: Total Reward: {episode_reward}")env.close()# 创建 CartPole 环境并调用测试函数
env = gym.make('CartPole-v1', render_mode='human')
test_option_critic(agent, env)

[Notice]  注意事项

        确保您使用的环境和库版本支持 render_mode 参数。如果使用的 Gym 版本较旧,可能不支持此选项。在这种情况下,建议更新 gym 库。

        上述采用的是gym == 0.26.2

pip install --upgrade gym

注意 :env.step(action)的返回参数数量,多则删除__

        由于博文主要为了介绍相关算法的原理应用的方法,缺乏对于实际效果的关注,算法可能在上述环境中的效果不佳,一是算法不适配上述环境,二是算法未调参和优化,三是等。上述代码用于了解和学习算法足够了,但若是想直接将上面代码应用于实际项目中,还需要进行修改。


4. Option-Critic的优势

Option-Critic架构的优点主要体现在以下几方面:

  1. 层次化决策:通过分层的结构,智能体能够进行更高级别的决策,不必在每一步都从头开始学习。
  2. 策略的可重用性:通过选项,智能体可以学习可重复使用的策略片段,用于不同的任务场景。
  3. 提升效率:在复杂任务中,分层策略减少了动作空间的复杂度,使得学习过程更加高效。

5. 相关的挑战

尽管Option-Critic架构在理论上具备优势,但在实际应用中仍面临一些挑战:

  • 选项的设计与优化:选择合适的选项数量和复杂度对于模型性能有很大影响。
  • 探索与利用的平衡:在不同的选项之间,如何平衡探索新选项与利用已有的选项是一个难题。
  • 终止条件的优化:如何合理地学习选项的终止条件,避免选项过早或过晚终止,同样是一个挑战。

6. 总结

        Option-Critic架构通过引入 选项 这一中间层次,将复杂问题分解为多个子任务,并通过学习这些子任务的策略与终止条件来实现有效的分层强化学习。它是一种非常有前景的强化学习框架,适用于处理复杂、长期依赖的任务。

参考文献

Bacon, P.-L., Harb, J., & Precup, D. (2017). The Option-Critic Architecture. Proceedings of the 31st AAAI Conference on Artificial Intelligence (AAAI-17).

 完整项目代码:

【RL Latest Tech】分层强化学习:Option-Critic架构算法项目代码实现

        Option-Critic架构通过整合选项策略和Q学习算法,提供了一种优雅的解决方案,使得智能体能够高效地在复杂环境中进行学习和决策。


     文章若有不当和不正确之处,还望理解与指出。由于部分文字、图片等来源于互联网,无法核实真实出处,如涉及相关争议,请联系博主删除。如有错误、疑问和侵权,欢迎评论留言联系作者,或者关注VX公众号:Rain21321,联系作者。✨

相关文章:

【RL Latest Tech】分层强化学习:Option-Critic架构算法

&#x1f4e2;本篇文章是博主强化学习RL领域学习时&#xff0c;用于个人学习、研究或者欣赏使用&#xff0c;并基于博主对相关等领域的一些理解而记录的学习摘录和笔记&#xff0c;若有不当和侵权之处&#xff0c;指出后将会立即改正&#xff0c;还望谅解。文章分类在&#x1f…...

分布式数据库

前言 分布式数据库系统&#xff08;‌DDBS&#xff09;包含分布式数据库管理系统&#xff08;‌DDBMS&#xff09;和分布式数据库&#xff08;DDB&#xff09;。在分布式数据库系统中&#xff0c;一个应用程序可以对数据库进行透明操作&#xff0c;数据库中的数据分别在不同的…...

MySQL(2)【库的操作】

阅读导航 引言一、创建数据库1. 基本语法2. 创建数据库案例&#x1f4cc;创建名为db1的数据库&#x1f4cc;创建一个使用utf8字符集的db2数据库&#x1f4cc;创建一个使用utf8字符集&#xff0c;并带校对规则的db3数据库 二、字符集和校验规则1. 查看系统默认字符集以及校验规则…...

python pip更换(切换)国内镜像源

国内镜像源列表(个人推荐清华大学的源) ​ 清华大学&#xff1a; https://pypi.tuna.tsinghua.edu.cn/simple阿里云&#xff1a; http://mirrors.aliyun.com/pypi/simple豆瓣&#xff1a; http://pypi.douban.com/simple中国科技大学&#xff1a; https://pypi.mirrors.ustc.e…...

阿里云镜像源无法访问?使用 DaoCloud 镜像源加速 Docker 下载(Linux 和 Windows 配置指南)

&#x1f680; 作者主页&#xff1a; 有来技术 &#x1f525; 开源项目&#xff1a; youlai-mall &#x1f343; vue3-element-admin &#x1f343; youlai-boot &#x1f343; vue-uniapp-template &#x1f33a; 仓库主页&#xff1a; GitCode&#x1f4ab; Gitee &#x1f…...

使用 BERT 和逻辑回归进行文本分类及示例验证

使用 BERT 和逻辑回归进行文本分类及示例验证 一、引言 在自然语言处理领域中&#xff0c;文本分类是一项至关重要的任务。本文将详细介绍如何结合 BERT 模型与逻辑回归算法来实现文本分类&#xff0c;并通过实际示例进行验证。 二、环境准备 为了运行本文中的代码&#xf…...

【skywalking 】监控 Spring Cloud Gateway 数据

使用Spring Cloud 开发&#xff0c;用Skywalking 监控服务&#xff0c;但是Skywalking 默认是不支持 Spring Cloud Gateway 网关服务的&#xff0c;需要手动将 Gateway 的插件添加到 Skywalking 启动依赖 jar 中。 skywalking相关版本信息 jdk&#xff1a;17skywalking&#x…...

SpringWeb

SpringWeb SpringWeb 概述 SpringWeb 是 spring 框架中的一个模块&#xff0c;基于 Servlet API 构建的 web 框架. springWeb 是 Spring 为 web 层开发提供的一整套完备的解决方案。 在 web 层框架历经 Strust1&#xff0c;WebWork&#xff0c;Strust2 等诸多产品的历代更…...

嵌入式刷题(day21)

MySQL和sqlite的区别 MySQL和SQLite是两种常见的关系型数据库管理系统(RDBMS),但它们在特性、使用场景和架构方面有显著的区别: 1. 架构 MySQL:是一个基于服务器的数据库系统,遵循客户端-服务器架构。MySQL服务器运行在主机上,客户端通过网络连接并发送查询。它可以并…...

OpenAI 下一代旗舰模型现身?奥尔特曼亲自辟谣“猎户座“传闻

在人工智能领域最受瞩目的ChatGPT即将迎来两周岁之际&#xff0c;一场关于OpenAI新旗舰模型的传闻再次引发业界热议。然而&#xff0c;这场喧嚣很快就被OpenAI掌门人奥尔特曼亲自澄清。 事件源于科技媒体The Verge的一则报道。据多位知情人士透露&#xff0c;OpenAI可能会在11…...

【C++】STL初识

【C】STL初识 文章目录 【C】STL初识前言一、STL基本概念二、STL六大组件简介三、STL三大组件四、初识STL总结 前言 本篇文章将讲到STL基本概念&#xff0c;STL六大组件简介&#xff0c;STL三大组件&#xff0c;初识STL。 一、STL基本概念 STL(Standard Template Library,标准…...

框架篇补充(东西多 需要重新看网课)

什么是AOP 面向切面编程 降低耦合 提高代码的复用 Spring的bean的生命周期 实例化bean 赋值 初始化bean 使用bean 销毁bean SpringMVC的执行流程 Springboot自动装配原理 实际上就是为了从spring.factories文件中 获取到对应的需要 进行自动装配的类 并生成相应的Bean…...

合约门合同全生命周期管理系统:企业合同管理的数字化转型之道

合约门合同全生命周期管理系统&#xff1a;企业合同管理的数字化转型之道 1. 引言 在现代企业中&#xff0c;合同管理已经不再是简单的文件存储和审批流程&#xff0c;而是企业合规性、风险管理和业务流程的关键环节之一。随着企业规模的扩大和合同数量的增加&#xff0c;传统…...

等保测评与风险管理:识别、评估和缓解潜在的安全威胁

在信息化时代&#xff0c;数据已成为企业最宝贵的资产之一&#xff0c;而信息安全则成为守护这份资产免受侵害的重中之重。等保测评&#xff08;信息安全等级保护测评&#xff09;作为保障信息系统安全的重要手段&#xff0c;其核心在于通过科学、规范、专业的评估手段&#xf…...

Golang Agent 可观测性的全面升级与新特性介绍

作者&#xff1a;张海彬&#xff08;古琦&#xff09; 背景 自 2024 年 6 月 26 日&#xff0c;ARMS 发布了针对 Golang 应用的可观测性监控功能以来&#xff0c;阿里云 ARMS 团队与程序语言与编译器团队一直致力于不断优化和提升该系统的各项功能&#xff0c;旨在为开发者提…...

SpringBoot的开篇 特点 初始化 ioc 配置文件

文章目录 前言SpringBoot发展历程SpringBoot前置准备SpringBoot特点 SpringBoot项目初始化项目启动Springboot的核心概念IOC概念介绍Bean对象通过注解扫描包 例子配置文件 前言 SpringBoot发展历程 最初&#xff0c;Spring框架的使用需要大量的XML配置&#xff0c;这使得开发…...

docker 可用镜像服务地址(2024.10.25亲测可用)

1.错误 Error response from daemon: Get “https://registry-1.docker.io/v2/” 原因&#xff1a;镜像服务器地址不可用。 2.可用地址 编辑daemon.json&#xff1a; vi /etc/docker/daemon.json内容修改如下&#xff1a; {"registry-mirrors": ["https://…...

【SQL实验】表的更新和简单查询

完整代码在文章末尾 在上次实验创建的educ数据库基础上&#xff0c;用SQL语句为student表、course表和sc表中添加以下记录 【SQL实验】数据库、表、模式的SQL语句操作_创建一个名为educ数据库,要求如下: (下面三个表中属性的数据类型需要自己设计合适-CSDN博客在这篇博文中已经…...

【C++】 string的了解及使用

标准库中的string类 在使用string类时&#xff0c;必须包含#include头文件以及using namespace std; string类的常用接口说明 C中string为我们提供了丰富的接口来供我们使用 – string接口文档 这里我们只介绍一些常见的接口 string类对象的常见构造 #include <iostrea…...

【K8S】kubernetes-dashboard.yaml

https://raw.githubusercontent.com/kubernetes/dashboard/v3.0.0-alpha0/charts/kubernetes-dashboard.yaml 以下链接的内容&#xff1a; 由于国内访问不了&#xff0c;找到一些方法下载了这个文件内容&#xff0c; 部署是mages 对象的镜像 WEB docker.io/kubernetesui/dash…...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段&#xff1a; 构建阶段&#xff08;Build Stage&#xff09;&#xff1a…...

376. Wiggle Subsequence

376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...

苍穹外卖--缓存菜品

1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得&#xff0c;如果用户端访问量比较大&#xff0c;数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据&#xff0c;减少数据库查询操作。 缓存逻辑分析&#xff1a; ①每个分类下的菜品保持一份缓存数据…...

招商蛇口 | 执笔CID,启幕低密生活新境

作为中国城市生长的力量&#xff0c;招商蛇口以“美好生活承载者”为使命&#xff0c;深耕全球111座城市&#xff0c;以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子&#xff0c;招商蛇口始终与城市发展同频共振&#xff0c;以建筑诠释对土地与生活的…...

纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join

纯 Java 项目&#xff08;非 SpringBoot&#xff09;集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...

关于easyexcel动态下拉选问题处理

前些日子突然碰到一个问题&#xff0c;说是客户的导入文件模版想支持部分导入内容的下拉选&#xff0c;于是我就找了easyexcel官网寻找解决方案&#xff0c;并没有找到合适的方案&#xff0c;没办法只能自己动手并分享出来&#xff0c;针对Java生成Excel下拉菜单时因选项过多导…...

Python学习(8) ----- Python的类与对象

Python 中的类&#xff08;Class&#xff09;与对象&#xff08;Object&#xff09;是面向对象编程&#xff08;OOP&#xff09;的核心。我们可以通过“类是模板&#xff0c;对象是实例”来理解它们的关系。 &#x1f9f1; 一句话理解&#xff1a; 类就像“图纸”&#xff0c;对…...

Java多线程实现之Runnable接口深度解析

Java多线程实现之Runnable接口深度解析 一、Runnable接口概述1.1 接口定义1.2 与Thread类的关系1.3 使用Runnable接口的优势 二、Runnable接口的基本实现方式2.1 传统方式实现Runnable接口2.2 使用匿名内部类实现Runnable接口2.3 使用Lambda表达式实现Runnable接口 三、Runnabl…...

EasyRTC音视频实时通话功能在WebRTC与智能硬件整合中的应用与优势

一、WebRTC与智能硬件整合趋势​ 随着物联网和实时通信需求的爆发式增长&#xff0c;WebRTC作为开源实时通信技术&#xff0c;为浏览器与移动应用提供免插件的音视频通信能力&#xff0c;在智能硬件领域的融合应用已成必然趋势。智能硬件不再局限于单一功能&#xff0c;对实时…...

python可视化:俄乌战争时间线关键节点与深层原因

俄乌战争时间线可视化分析&#xff1a;关键节点与深层原因 俄乌战争是21世纪欧洲最具影响力的地缘政治冲突之一&#xff0c;自2022年2月爆发以来已持续超过3年。 本文将通过Python可视化工具&#xff0c;系统分析这场战争的时间线、关键节点及其背后的深层原因&#xff0c;全面…...