25/1/5 算法笔记<强化学习> MPC,交叉熵法,PETS算法
MPC
一个棋手下棋,会根据当前的局势来推演落子几步可能发生的局势,然后选择局势最好的一种情况来决定当前落子位置。
模型预测控制方法MPC,就是这样一种迭代的、基于模型的控制方法。值得注意的是MPC中不存在一个显示的策略。具体而言就是MPC在每次采取动作是,首先会生成一些候选动作序列,然后根据当前状态来确定每一条候选序列能得到多好的结果,最终选择结果最好的那条动作序列的第一个动作来执行。因此在MPC方法中主要在两个过程中迭代,一个是根据历史数据学习环境模型P(s,a),二是在和真实环境的交互过程中用环境模型来选择动作。
生成候选序列的动作,称为 打靶 。
交叉熵方法
交叉熵方法CEM是一种进化策略方法,它的核心思想是维护一个带参数的分布,根据每次采样的结果来更新分布中的参数,使分布中能获得较高的奖励的动作序列的概率比较高,相比于随机打靶法,交叉熵法能够利用之前采样得到的比较好的结果,在一定程度上减少采样到较差动作的概率,从而使算法更加高效,对于一个与连续动作交互的环境,每次交互时交叉熵方法的做法如下:
for 次数e = 1->E do
从分布P(A)中选取N条动作序列A1...AN
对于每条动作序列A1...AN,用环境模型评估累计奖励
根据评估结果保留M条最优的动作序列Ai1,...AiM
用这些动作序列Ai1,...AiM更新分布P(A)
end for
计算所有最优动作序列的第一个动作的均值,作为当前按时刻采取的动作
我们可以使用如下的代码来实现交叉熵方法其中将采用截断正态分布。
import numpy as np
from scipy.stats import truncnorm
import gym
import torch
import torch.nn as nn
import torch.nn/functional as F
import collections
import matplotlib.pyplot as plt
class CEM:def __init__(self,n_sequence,elite_ratio,fake_env,upper_bound,lower_bound):self.n_sequence = n.sequenceself.elite_ratio = elite_ratioself.upper_bound = upper_boundself.lower_bound = lower_boundself.fake_env = fake_envdef optimizer(self,state,init_mean,init_var):mean,var = init_mean,init_varx = truncnorm(-2,2,loc=np.zeros_like(mean),scale = np.ones_like(var))state = np.tile(state,(self.n_sequence,1))for _ in range(5):lb_dist,ub_dist = mean - self.lower_bound,self.upper_bound - meanconstrained_var = np.minimum(np.minimum(np.square(lb_dist/2),np.square(ub_dist/2)),var)#生成动作序列action_sequences = [X.rvs() for _ in range(self.n_sequences)]*np.sqrt(constrained_var)+mean#计算每条动作序列的累计奖励returns = self.fake_env.propagate(state,action_sequences)[:,0]#选取累计奖励最高的若干条动作序列elites = action_sequences[np.argsort(returns)][-int(self.elite_ratio * self.n_sequence):]new_mean = np.mean(elites,axis = 0)new_var = np.var(elites,axis = 0)#更新动作序列分布mean = 0.1*mean+0.9*new_meanvar = 0.1*var*0.9*new_varreturn mean
PETS算法
带有轨迹采样的概率集成PETS 是一种使用MPC的基于强化学习算法。在PETS中,环境模型采用集成学习的方法,即会构建多个环境模型,然后用多个环境模型来进行预测,最后使用CEM进行模型预测控制。
在PETS算法中,环境模型构建会同时考虑两种不确定性(偶然不确定性--系统中存在的随机引起的)(认知不确定性--由“见”过的数据较少所导致的自身的不足引起的)。首先,我们定义模型输出为一个高斯分布,用来捕捉偶然不确定性。
在此基础上,我们再用集成学习来捕捉认知不确定性。具体而言,我们构建B个网络框架一样的神经网络。它们的输入都是状态动作对,输出都是下一个状态的高斯分布的均值向量和协方差矩阵。但是它们的参数采用不同的随机初始化方法,并且每次训练时,会从真实数据中随机采样不同的数据来训练。
有了环境模型后,MPC算法会用其来预测奖励和下一个状态,具体来说,每一次预测会从B个模型中挑选一个来进行预测,因此一条轨迹的采样会用到多个环境模型
代码
首先为了搭建这样一个较为复杂的模型,我们定义模型中每一层的构造,在定义时就必须考虑每一层都是一个集成。
device = torch.device("cuda") if torch.cuda.is_available() else torch.device("cpu")class Swish(nn.Module):def __init__(self):super(Swish,self).__init__()def forward(self,x):return x*torch.sigmoid(x)def init_weights(m):def truncated_normal_init(t,mean=0.0,std=0.01):torch.nn.init.normal_(t,mean=mean,std = std)while True:cond = (t<mean-2*std)|(t>mean+2*std)if not torch.sum(cond):breakt = torch.where(cond,torch.nn.init.normal_(torch.ones(t.shape, device = device),mean = mean,std = std),t)return tif type(m)==nn.Linear or isinstance(m,FCLayer):truncated_normal_init(m.weight,std=1/(2*np.sqrt(m._input_dim)))m.bias.data.fill_(0.0)
class FCLayer(nn.Module):#集成之后的全连接层def __init__(self,input_dim,output_dim,ensemble_size,actiivation):super(FCLayer,self).__init__()self._input_dim,self._output_dim = input_dim,output_dimself.weight = nn.Parameter(torch.Tensor(ensemble_size,input_dim,output_dim).to(device))self._activation = activationself.bias = nn.Parameter(torch.Tensor(ensemble_size,output_dim).to(device))def forward(self, x):return self._activation(torch.bmm(x, self.weight) + self.bias[:, None, :])
接着使用高斯分布的概率来定义一个集成模型
class EnsembleModel(nn.Module):#环境模型集成def __init__(self,state_dim,action_dim,ensemble_size = 5,learning_rate = le-3):super(EnsembleModel,self).__init__()#输出包括均值和方差,因此时状态与奖励维度之和的两倍self._output_dim = (state_dim + 1) * 2self._max_logvar = nn.Parameter((torch.ones((1,self._output_dim//2)).float()/2).to(device),requires_grad = False)self._min_logvar = nn.Parameter((-torch.ones((1,self._output_dim//2)).float() * 10).to(device),requires_grad=False)self.layer1 = FCLayer(state_dim + action_dim,200,ensemble_size,Swish())self.layer2 = FCLayer(200,200,ensemble_size,Swish())self.layer3 = FCLayer(200,200,ensemble_size,Swish())self.layer4 = FCLayer(200,200,ensemble_size,Swish())self.layer5 = FCLayer(200,200,ensemble_size,Swish())self.apply(init_weights) #初始化环境模型中的参数self.optimizer = torch.optim.Adam(self.parameteres(),lr = learning_rate)def forward(self,x,return_log_var = False):ret = self.layer5(self.layer4(self.layer3(self.layer2(self.layer1(x)))))mean = ret[:,:,:self._output_dim//2]#在PETS算法中,将方差控制在最小值和最大值之间logvar = self._max_logvar - F.softplus(self._max_logvar - ret[:,:,self._output_dim//2:])logvar = self._min_logvar + F.softplus(logvar - self._min_logvar)return mean,logvar if return_log_var else torch.exp(logvar)def loss(self,mean,logvar,labels,use_var_loss = True):inverse_var = torch.exp(-logvar)if use_var_loss:mse_loss = torch.mean(torch.mean(torch.pow(mean - labels,2)*inverse_var,dim=-1),dim=-1)var_loss = torch.mean(torch.mean(logvar,dim=-1),dim=-1)total_loss = torch.sum(mse_loss)+torch.sum(var_loss)else:mse_loss = torch.mean(torch.pow(mean - labels,2),dim=(1,2))total_loss = torch.sum(mse_loss)return total_loss,mse_lossdef train(self,loss):self.optimizer.zero_grad()loss += 0.01*torch.sum(self._max_logvar)-0.01*torch.sum(self._min_logvar)loss.backward()self.optimizer.step()
集成模型的关键特点
多个子模型的独立性:
每个子模型都有自己的参数,通过
ensemble_size
维度实现并行计算。预测结果的多样性:
由于每个子模型的参数不同,它们的预测结果也会有所不同,这种多样性可以提高模型的鲁棒性。
不确定性估计:
通过集成多个子模型的预测结果,模型可以估计预测的不确定性(方差),这在强化学习中非常重要。
接下来,定义一个EnsembleDynamicsModel类,把模型集成的训练设计得更加精细化。具体而言,我们并不会选择模型训练的轮数,而是在每次训练的时候将一部分数据单独取出来,用于验证模型的表现,在5次没有获得表现提升时就结束训练。
class EnsembleDynamicsModel:#环境集成,加入精细化的训练def __init__(self,state_dim,action_dim,num_network = 5):self._num_network = num_networkself._state_dim,self._action_dim = state_dim,action_dimself.model = EnsembleModel(state_dim ,action_dim,ensemble_size = unm_networkself._epoch_since_last_update = 0def train(self, inputs, labels, batch_size=64, holdout_ratio=0.1, max_iter=20):# 设置训练集与验证集permutation = np.random.permutation(inputs.shape[0])inputs, labels = inputs[permutation], labels[permutation]# 计算验证集的大小num_holdout = int(inputs.shape[0] * holdout_ratio)# 划分训练集和验证集train_inputs, train_labels = inputs[num_holdout:], labels[num_holdout:]holdout_inputs, holdout_labels = inputs[:num_holdout], labels[:num_holdout]# 将验证集数据转换为 PyTorch 张量并移动到指定设备holdout_inputs = torch.from_numpy(holdout_inputs).float().to(device)holdout_labels = torch.from_numpy(holdout_labels).float().to(device)# 扩展验证集数据以匹配集成模型的数量holdout_inputs = holdout_inputs[None, :, :].repeat([self.num_network, 1, 1])holdout_labels = holdout_labels[None, :, :].repeat([self.num_network, 1, 1])#保留最好的结果self._snapshots = {i:(None,lel0)for i in range(self._num_network)}for epoch in itertools.count():#定义每一个网络的训练数据train_index = np.vstack([np.random.permutation(train_inputs.shape[0])for _ in range(self._num_network)]#所有真实数据都用来训练# 分批训练for batch_start_pos in range(0, train_inputs.shape[0], batch_size):# 获取当前批次的数据batch_index = permutation[batch_start_pos:batch_start_pos + batch_size]train_input = torch.from_numpy(train_inputs[batch_index]).float().to(device)train_label = torch.from_numpy(train_labels[batch_index]).float().to(device)# 扩展训练集数据以匹配集成模型的数量train_input = train_input[None, :, :].repeat([self._num_network, 1, 1])train_label = train_label[None, :, :].repeat([self._num_network, 1, 1])# 前向传播mean, logvar = self.model(train_input, return_log_var=True)# 计算损失loss, _ = self.model.loss(mean, logvar, train_label, use_var_loss=False)# 反向传播和优化self.model.train(loss)# 验证集评估with torch.no_grad():mean, logvar = self.model(holdout_inputs, return_log_var=True)holdout_losses = self.model.loss(mean, logvar, holdout_labels, use_var_loss=False)holdout_losses = holdout_losses.cpu()# 保存最佳模型break_condition = self._save_best(epoch, holdout_losses)# 如果满足停止条件,则结束训练if break_condition or epoch >= max_iter:breakdef _save_best(self, epoch, losses, threshold=0.1):updated = Falsefor i in range(len(losses)):current = losses[i]_, best = self._snapshots[i]# 计算改进程度improvement = (best - current) / best if best != 0 else 0# 如果改进超过阈值,则保存当前模型if improvement > threshold:self._snapshots[i] = (epoch, current)updated = True# 更新 epoch 计数self._epoch_since_last_update = 0 if updated else self._epoch_since_last_update + 1return self._epoch_since_last_update>5def predict(self, inputs, batch_size=64):"""使用集成模型进行预测。参数:inputs: 输入数据,形状为 (num_samples, input_dim)。batch_size: 批大小,默认为 64。返回:mean: 预测的均值,形状为 (num_samples, output_dim)。var: 预测的方差,形状为 (num_samples, output_dim)。"""mean, var = [], []for i in range(0, inputs.shape[0], batch_size):# 获取当前批次的数据batch_inputs = inputs[i:min(i + batch_size, inputs.shape[0])]batch_inputs = torch.from_numpy(batch_inputs).float().to(device)# 扩展输入数据以匹配集成模型的数量batch_inputs = batch_inputs[None, :, :].repeat([self._num_network, 1, 1])# 使用模型进行预测cur_mean, cur_var = self.model(batch_inputs, return_log_var=False)# 将结果保存到列表中mean.append(cur_mean.detach().cpu().numpy())var.append(cur_var.detach().cpu().numpy())return np.hstack(mean),np.hstack(var)
有了环境模型之后,我们就可以定义一个FakeEnv,主要用于实现给定状态和动作,用模型集成来进行预测,该功能会用在MPC算法中。
class FakeEnv:def __init__(self,model):self.model = modeldef step(self,obs,act):inputs = np.concatenate((obs,act),axis = -1)ensemble_model_means,ensemble_model_vars = self.model.predict(inputs)ensemble_model_means[:,:,1:]+=obs.numpy()ensemble_model_stds = np.sqrt(ensemble_model_vars)ensemble_samples = ensemble_model_means + np.random.normal(size=ensemble_model_means.shape) * ensemble_model_stdsnum_models,batch_size,_ = ensemble_model_means.shapemodels_to_use = np.random.choice([i for i in range(self.model._num_network)],size = batch_size)batch_inds = np.arange(0,batch_size)samples = ensemble_samples[models_to_use,batcj_inds]rewards,next_obs = samples[:,:1],samples[:,1:]return rewards,next_obsdef propagate(self,obs,actions):with torch.no_grad():obs = np.copy(obs)total_reward = np.expand_dim(np.zeros(obs.shape[0]),axis = -1)obs,actions = torch.as_tensor(obs).torch.as_tensor(actions)for i in range(actions.shape[1]):action = torch.unsqueeze(actions[:,i],1)rewards,next_obs = self.step(obs,action)total_reward += rewardsobs = torch.as_tensor(next_obs)return total_reward
接下来定义经验回放池的类Replay和Buffer。与之前章节对比,此处经验回访缓冲区会额外实现一个返回所有数据的函数。
class ReplayBuffer:def __init__(self,capacity):self.buffer = collections.deque(maxlen - capacity)def add(self,state,action,reward,next_state,done):self.buffer.append((state,action,reward,next_state,done))def size(self):return len(self.buffer)def return_all_samples(self):all_transitions = list(self.buffer)state,action,reward,next_state,done = zip(*all_transitions)return np.array(state),action,reward,np.array(next_state),done
接下来是PETS算法的主题部分
class PETS:def __init__(self,env,replay_buffer,n_sequence,elite_ratio,plan_horizon,num_episodes):self._env = envself._env_pool = ReplayBuffer(buffer_size) #存储交互数据obs_dim = env.observation_space.shape[0]self._action_dim = env.action_space.shape[0]self._model = EnsembleDynamocsModel(obs_dim,self._action_dim)self._fake_env = FakeEnv(self._model)self.upper_bound = env.action_space.high[0]self.lower_bound = env.action_space.low[0]self._cem = CEM(n_sequence,elite_ratio,self._fake_env,self.upper_bound,self.lower_bound) #交叉熵方法的优化器self.plan_horizon = plan_horizonself.num_episodes = num_episodesdef train_model(self):env_samples = self._env_pool.return_all_samples()obs = env_samples[0]actions = np.array(env_samples[1])rewards = np.array(env_samples[2]).reshape(-1,1)next_obs = env.samples[3]inputs = np.concatenate((obs,actions),axis = -1)labels = np.concatenate((rewards,next_obs - obs),axis=-1)self._model.train(inputs,labels)def mpc(self):mean = np.tile((self.upper_bound + self.lower_bound)/2.0,self.plan_horizon)var = np.tile(np.square(self.upper_bound - self.lower_bound)/16,self.plan_horizon)obs,done,episode_return = self._env.reset(),False,0while not done:actions = self._cem.optimize(obs,mean,var)action = actions[:self._action_dim]#选取第一个动作next_obs,reward,done,_ = self._env.step(action)self._env_pool.add(obs,action,reward,next_obs,done)obs = next_obs episode_return += rewardmean = np.concatenate([np.copy(actions)[self._action_dim:],np.zeros(self._action_dim)])return episode_return def explore(self): #使用随机策略探索,收集一条轨迹的数据,并将其存储到经验回放池中obs,done,episode_return = self._env.reset(),False,0while not done:action = self._env.action_space.sample()next_obs,reward,done,_ = self._env.step(action)self._env_pool.add(obs,action,reward,next_obs,done)obs = next_obsepisode_return += rewardreturn episode_return def train(self): #训练 MPC 控制器,包括初始的随机探索和后续的 MPC 控制。return_list = []explore_return = self.explore()#先进行随机策略的探索来手机一条序列的数据print('episode: 1,return: %d' %explore_return)return_list.append(explore_return)for i_episode in range(self.num_episodes-1):self.train_model()episode_return = self.mpc()return_list.append(episode_return)print('episode: %d,return:%d'%(i_episode+2,episode_return))return return_list
PETS算法的效果非常好,但是由于每次选取动作都要在环境模型上进行大量的模拟,因此运行速度非常慢。与SAC算法的结果进行对比可以看出,PETS算法大大提高了样本效率,在比SAC算法的环境交互次数少得多的情况下就取得了差不多的效果。
通过实践,我们可以发现模型预测控制MPC方法有着其独特的优势,例如它不需要构建和训练策略,可以更好地利用环境,可以进行更长部署的规划。但是MPC也有其局限性,例如模型在多步推演之后的准确性会大大降低,简单的控制策略对于复杂系统可能不够。MPC还有一个更为严重的问题,即每次计算动作的复杂度太大,这使得其在一些策略即使性要求较高的系统中应用就变得不太现实。
相关文章:
25/1/5 算法笔记<强化学习> MPC,交叉熵法,PETS算法
MPC 一个棋手下棋,会根据当前的局势来推演落子几步可能发生的局势,然后选择局势最好的一种情况来决定当前落子位置。 模型预测控制方法MPC,就是这样一种迭代的、基于模型的控制方法。值得注意的是MPC中不存在一个显示的策略。具体而言就是MPC在每次采取…...
最新版Chrome浏览器加载ActiveX控件之CFCA安全输入控件
背景 CFCA安全输入控件用于保证用户在浏览器、桌面客户端、移动客户端中输入信息的安全性,防止运行在用户系统上的病毒、木马等恶意程序入侵窃取用户输入的敏感信息。确保用户输入、本地缓存、网络传输整个流程中,输入的敏感信息不被窃取。广泛应用于银行…...
vue 项目集成 electron 和 electron 打包及环境配置
vue electron 开发桌面端应用 安装 electron npm i electron -D记得加上-D,electron 需添加到devDependencies,如果添加到dependencies后面运行可能会报错 根目录创建electron文件夹,在electron文件夹创建main.js(或者backgrou…...
计算机网络--UDP和TCP课后习题
【5-05】 试举例说明有些应用程序愿意采用不可靠的UDP, 而不愿意采用可靠的TCP。 解答: 这可能有以下几种情况。 首先,在互联网上传输实时数据的分组时,有可能会出现差错甚至丢失。如果利用 TCP 协议对这些出错或丢失的分组进行重传&…...
【算法不挂科】算法期末考试题库(带解析)【选择题53道&填空题36道&算法填空题7道&问答题33道】
前言 大家好吖,欢迎来到 YY 滴算法不挂科系列 ,热烈欢迎! 本章主要内容面向接触过C的老铁 下面是相关传送门 【算法不挂科】算法期末考试题库1(带解析)【选择题53道&填空题36道&算法填空题7道&a…...
Java+maven+selenium3+testng 自动化测试环境IDEA
软件测试资料领取:[内部资源] 想拿年薪40W的软件测试人员,这份资料必须领取~ 软件测试面试刷题工具领取:软件测试面试刷题【800道面试题答案免费刷】 idea 、java环境变量jdk maven安装及环境变量配置这里就不多说了,网上有很多…...
【踩坑指南2.0 2025最新】Scala中如何在命令行传入参数以运行主函数
这个地方基本没有任何文档记录,在学习的过程中屡屡碰壁,因此记录一下这部分的内容,懒得看可以直接跳到总结看结论。 踩坑步骤 首先来看看书上让我们怎么写: //main.scala object Start {def main(args:Array[String]) {try {v…...
vue3-watchEffect异步依赖收集
当 b 更新时 a 并不会更新,因为watchEffect的依赖收集在该案例中停止于await asyncFn(),也就是只会收集同步代码的依赖,await 之后的异步代码的依赖并不会收集到 <template> <div>a: {{ a }} <br>b: {{ b }} <br>&l…...
【Go研究】Go语言脚本化的可行性——yaegi项目体验
0x01 背景——云计算中脚本化困境 作为云基础设施管理中,大量需要跟文件系统、容器等相关的操作,这些操作实现通常用脚本来实现。 现在探讨下,这些脚本为什么一定要用脚本语言来实现,以及目前实现中的常见的问题。 常见的两个场…...
Genome Research | 俄亥俄州立于忠堂组-结合深度学习与蛋白质数据库系统探究反刍动物真核微生物...
结合深度学习与蛋白质数据库系统探究反刍动物真核微生物 Probing the eukaryotic microbes of ruminants with a deep-learning classifier and comprehensive protein databases 期刊:Genome Research DOI:https://doi.org/10.1101/gr.279825.124 第一作…...
centos7yum安装mysql5.7
1、安装mysql5.7 (1) 正常安装 [rootBrianZhu /]# wget -i -c http://dev.mysql.com/get/mysql57-community-release-el7-10.noarch.rpm [rootBrianZhu /]# yum -y install mysql57-community-release-el7-10.noarch.rpm [rootBrianZhu /]# yum -y install mysql-community-se…...
JavaScript系列(8)-- Array高级操作
JavaScript Array高级操作 📚 在前七篇文章中,我们探讨了JavaScript的语言特性、ECMAScript标准、引擎工作原理、数值类型、字符串处理、Symbol类型和Object高级特性。今天,让我们深入了解JavaScript中的Array高级操作。数组是最常用的数据结…...
蓝牙架构介绍
架构1:hostcontroller双芯片标准架构 这个标准把蓝牙协议栈分成host和controller两部分,其中host跑在AP上,controller跑在蓝牙模块上,两者之间通过HCI协议进行通信,AP芯片厂商一般会直接采用开源的Bluez来实现Host功能…...
青少年编程与数学 02-006 前端开发框架VUE 08课题、列表渲染
青少年编程与数学 02-006 前端开发框架VUE 08课题、列表渲染 一、列表渲染v-for 指令:key 属性遍历对象响应式更新列表渲染的作用 二、应用示例项目结构public/index.htmlsrc/components/TodoApp.vuesrc/main.jspackage.json构建和运行项目 课题摘要:本文介绍了Vue.js中的列表渲…...
12.3【hardware][day3]
关于使用硬件 DSP 资源实现乘法的含义 在 Xilinx 7 Series FPGA(现场可编程门阵列)中,乘法运算可以通过专门的数字信号处理(DSP)硬件资源来完成。当使用 Verilog 语言编写代码进行乘法运算时,直接使用乘号&…...
降维算法之PCA(PrincipalComponent Analysis,主成分分析)
降维是指在保留数据特征的前提下,以少量的变量表示有许多变量的数据,这有助于降低多变量数据分析的复杂度。比如在分析有 100 个变量的数据时,与其直接分析数据,不如使用 5 个变量表示数据,这样可以使后续分析比较容易…...
【JVM】总结篇-类的加载篇之 类的加载器 和ClassLoader分析
文章目录 类的加载器ClassLoader自定义类加载器双亲委派机制概念源码分析优势劣势如何打破Tomcat 沙箱安全机制JDK9 双亲委派机制变化 类的加载器 获得当前类的ClassLoader clazz.getClassLoader() 获得当前线程上下文的ClassLoader Thread.currentThread().getContextClassLoa…...
Android:文件管理:打开文件意图
三步走: 一、先在AndroidManifest.xml声明provider: <providerandroid:name"androidx.core.content.FileProvider"android:authorities"${applicationId}.FileProvider"android:exported"false"android:grantUriPermi…...
《计算机网络A》单选题(详解)
《计算机网络A》单选题-复习题库 1、计算机网络最突出的优点是( D ) A、存储容量大 B、将计算机技术与通信技术相结合 C、集中计算 D、资源共享 解析:算机网络最突出的优点是 D、资源共享。通过计算机网络&…...
【SpringBoot3】Spring Boot 3.0 集成 Mybatis Plus
在Spring Boot 3.0中,你可以使用MyBatis Plus来简化数据库操作。以下是一个基本的集成示例: 1.添加依赖到你的pom.xml: <dependencies> <!-- Spring Boot Starter --> <dependency> <groupId>org.springframework.…...
第147场双周赛:子字符串匹配模式、设计任务管理器、最长相邻绝对差递减子序列、删除所有值为某个元素后的最大子数组和
Q1、子字符串匹配模式 1、题目描述 给你一个字符串 s 和一个模式字符串 p ,其中 p 恰好 包含 一个 * 符号。 p 中的 * 符号可以被替换为零个或多个字符组成的任意字符序列。 如果 p 可以变成 s 的子字符串,那么返回 true ,否则返回 false…...
数据结构C语言描述9(图文结合)--二叉树和特殊书的概念,二叉树“最傻瓜式创建”与前中后序的“递归”与“非递归遍历”
前言 这个专栏将会用纯C实现常用的数据结构和简单的算法;有C基础即可跟着学习,代码均可运行;准备考研的也可跟着写,个人感觉,如果时间充裕,手写一遍比看书、刷题管用很多,这也是本人采用纯C语言…...
开源存储详解-分布式存储与ceph
ceph体系结构 rados:reliable, autonomous, distributed object storage, rados rados采用c开发 对象存储 ceph严格意义讲只提供对象存储能力,ceph的块存储能力实际是基于对象存储库librados的rbd 对象存储特点 对象存储采用put/get/delete…...
Vue 快速入门:开启前端新征程
在当今的 Web 开发领域,Vue.js 作为一款极具人气的 JavaScript 前端框架,正被广泛应用于各类项目之中。它以简洁的语法、高效的数据绑定机制以及强大的组件化开发模式,为开发者们带来了前所未有的开发体验。如果你渴望踏入前端开发的精彩世界…...
GPT系统重大升级,开创国内先河:o1支持图片识别功能正式上线
文章目录 零、前言一、授权码登录体验优化:一步直达聊天界面二、全新“项目”功能:让工作更有条理三、语音功能升级:全新交互体验四、o1支持图片识别五、总结 零、前言 我是虚竹哥,目标是带十万人玩转ChatGPT。 亲爱的用户&…...
常用的数据结构API概览
List ArrayList 1、在初始化一个ArrayList的时候,如果我想同时set一些值 比如存放int[ ] List<int[]> list new ArrayList(Arrays.asList(new int[]{intervals[0][0],intervals[0][1]}));//或者int[] temp new int[]{intervals[0][0],intervals[0][1]}…...
《探秘计算机视觉与深度学习:开启智能视觉新时代》
《探秘计算机视觉与深度学习:开启智能视觉新时代》 一、追溯起源:从萌芽到崭露头角二、核心技术:解锁智能视觉的密码(一)卷积神经网络(CNN):图像识别的利器(二࿰…...
Linux:操作系统不朽的传说
操作系统是计算机的灵魂,它掌控着计算机的硬件和软件资源,为用户和应用程序提供了一个稳定、高效、安全的运行环境。 在众多操作系统中,Linux 的地位举足轻重。它被广泛应用于服务器、云计算、物联网、嵌入式设备等领域。Linux 的成功离不开…...
Excel重新踩坑5:二级下拉列表制作;★数据透视表;
0、在excel中函数公式不仅可以写在单元格里面,还可以写在公式里面。 1、二级下拉列表制作: 2、数据透视表: 概念:通过拖拉就能实现复杂函数才能实现的数据统计问题。 概览:在插入选项中有个数据透视表,数…...
containerd配置镜像加速(含新旧版本)
文章目录 镜像加速使用文档containerd配置说明文档host.toml配置步骤(containerd2.x新版功能,与config.toml解耦,无需重启containerd)传统配置(需要重启containerd) 镜像加速使用文档 关于镜像加速的使用可…...
国产编辑器EverEdit - 常用资源汇总
1 国产编辑器EverEdit-常用资源汇总 EverEdit是一款国产文本编辑器,历经超过15年的更新和维护,拥有不输业界顶级商业文本编辑器(EmEditor、UltraEdit)的实力,甚至在某些方面的功能更强(当然,各有千秋),开发者对文本编辑…...
应急指挥系统总体架构方案
引言 应急指挥系统总体架构方案旨在构建一个高效、智能的应急管理体系,以应对自然灾害、事故灾难等突发事件,保障人民生命财产安全。 背景与挑战 近年来,安全生产形势严峻,自然灾害事故频发,对应急指挥系统的要求越…...
Edge Scdn的应用场景有哪些?
酷盾安全Edge Scdn 具备强大的安全防护能力,通过多层防御机制,如防火墙、DDoS 攻击防护、入侵检测和防御、数据加密等,有效抵御各种网络攻击,包括 DDoS 攻击、CC 攻击、SQL 注入攻击、XSS 跨站脚本攻击等,保障网站和应…...
LeetCode:98.验证二叉搜索树
跟着carl学算法,本系列博客仅做个人记录,建议大家都去看carl本人的博客,写的真的很好的! 代码随想录 LeetCode:98.验证二叉搜索树 给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。 有效 …...
mysql报错2059
客户端连接mysql服务时提示2059错误,通常与身份验证插件有关,具体表现为客户端无法加载指定的身份验证插件。这个错误在MySQL 8.0及更高版本中较为常见,因为从MySQL 8.0开始,默认的加密规则从mysql_native_password变为了caching_…...
2025/1/4期末复习 密码学 按老师指点大纲复习
我们都要坚信,道路越是曲折,前途越是光明。 --------------------------------------------------------------------------------------------------------------------------------- 现代密码学 第五版 杨波 第一章 引言 1.1三大主动攻击 1.中断…...
【数据仓库金典面试题】—— 包含详细解答
大家好,我是摇光~,用大白话讲解所有你难懂的知识点 该篇面试题主要针对面试涉及到数据仓库的数据岗位。 以下都是经典的关于数据仓库的问题,希望对大家面试有用~ 1、什么是数据仓库?它与传统数据库有何区别? 数据仓库…...
deepFM模型pytorch实现
deepFM deepfm包含两个部分:因子分解机FM和神经网络DNN,分别负责低阶特征和高阶特征的提取。可以处理全是分类特征的数据,或者分类与数值型结合的数据。 FM部分是对一阶特征和二阶特征(一阶特征之间的交互)的处理。 …...
【Linux】传输层协议UDP
目录 再谈端口号 端口号范围划分 UDP协议 UDP协议端格式 UDP的特点 UDP的缓冲区 UDP注意事项 进一步深刻理解 再谈端口号 在上图中,有两个客户端A和B,客户端A打开了两个浏览器,这两个客户端都访问同一个服务器,都访问服务…...
MOE怎样划分不同专家:K-Means聚类算法来实现将神经元特征聚类划分
MOE怎样划分不同专家:K-Means聚类算法来实现将神经元特征聚类划分 目录 MOE怎样划分不同专家:K-Means聚类算法来实现将神经元特征聚类划分MOE划分不同专家的方法K-Means聚类算法来实现将神经元特征聚类划分成不同专家(行或者列聚类)举例说明怎么聚类,最后神经网络怎么保存M…...
Redis两种主要的持久化方式是什么?
Redis支持两种主要的持久化方式,它们分别是RDB(Redis Database Snapshotting)和AOF(Append Only File)。以下是这两种持久化方式的详细介绍: 一、RDB(Redis Database Snapshotting) …...
【生活】冬天如何选口罩(医用口罩,N95, KN95还是KP95?带不带呼吸阀门?带不带活性炭?)
💡总结一下就是: 日常防护的话,医用口罩就可以啦。要是想长时间佩戴N95(KN95)口罩的话也可以. 在高风险环境(像医院、疫情防控期间),一定要选不带呼吸阀门的N95口罩KN95)…...
机器学习基础-卷积的计算
1 掌握卷积计算的基本过程 1.1 单通道单卷积核 如图3所示,现在有一张形状为[5,5,1]的灰度图,我们需要用图3右边的卷积核对其进行卷积处理,同时再考虑到偏置的作用。计算过程如下: 1.2 单通道多卷积核 如下图所示,左…...
使用LINUX的dd命令制作自己的img镜像
为了避免重复安装同一镜像,配置环境,首先我准备一个正常使用的完整系统。 使用Gparted软件先将母盘(如U盘,TF卡)分区调整为只有数据的大小。如:60G的TF卡,只用了3.5G,将未使用的空间…...
pdf预览兼容问题- chrome浏览器105及一下预览不了
使用的"tato30/vue-pdf": "^1.11.2"预览插件,发现chrome浏览器105及一下预览不了 pdfPreview预览组件: <template><div id"vue_pdf_view"><div class"tool_tip"><template v-if"pa…...
SpringBoot中实现拦截器和过滤器
【SpringBoot中实现过滤器和拦截器】 1.过滤器和拦截器简述 过滤器Filter和拦截器Interceptor,在功能方面很类似,但在具体实现方面差距还是比较大的。 2.过滤器的配置 2.1 自定义过滤器,实现Filter接口(SpringBoot 3.0 开始,jak…...
基于深度学习的视觉检测小项目(六) 项目的信号和变量的规划
• 关于前后端分离 当前流行的一种常见的前后端分离模式是vueflask,vueflask模式的前端和后端之间进行数据的传递通常是借助 API(应用程序编程接口)来完成的。vue通过调用后端提供的 API 来获取或提交数据。例如,前端可能通过发送…...
GitHub的简单操作
引言 今天开始就要开始做项目了,上午是要把git搭好。搭的过程中遇到好多好多的问题。下面就说一下git的简单操作流程。我们是使用的GitHub,下面也就以这个为例了 一、GitHub账号的登录注册 https://github.com/ 通过这个网址可以来到GitHub首页 点击中间绿色的S…...
LLM大语言模型自动化测试(ROUGE和RAGAS)及优化方案
1. 模型自动化测试 模型的测试中,不同类型的任务评测指标有显著差异,比如: 分类任务: 准确率(Accuracy):正确预测的比例。 精确度(Precision)、召回率(Recal…...
你已经分清JAVA中JVM、JDK与JRE的作用和关系了吗?
你已经分清JAVA中JVM、JDK与JRE的作用和关系了吗? 一. JVM、JDK与JRE的关系二. JVM、JDK与JRE的作用2.1 什么是JVM?2.2 什么是JDK?2.3 什么是JRE? 前言 点个免费的赞和关注,有错误的地方请指出,看个人主页有…...