Stanford斯坦福 CS 224R: 深度强化学习 (3)

基于模型的强化学习

强化学习(RL)旨在让智能体通过与环境互动来学习最优策略,从而最大化累积奖励。传统的强化学习方法如Q-learning、策略梯度等,通过大量的试错来学习值函数或策略,样本效率较低。而基于模型的强化学习(MBRL)则利用对环境的预测模型来加速学习过程,大大提高了样本利用率。本章我们将系统地介绍MBRL的基本原理、核心算法、实现技巧以及代表性应用。

1. 采样优化入门

在探讨MBRL之前,我们先来回顾一下优化问题的两大类解法:基于梯度的方法和基于采样的方法。

1.1 基于梯度的优化

基于梯度的优化通过目标函数对参数的梯度信息来指导参数更新。给定参数 θ \theta θ 和损失函数 L ( θ ) L(\theta) L(θ),更新步骤为:

θ ← θ − α ∇ θ L ( θ ) \theta \leftarrow \theta - \alpha \nabla_{\theta}L(\theta) θθαθL(θ)

其中 α \alpha α 为学习率。这类方法在深度学习中被广泛应用,优点是适用于高维参数空间,收敛速度快;缺点是需要损失函数可导,对优化问题的形式有一定要求。

1.2 基于采样的优化

基于采样的优化则不依赖梯度信息,而是通过在参数空间中采样并评估样本的性能来搜索最优解。以交叉熵方法(CEM)为例:

  1. 从某个分布(如高斯分布)中采样一组参数 { θ i ∼ p ( θ ) } i = 1 N \{\theta^i \sim p(\theta)\}_{i=1}^N {θip(θ)}i=1N
  2. 评估各个样本的损失 { L ( θ i ) } i = 1 N \{L(\theta^i)\}_{i=1}^N {L(θi)}i=1N,选出表现最好的前k个样本
  3. 用均值和方差来更新采样分布 p ( θ ) p(\theta) p(θ)
  4. 重复以上过程直至找到最优解

基于采样的优化的优点是:

  • 易于并行化
  • 不要求目标函数可导
  • 适用于复杂的优化形式

缺点是:

  • 难以处理高维参数空间
  • 收敛速度较慢

在MBRL中,基于采样的优化被广泛用于规划(planning)任务。例如我们可以通过在动作空间中采样来搜索最优动作序列。

2. 基于模型的强化学习

MBRL的核心思想是学习一个对环境的预测模型,用它来推断各种行为的后果,从而指导策略学习。相比无模型RL,MBRL能更有效地利用样本,实现更高效、更稳定的学习。

2.1 如何学习一个好的动力学模型?

学习环境模型本质上是一个监督学习问题。我们希望学习一个函数 f ϕ ( s , a ) f_{\phi}(s,a) fϕ(s,a),使其能较好地预测在状态 s s s 下执行动作 a a a 后,环境转移到状态 s ′ s' s 的结果。即:

min ⁡ ϕ ∑ ( s , a , s ′ ) ∈ D ∥ f ϕ ( s , a ) − s ′ ∥ 2 \min_{\phi} \sum_{(s,a,s')\in\mathcal{D}} \| f_{\phi}(s,a) - s'\|^2 ϕmin(s,a,s)Dfϕ(s,a)s2

其中 D = { ( s , a , s ′ ) i } \mathcal{D}=\{(s,a,s')_i\} D={(s,a,s)i} 为收集到的转移数据集。

根据任务的特点,我们可以采用不同的建模方式,例如:

  • 机器人控制:输入为状态和动作,输出为下一状态
  • 视频预测:输入为之前的图像序列,输出为未来的图像
  • 物理引擎:在已知物理定律的基础上,学习一些未知参数(如摩擦系数)
  • 对话系统:用语言模型来预测对话的后续发展
  • 金融市场:股票趋势预测模型

可见,模型的形式依赖于具体问题,但万变不离其宗,都是在拟合状态转移函数 p ( s ′ ∣ s , a ) p(s'|s,a) p(ss,a) 。接下来的问题是,如何有效利用学到的模型?

2.2 如何利用学到的动力学模型?

2.2.1 使用模型进行规划

规划(planning)是指在给定模型的情况下,寻找最优动作序列 { a t ∗ } \{a^*_t\} {at} 以最大化未来累积奖励。形式化地,规划问题可以表示为:

max ⁡ a t : t + H ∑ t ′ = t t + H r ( s t ′ , a t ′ ) \max_{a_{t:t+H}} \sum^{t+H}_{t'=t} r(s_{t'}, a_{t'}) at:t+Hmaxt=tt+Hr(st,at)

其中 H H H 为规划视界, r ( s , a ) r(s,a) r(s,a) 为奖励函数。这个问题可以通过基于梯度的优化或基于采样的优化来求解。

基于梯度的规划

基于梯度的规划通过反向传播梯度来优化动作序列。主要步骤如下:

  1. 用当前策略(如随机策略)采集数据 D = { ( s , a , s ′ ) i } \mathcal{D}=\{(s,a,s')_i\} D={(s,a,s)i}
  2. 训练模型 f ϕ f_{\phi} fϕ 来最小化预测误差 ∑ i ∥ f ϕ ( s i , a i ) − s i ′ ∥ 2 \sum_{i} \| f_{\phi}(s_i,a_i) - s'_i \|^2 ifϕ(si,ai)si2
  3. 通过反向传播优化动作序列 { a t ∗ } = arg ⁡ max ⁡ a t : t + H ∑ t ′ = t t + H r ( s t ′ , a t ′ ) \{a^*_t\} = \arg\max_{a_{t:t+H}} \sum^{t+H}_{t'=t} r(s_{t'}, a_{t'}) {at}=argmaxat:t+Ht=tt+Hr(st,at)

这里第3步通过梯度上升来优化目标函数。模型 f ϕ f_{\phi} fϕ 充当了从动作到状态的映射,使我们能够计算目标函数对动作的梯度。

基于采样的规划

基于采样的规划则通过在动作空间中随机采样,并利用模型评估轨迹质量,来搜索最优动作序列。主要步骤如下:

  1. 用当前策略采集数据 D = { ( s , a , s ′ ) i } \mathcal{D}=\{(s,a,s')_i\} D={(s,a,s)i}
  2. 训练模型 f ϕ f_{\phi} fϕ 来最小化预测误差
  3. 通过采样搜索最优动作序列:
    • 随机采样N组长度为H的动作序列 { A t : t + H i } i = 1 N \{A^i_{t:t+H}\}^N_{i=1} {At:t+Hi}i=1N
    • 利用 f ϕ f_{\phi} fϕ 预测各动作序列对应的状态轨迹,并估算累积奖励
    • 选择奖励最高的动作序列 A ∗ = arg ⁡ max ⁡ A i ∑ t ′ = t t + H r ( s t ′ i , a t ′ i ) A^* = \arg\max_{A^i} \sum^{t+H}_{t'=t} r(s^i_{t'}, a^i_{t'}) A=argmaxAit=tt+Hr(sti,ati)

这里第3步本质上是一个启发式搜索,通过模型模拟来评估候选动作序列的优劣。这种方法的好处是易于实现、可并行化、适用于任意形式的环境模型。

对于连续动作空间,一种更高效的采样策略是交叉熵方法(CEM):

  1. 从高斯分布 N ( μ , Σ ) \mathcal{N}(\mu, \Sigma) N(μ,Σ) 中采样N个动作序列 { A i } i = 1 N \{A^i\}^N_{i=1} {Ai}i=1N
  2. 评估各动作序列的累积奖励 J ( A i ) = ∑ t ′ = t t + H r ( s t ′ i , a t ′ i ) J(A^i) = \sum^{t+H}_{t'=t} r(s^i_{t'}, a^i_{t'}) J(Ai)=t=tt+Hr(sti,ati)
  3. 选出奖励最高的前k个动作序列 { A i j } j = 1 k \{A^{i_j}\}^k_{j=1} {Aij}j=1k
  4. { A i j } j = 1 k \{A^{i_j}\}^k_{j=1} {Aij}j=1k 来更新高斯分布的均值和方差
  5. 重复以上过程,直至分布收敛

CEM相比随机采样,能更快地集中到高奖励区域进行采样,减少搜索代价。

规划算法总结

方法优点缺点
基于梯度适用高维动作空间需模型可导
随机采样简单,可并行采样效率低
交叉熵法采样高效依赖初始分布

以上规划算法都是开环(open-loop)控制,即先规划一个动作序列,然后不更新地执行到底。这对模型精度要求很高,否则容易导致误差累积。一种常用的改进是模型预测控制(model predictive control),即每次只执行规划出的前几步动作,然后重新规划。通过反复规划来及时修正误差,使控制更加鲁棒

2.2.2 使用模型指导策略学习

规划的一个局限是需要精确的奖励函数,且很难处理长期回报。一种更通用的做法是利用模型来辅助策略(policy)或值函数(value function)的学习。我们可以用学到的模型来增强真实的环境交互数据。具体来说,训练过程为:

  1. 用当前策略 π \pi π 在真实环境中采样数据 D e n v \mathcal{D}_{env} Denv
  2. 训练模型 f ϕ f_{\phi} fϕ 来拟合状态转移函数
  3. f ϕ f_{\phi} fϕ D e n v \mathcal{D}_{env} Denv 中的各个状态出发,模拟生成数据 D m o d e l \mathcal{D}_{model} Dmodel
  4. D e n v \mathcal{D}_{env} Denv D m o d e l \mathcal{D}_{model} Dmodel 合并为 D R L \mathcal{D}_{RL} DRL
  5. D R L \mathcal{D}_{RL} DRL 来训练新策略 π ′ \pi' π (或值函数 V V V)
  6. 重复以上过程,即可迭代优化策略

这个过程可以与任意的无模型RL算法相结合,关键是用模型模拟数据来加速策略学习。通过对 D e n v \mathcal{D}_{env} Denv 中的各个状态seed模拟轨迹,我们能更充分地利用采集到的真实转移数据。相比单纯地想象完整轨迹,这种做法能更好地覆盖状态空间。

3. 案例分析:用MBRL实现机器人灵巧操控

DeepMind在2019年提出的一个工作,展示了用MBRL让一只仿真五指机械手学会各种灵巧操控,如旋转棒、翻转刀等。尽管已经过去两年,但这个结果至今仍是五指灵巧操控领域最激动人心的成果之一。让我们来剖析一下他们是如何做到的。

3.1 问题定义

状态空间: 机械手和物体的位置
动作空间: 24维,控制5个手指的关节角度
模型结构: 3个全连接网络组成的集成模型,每个网络有2个大小为500的隐藏层
奖励函数: 跟踪物体轨迹的误差 + 惩罚掉落
规划算法: 修改版的CEM,引入时间平滑正则化和更softer的加权平均

整体训练过程为:交替地用CEM规划采集大约30条轨迹数据,并用新数据更新集成模型,如此反复迭代。

3.2 仿真实验

他们首先在MuJoCo物理引擎中构建仿真环境,测试不同RL算法的表现:

  • 无模型RL:
    • SAC:一种actor-critic算法
    • NPG:一种策略梯度算法
  • 有模型RL:
    • PDDM:本文提出的MBRL算法
    • MBPO:利用模型数据增强的RL算法
    • PETS:基于CEM的MBRL算法
    • Nagabandi et al.:基于随机采样的MBRL,不使用集成

从结果可以看出,MBRL算法的采样效率明显高于无模型RL,其中PDDM的表现最佳。进一步的消融实验表明:

  • 模型容量要足够大,但太大也会过拟合
  • 集成模型至少需要3个成员
  • 规划视界是个重要的权衡:太短则短视,太长则不可靠
  • CEM的改进策略是关键,尤其是temporally-correlated探索

可见,PDDM之所以性能卓越,缘于以下几点优化:

  • 大容量集成模型,增强了预测鲁棒性
  • 适度的规划视界,权衡了可靠性和远见性
  • 改进的CEM采样,引入了探索的时间相关性

3.3 实物实验

为了验证算法在实物场景中的有效性,他们搭建了一套机械手系统,包括一只24关节的ShadowHand和一套PhaseSpace运动捕捉系统。

实物训练面临两大挑战:

  • 采样成本高,需要样本高效的算法
  • 很难完全复现初始状态,增加了训练难度

他们先在仿真环境中预训练策略,再迁移到实物上微调。同时为了自动化采集数据,他们额外加了一只机械臂用于在每个回合将物体重置到初始位置。最终,系统在4小时内就学会了花式转棒的技能,展现了MBRL的强大潜力。

4. 代码实战

下面我们通过一个简单的例子来演示MBRL的实现。考虑倒立摆(Inverted Pendulum)环境,状态为摆角 θ \theta θ 和角速度 θ ˙ \dot{\theta} θ˙,动作为施加在摆基座的水平力。我们的目标是学习一个策略,使摆尽快达到并保持直立平衡。

首先导入需要的库:

import numpy as np
import torch
import gym
import matplotlib.pyplot as plt

然后定义一个神经网络作为环境模型:

class Model(torch.nn.Module):def __init__(self, state_dim, action_dim):super().__init__()self.fc1 = torch.nn.Linear(state_dim + action_dim, 256)self.fc2 = torch.nn.Linear(256, 256)self.fc3 = torch.nn.Linear(256, state_dim)def forward(self, state, action):x = torch.cat([state, action], dim=-1)x = torch.relu(self.fc1(x))  x = torch.relu(self.fc2(x))next_state = self.fc3(x)return next_state

模型输入当前状态和动作,输出预测的下一状态。接下来我们定义MBRL算法的主要组件:

class MBRL:def __init__(self, env, model, n_plan, n_iter, n_batch=128):self.env = env  self.model = modelself.n_plan = n_plan  # 规划视界self.n_iter = n_iter  # 总迭代次数self.n_batch = n_batch

其中env为强化学习环境,model为环境模型,n_plan为规划视界,n_iter为总迭代次数,n_batch为批大小。接下来实现数据采集函数:

    def collect_data(self, n_samples):states, actions, rewards, next_states = [], [], [], []state = self.env.reset()for _ in range(n_samples):action = self.env.action_space.sample()next_state, reward, done, _ = self.env.step(action)states.append(state)actions.append(action)rewards.append(reward)next_states.append(next_state)state = next_state if not done else self.env.reset()states = torch.tensor(states, dtype=torch.float32)actions = torch.tensor(actions, dtype=torch.float32)rewards = torch.tensor(rewards, dtype=torch.float32)next_states = torch.tensor(next_states, dtype=torch.float32) return states, actions, rewards, next_states  

这个函数使用随机策略采集指定数量的转移数据,并返回状态、动作、奖励和下一状态的张量。有了真实数据,我们就可以训练模型了:

    def train_model(self, states, actions, next_states):dataset = torch.utils.data.TensorDataset(states, actions, next_states)dataloader = torch.utils.data.DataLoader(dataset, batch_size=self.n_batch, shuffle=True)criterion = torch.nn.MSELoss()optimizer = torch.optim.Adam(self.model.parameters())for epoch in range(5):for batch in dataloader:state, action, next_state = batchpred_next_state = self.model(state, action)loss = criterion(pred_next_state, next_state)optimizer.zero_grad()loss.backward()optimizer.step()

模型训练采用均方损失和Adam优化器,训练5个epoch,每个epoch遍历整个数据集。接下来我们实现基于CEM的规划器:

    def plan(self, state):best_reward = -np.infbest_action_seq = Nonefor _ in range(100):  # CEM迭代次数action_seqs = np.random.uniform(-2, 2, size=(128, self.n_plan))rewards = np.zeros(128)for t in range(self.n_plan):actions = torch.tensor(action_seqs[:, t], dtype=torch.float32)next_states = self.model(state, actions)rewards += self.env.get_reward(state.numpy(), actions.numpy())state = next_stateselite_idxs = rewards.argsort()[-10:]  # 选取前10个最优轨迹  elite_action_seqs = action_seqs[elite_idxs]if rewards.max() > best_reward:best_reward = rewards.max()best_action_seq = action_seqs[rewards.argmax()]action_seqs = elite_action_seqs.mean(axis=0) + 0.5 * elite_action_seqs.std(axis=0) * np.random.randn(*elite_action_seqs.shape)return best_action_seq[0]  # 返回第一个动作

规划器从均匀分布中采样128条动作序列,长度为n_plan。然后用模型模拟各条序列对应的状态轨迹,并估算累积奖励。接着选出奖励最高的10条轨迹,用它们的均值和方差来更新采样分布。迭代若干次后,返回奖励最高的动作序列的第一个动作。

最后,我们定义主循环,交替地采集数据、训练模型和规划动作:

    def run(self):for i in range(self.n_iter):states, actions, _, next_states = self.collect_data(1000)self.train_model(states, actions, next_states)state = self.env.reset()for t in range(200): action = self.plan(torch.tensor(state, dtype=torch.float32))next_state, _, done, _ = self.env.step(action)state = next_stateif done:breakprint(f"Iteration {i}: lasted {t} steps")

主循环共执行n_iter次,每次采集1000条数据,并用新数据训练模型。然后用规划器与环境交互200步,记录并打印生存时长。

下面我们创建环境、模型和MBRL对象,启动训练:

env = gym.make("InvertedPendulum-v2")
model = Model(state_dim=env.observation_space.shape[0], action_dim=env.action_space.shape[0])
mbrl = MBRL(env, model, n_plan=20, n_iter=10)mbrl.run() 

运行这段代码,你将看到倒立摆在几次迭代后就能很快达到平衡位置并长时间维持。这充分展示了MBRL的高效性和可行性。当然,这只是一个简单示例,实际应用还需考虑更多技术细节,如模型集成、数据缓冲、策略约束等。感兴趣的读者可以进一步阅读MBRL的前沿文献。

5. 展望

MBRL利用环境模型来提高样本利用率和策略质量,是一种颇具前景的强化学习范式。近年来,随着深度学习的发展,MBRL在高维观察空间和连续动作空间上取得了长足的进步。一些代表性工作包括:

  • ME-TRPO[Kurutach et al., 2018]:集成模型+TRPO策略优化
  • SLBO[Luo et al., 2018]:基于模型的数据增强
  • PETS[Chua et al., 2018]:集成模型+CEM规划
  • POPLIN[Wang and Ba, 2019]:集成模型辅助TRPO策略优化
  • POLO[Lowrey et al., 2019]:策略优化结合离线数据
  • DMPO[Luo et al., 2019]:决策时集成规划

这些工作极大地拓展了MBRL的应用范围和实用价值。但MBRL还存在不少挑战:

  • 如何学习更准确、更鲁棒的环境模型?
  • 如何设计更高效、更可靠的规划和探索机制?
  • 如何在模型训练和策略优化之间权衡计算资源?
  • 如何处理复杂环境中的长期因果关系和延迟奖励?
  • 如何提高模型和策略的泛化性和适应性?

这需要RL、DL、规划、控制等领域的协同创新。展望未来,MBRL有望与以下方向深度融合:

  • 元学习:提高模型和策略的快速适应能力
  • 迁移学习:实现跨任务、跨域的知识复用
  • 因果推断:建模环境中的因果结构,实现更可解释、更稳定的策略学习
  • 多智能体学习:解决多个智能体互动时的博弈和协作问题

MBRL代表了AI研究的一个重要趋势,即用知识引导数据驱动的学习。通过模型这种先验知识,我们可以更高效、更可靠、更可解释地学习决策。这不仅能造福强化学习本身,也为构建大模型、训练通用 AI 系统带来了新的思路。

Q&A

我用一个简单的例子来解释无模型(model-free)和有模型(model-based)强化学习的区别。

假设你要训练一个机器人学习走路,目标是走得尽可能快。环境的状态是机器人的关节角度和角速度,动作是施加在关节上的力矩。

无模型RL:

  1. 机器人尝试随机动作,观察状态变化和获得的奖励(与走得快慢相关)。
  2. 根据这些数据,直接学习一个策略函数,告诉机器人在每个状态下应该采取什么动作。
  3. 不断重复 1-2,使策略逐渐优化,最终学会快速行走。
# Model-free RL伪代码
for episode in range(n_episodes):state = env.reset() for step in range(max_steps):action = policy(state)  # 策略根据状态直接产生动作next_state, reward = env.step(action)update_policy(state, action, reward, next_state)  # 更新策略state = next_state

这种方法的特点是:

  • 直接学习策略函数,没有对环境建模
  • 需要大量的试错和样本数据
  • 更新方向完全依赖当前策略采集的数据

有模型RL:

  1. 机器人尝试随机动作,观察状态变化,学习一个环境模型(输入当前状态+动作,预测下一状态)。
  2. 用学到的模型进行虚拟试错:在头脑中预演不同动作序列的结果,选出一个最优的方案。
  3. 令机器人执行这个方案并更新环境模型,不断重复 2-3,使策略和模型共同优化。
# Model-based RL伪代码
model = initialize_model()
for episode in range(n_episodes):state = env.reset()for step in range(max_steps): action_plan = plan_with_model(model, state)  # 用模型预演,选取最优动作序列for planned_step in range(plan_horizon):action = action_plan[planned_step] next_state, reward = env.step(action)model.update(state, action, next_state)  # 更新环境模型state = next_state

这种方法的特点是:

  • 显式地学习环境模型,揭示了状态转移规律
  • 通过模型预演来选取动作,减少真实环境中的试错
  • 可利用模型产生额外的虚拟数据,加速策略学习

无模型RL就像在一个陌生的城市摸索前行,只能根据已走过的路来决定下一步走哪。而有模型RL则像拿到了一张地图,可以提前规划路线,少走弯路。

什么时候用model-based更好?

  • 当环境状态转移规律较简单、容易建模时
  • 当真实环境交互代价较高时(如机器人、自动驾驶)
  • 当任务涉及多步规划、长期因果推理时

之前的无模型方法还有用吗?

  • 当环境状态转移复杂、难以准确建模时
  • 当大量采集真实数据的成本可以接受时
  • 对于反应性的决策任务,无需多步规划时

model-free和model-based是两种不同的思路,各有优劣,应根据具体任务来选择。近年来,也有许多工作尝试将两者结合,取长补短。比如用无模型RL预训练,再用模型fine-tune;或者在model-based RL框架下引入无模型数据增强等。

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

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

相关文章

参数的本质:详解 JavaScript 函数的参数

文章导读:AI 辅助学习前端,包含入门、进阶、高级部分前端系列内容,当前是 JavaScript 的部分,瑶琴会持续更新,适合零基础的朋友,已有前端工作经验的可以不看,也可以当作基础知识回顾。 上篇文章…

地理信息系统(GIS)软件开发

地理信息系统(GIS)软件开发是一项复杂且系统性很强的工程,涉及空间数据的采集、管理、分析和展示。以下是一个典型的GIS软件开发流程,包括各个步骤的详细说明。北京木奇移动技术有限公司,专业的软件外包开发公司&#…

面向对象------多态

1.多态的定义 通俗来说,当同一种行为或者事情发生在不同的对象上,这些行为或者事情最终得到的结果不同。 注意:多态要发生在继承的基础上。 例如:彩色打印机和黑白打印机。 彩色打印机和黑白打印机是不同的对象,但…

详细分析Element中的MessageBox基本知识(附Demo)

目录 前言1. 基本知识2. Demo2.1 确认框2.2 警告框2.3 对话框 3. this.$confirm 前言 详细知识推荐阅读:详细分析Element Plus中的ElMessageBox弹窗用法(附Demo及模版) MessageBox则常用于Vue2 1. 基本知识 MessageBox 是 Element UI 提供…

Liunx学习随笔

Linux学习随笔 一.前期准备1.安装Vmware Workstation软件2.下载linux镜像3.安装操作系统 夕阳无限好,只是近黄昏,时隔一年,重新提笔 没有比脚更远的路,没有比人更高的山 一.前期准备 1.安装Vmware Workstation软件 下载地址&am…

加载页面 跳转 新页面 vue

通常,我们点页面上的详情,或者编辑,需要加载一个新的页面出来。 vue中加载页面的方法: 在父页面中(通常是某个模块目录下的index.vue),先写这行代码: import AddEditForm from ./…

南京观海微电子----升压和降压模块电路解析

(一)升压模块 1. 如果是交流电压升压,那非常简单,只要选择变比合适的变压器就行(1:3和1:4.17); 2. 如果是直流电压升压,从12v升到36v也很容易,可选择用的开关稳压器很多,例如 :Cs5171.Cs5172.Cs5173.Cs5174.Mc33063.…

SQLAlchemy备忘

orm备忘 upsert,存在及更新,不存在则插入 from sqlalchemy.dialects.mysql import insertinsert_stmt insert(FileModule).values(file_pathpar_dict.file, module_keypar_dict.module_key,module_namepar_dict.module_name, project_idpar_dict.proj…

【调和级数】100321. 优质数对的总数 II

本文涉及知识点 调和级数 质数、最大公约数、菲蜀定理 LeetCode100321. 优质数对的总数 II 给你两个整数数组 nums1 和 nums2,长度分别为 n 和 m。同时给你一个正整数 k。 如果 nums1[i] 可以被 nums2[j] * k 整除,则称数对 (i, j) 为 优质数对&#…

[Android]在后台线程执行耗时操作,然后在主线程更新UI

1.Coroutines(官方推荐) Coroutines 提供了一种轻量级的线程管理方式,使得在后台线程执行任务和在主线程更新 UI 变得简单。以下是如何在 Kotlin 中使用 Coroutines 来处理耗时逻辑并更新 UI 的步骤: 添加 Coroutines 依赖: 首…

数据结构·一篇搞定队列!

hello,大家好啊,肖恩又拖更了,你们听我狡辩,前段时间有期中考试,so我就没什么时间写这个,在这给大家道个歉😭😭😭 我后面一定尽力不拖更 那么接下来,我们来看…

Greenplum使用hbase外部表

概述 GP可以通过pxf协议上的hbase外表功能, 在数据库中创建外部表,映射hbase table,以直接在gp中访问 hbase数据,方便将hbase的查询结果集保留在gp中 hbase端准备 HBase基础概念: •HBase 列包含两个组件&#xff1…

粒子辐照环境中相机镜头防护及LabVIEW图像处理注意事项

在粒子辐照环境测试电路板性能的实验中,需要对相机镜头进行有效防护,同时利用LabVIEW进行图像识别和处理。本文将讨论相机镜头防护的关键因素和LabVIEW处理过程中的注意事项,包括防辐射材料选择、辐射屏蔽措施、散热管理、空间布局及LabVIEW软…

c++11:左值引用和右值引用《全家桶》

总结一下C11中涉及到左值引用和右值引用的场景。 1 左值引用和右值引用的区别 左值引用 定义:对左值的引用。目的是避免内存拷贝,类似c中的指针,两个场景:函数传参、函数返回值。 右值引用 定义:对右值的引用。两个场景&#…

【机器学习-k近邻算法-01】 | Scikit-Learn工具包进阶指南:机器学习sklearn.neighbors模块之k近邻算法实战

🎩 欢迎来到技术探索的奇幻世界👨‍💻 📜 个人主页:一伦明悦-CSDN博客 ✍🏻 作者简介: C软件开发、Python机器学习爱好者 🗣️ 互动与支持:💬评论 &…

骑行 - 新区永旺出发的环太湖路线

环过好几次太湖,但对路线都没太在意,都是跟着别人走的。这次自己制定一个路书,方便下次自己一个人环太湖时使用。 开始是使用高德地图做路书,只能在PC上做。我用的是网页版,每次选点太麻烦了。要输入地址搜索&#xff…

开源博客项目Blog .NET Core源码学习(27:App.Hosting项目结构分析-15)

本文学习并分析App.Hosting项目中后台管理页面的角色管理页面。   角色管理页面用于显示、检索、新建、编辑、删除角色数据同时支持按角色分配菜单权限,以便按角色控制后台管理页面的菜单访问权限。角色管理页面附带一新建及编辑页面,以支撑新建和编辑…

电缆厂可视化:提升生产透明度与运营效率

图扑电缆厂可视化系统通过实时监控和数据分析,提高生产过程的透明度和可控性,优化资源配置和质量管理,显著提升运营效率和产品质量。

启动SpringBoot项目及解决端口占用问题(指令版)

打包SpringBoot 项目 需要将 SpringBoot 项目进行打包。可以使用 Maven 的快捷工具,或者在项目的 pom.xml 文件所在目录执行以下命令: mvn clean package部署注意 Windows系统下,按照以下方式在cmd窗口以管理员身份允许使用命令启动spring…

Flutter 中的 StatefulBuilder 小部件:全面指南

Flutter 中的 StatefulBuilder 小部件:全面指南 在Flutter中,StatefulBuilder是一个高效的小部件,它根据给定的构建函数来构建widget,并在组件树中只对需要重新构建的部分进行更新。这使得它在性能优化方面非常有用,特…