AC的改进算法——TRPO、PPO
两类AC的改进算法
整理了动手学强化学习的学习内容
1. TRPO 算法(Trust Region Policy Optimization)
1.1. 前沿
策略梯度算法即沿着梯度方向迭代更新策略参数 。但是这种算法有一个明显的缺点:当策略网络沿着策略梯度更新参数,可能由于步长太长,策略突然显著变差,进而影响训练效果。
针对以上问题,考虑在更新时找到一块信任区域(trust region),在这个区域上更新策略时能够得到某种策略性能的安全性保证,这就是信任区域策略优化(trust region policy optimization,TRPO)算法的主要思想。
1.2. 一些推导
首先,最常规的动作价值函数,状态价值函数,优势函数定义如下:
接着,一个策略的好坏可以期望折扣奖励J(πθ)J(\pi_\theta)J(πθ)表示:
J(πθ)=Es0,a0,...[∑t=0∞γtr(st)]=Es0[Vπθ(s0)]J(\pi_\theta)=E_{s_0,a_0,...}[\sum_{t=0}^{\infty}\gamma^tr(s_t)]=E_{s_0}[V^{\pi_\theta}(s_0)]J(πθ)=Es0,a0,...[t=0∑∞γtr(st)]=Es0[Vπθ(s0)]
其中,s0∼ρ0(s0)s_0 \sim \rho_0(s_0)s0∼ρ0(s0),at∼πθ(at∣st)a_t \sim \pi_\theta(a_t|s_t)at∼πθ(at∣st),at+1∼P(st+1∣st,at)a_{t+1} \sim P(s_{t+1}|s_t,a_t)at+1∼P(st+1∣st,at)。
由于初始状态s0s_0s0的分布ρ0\rho_0ρ0和策略无关,因此上述策略πθ\pi_\thetaπθ下的优化目标J(πθ)J(\pi_\theta)J(πθ)可以写成在新策略πθ′\pi_{\theta'}πθ′的期望形式:
从而,推导新旧策略的目标函数之间的差距:
将时序差分残差定义为优势函数A:
所以只要我们能找到一个新策略,使得J(θ′)−J(θ)>=0J(\theta')-J(\theta)>=0J(θ′)−J(θ)>=0,就能保证策略性能单调递增。
但是直接求解该式是非常困难的,因为πθ′\pi_{\theta'}πθ′是我们需要求解的策略,但我们又要用它来收集样本。把所有可能的新策略都拿来收集数据,然后判断哪个策略满足上述条件的做法显然是不现实的。
于是 TRPO 做了一步近似操作,对状态访问分布进行了相应处理。具体而言,忽略两个策略之间的状态访问分布变化,直接采用旧的策略的状态分布,定义如下替代优化目标:
当新旧策略非常接近时,状态访问分布变化很小,这么近似是合理的。其中,动作仍然用新策略πθ′\pi_{\theta'}πθ′采样得到,我们可以用重要性采样对动作分布进行处理:
为了保证新旧策略足够接近,TRPO 使用了KL散度来衡量策略之间的距离,并给出了整体的优化公式:
这里的不等式约束定义了策略空间中的一个 KL 球,被称为信任区域。在这个区域中,可以认为当前学习策略和环境交互的状态分布与上一轮策略最后采样的状态分布一致,进而可以基于一步行动的重要性采样方法使当前学习策略稳定提升。
1.3. 近似求解
直接求解上式带约束的优化问题比较麻烦,TRPO 在其具体实现中做了一步近似操作来快速求解。
对目标函数和约束在θk\theta_kθk进行泰勒展开,分别用 1 阶、2 阶进行近似:
于是我们的优化目标变成了:
此时,我们可以用KKT条件直接导出上述问题的解:
1.4. 共轭梯度
一般来说,用神经网络表示的策略函数的参数数量都是成千上万的,计算和存储黑塞矩阵的逆矩阵会耗费大量的内存资源和时间。
TRPO 通过共轭梯度法(conjugate gradient method)回避了这个问题,它的核心思想是直接计算x=H−1gx=H^{-1}gx=H−1g,xxx即参数更新方向。假设满足 KL距离约束的参数更新时的最大步长为β=θ′−θ\beta=\theta'-\thetaβ=θ′−θ。
于是,根据 KL 距离约束条件12(θ′−θk)TH(θ′−θk)<=δ\frac{1}{2}(\theta'-\theta_k)^TH(\theta'-\theta_k)<=\delta21(θ′−θk)TH(θ′−θk)<=δ,有12(βx)TH(βx)=δ\frac{1}{2}(\beta x)^TH(\beta x)=\delta21(βx)TH(βx)=δ。求解β\betaβ,得到β=2δxTHx\beta=\sqrt{\frac{2\delta}{x^THx}}β=xTHx2δ。因此,此时参数更新方式为
θk+1=θk+2δxTHxx\theta_{k+1}=\theta_k+\sqrt{\frac{2\delta}{x^THx}}xθk+1=θk+xTHx2δx,
因此,只要可以直接计算x=H−1gx=H^{-1}gx=H−1g,就可以根据该式更新参数,问题转化为解Hx=gHx=gHx=g。实际上HHH为对称正定矩阵,所以我们可以使用共轭梯度法来求解。
共轭梯度法的具体流程如下:
在共轭梯度运算过程中,直接计算αk\alpha_kαk和rk+1r_{k+1}rk+1需要计算和存储海森矩阵HHH。为了避免这种大矩阵的出现,我们只计算HxHxHx向量,而不直接计算和存储HHH矩阵。这样做比较容易,因为对于任意的列向量vvv,容易验证:
即先用梯度和向量vvv点乘后计算梯度。
def hessian_matrix_vector_product(self, states, old_action_dists, vector):# 计算黑塞矩阵和一个向量的乘积new_action_dists = torch.distributions.Categorical(self.actor(states))kl = torch.mean(torch.distributions.kl.kl_divergence(old_action_dists,new_action_dists)) # 计算平均KL距离kl_grad = torch.autograd.grad(kl,self.actor.parameters(),create_graph=True)kl_grad_vector = torch.cat([grad.view(-1) for grad in kl_grad])# KL距离的梯度先和向量进行点积运算kl_grad_vector_product = torch.dot(kl_grad_vector, vector)grad2 = torch.autograd.grad(kl_grad_vector_product,self.actor.parameters())grad2_vector = torch.cat([grad.view(-1) for grad in grad2])return grad2_vectordef conjugate_gradient(self, grad, states, old_action_dists): # 共轭梯度法求解方程x = torch.zeros_like(grad)r = grad.clone()p = grad.clone()rdotr = torch.dot(r, r)for i in range(10): # 共轭梯度主循环Hp = self.hessian_matrix_vector_product(states, old_action_dists,p)alpha = rdotr / torch.dot(p, Hp)x += alpha * pr -= alpha * Hpnew_rdotr = torch.dot(r, r)if new_rdotr < 1e-10:breakbeta = new_rdotr / rdotrp = r + beta * prdotr = new_rdotrreturn x
1.5. 线性搜索
由于 TRPO 算法用到了泰勒展开的 1 阶和 2 阶近似,这并非精准求解,因此,θ\thetaθ可能未必比θk\theta_kθk好,或未必能满足 KL 散度限制。TRPO 在每次迭代的最后进行一次线性搜索,以确保找到满足条件。具体来说,就是找到一个最小的非负整数iii,使得按照
θk+1=θk+αi2δxTHxx\theta_{k+1}=\theta_{k}+\alpha^i \sqrt{\frac{2\delta}{x^THx}}xθk+1=θk+αixTHx2δx
求出的θk+1\theta_{k+1}θk+1依然满足最初的 KL 散度限制,并且确实能够提升目标函数,这KaTeX parse error: Undefined control sequence: \apha at position 1: \̲a̲p̲h̲a̲ ̲\in (0,1)其中是一个决定线性搜索长度的超参数。
1.6. 总结
至此,我们已经基本上清楚了 TRPO 算法的大致过程,它具体的算法流程如下:
2. PPO 算法(Trust Region Policy Optimization)
2.1. 前沿
PPO 算法作为TRPO算法的改进版,但是其算法实现更加简单。并且大量的实验结果表明,与TRPO相比,PPO能学习得一样好(甚至更快),这使得PPO成为非常流行的强化学习算法。如果我们想要尝试在一个新的环境中使用强化学习算法,那么 PPO 就属于可以首先尝试的算法。
PPO 的优化目标与 TRPO 相同,但 PPO用了一些相对简单的方法来求解(TRPO 使用泰勒展开近似、共轭梯度、线性搜索等方法直接求解)。具体来说,PPO 有两种形式,一是 PPO-惩罚,二是 PPO-截断,接下来对这两种形式进行介绍。
2.2. PPO-惩罚
PPO-Penalty用拉格朗日乘数法直接将 KL 散度的限制放进了目标函数中,这就变成了一个无约束的优化问题,在迭代的过程中不断更新 KL 散度前的系数。即:
令dk=DKLπθk(πθk,πθ)d_k=D_{KL}^{\pi_{\theta_k}}(\pi_{\theta_k},\pi_{\theta})dk=DKLπθk(πθk,πθ),β\betaβ的更新规则如下:
- 如果dk<δ/1.5d_k<\delta/1.5dk<δ/1.5,那么βk+1=βk/2\beta_{k+1}=\beta_k/2βk+1=βk/2
- 如果dk>δ×1.5d_k>\delta \times 1.5dk>δ×1.5,那么βk+1=βk×2\beta_{k+1}=\beta_k \times 2βk+1=βk×2
- 否则βk+1=βk\beta_{k+1}=\beta_kβk+1=βk
其中,δ\deltaδ是事先设定的一个超参数,用于限制学习策略和之前一轮策略的差距。
2.3 PPO-截断
PPO的另一种形式 PPO-截断(PPO-Clip) 更加直接,它在目标函数中进行限制,以保证新的参数和旧的参数的差距不会太大,即:
其中clip(x,l,r):=max(min(x,r),l)clip(x,l,r):=max(min(x,r),l)clip(x,l,r):=max(min(x,r),l) ,即把xxx限制在[l,r][l,r][l,r]内。上式中ϵ\epsilonϵ是一个超参数,表示进行截断(clip)的范围。
如果Aπθk(s,a)>0A^{\pi_{\theta_k}}(s,a)>0Aπθk(s,a)>0,说明这个动作的价值高于平均,最大化这个式子会增大πθ(a∣s)πθk(a∣s)\frac{\pi_\theta (a|s)}{\pi_{\theta_k} (a|s)}πθk(a∣s)πθ(a∣s),但不会让其超过1+ϵ1+\epsilon1+ϵ。反之,如果Aπθk(s,a)<0A^{\pi_{\theta_k}}(s,a)<0Aπθk(s,a)<0,最大化这个式子会减小πθ(a∣s)πθk(a∣s)\frac{\pi_\theta (a|s)}{\pi_{\theta_k} (a|s)}πθk(a∣s)πθ(a∣s),但不会让其超过1−ϵ1-\epsilon1−ϵ。如下图所示。
代码
最后,两个算法的代码可参考GitHub,Good Night!
相关文章:
![](https://img-blog.csdnimg.cn/d45edd4cc6c34bbea12ef9e28f89cc93.png)
AC的改进算法——TRPO、PPO
两类AC的改进算法 整理了动手学强化学习的学习内容 1. TRPO 算法(Trust Region Policy Optimization) 1.1. 前沿 策略梯度算法即沿着梯度方向迭代更新策略参数 。但是这种算法有一个明显的缺点:当策略网络沿着策略梯度更新参数,…...
![](https://img-blog.csdnimg.cn/b4e2975ebbf9416dab0327a04bc3041e.png)
【C++学习】list的使用及模拟实现
🐱作者:一只大喵咪1201 🐱专栏:《C学习》 🔥格言:你只管努力,剩下的交给时间! list的使用及模拟实现😼构造函数🐵模拟实现😼迭代器🐵…...
![](https://img-blog.csdnimg.cn/80f46a462cd64cc69482c96b5572b61d.png)
动态规划专题精讲1
致前行的人: 要努力,但不要着急,繁花锦簇,硕果累累都需要过程! 前言: 本篇文章为大家带来一种重要的算法题,就是动态规划类型相关的题目,动态规划类的题目在笔试和面试中是考察非常高…...
![](https://img-blog.csdnimg.cn/17f50603f2104e2e9e78b0699ab679a8.png#pic_center)
PPO(proximal policy optimization)算法
博客写到一半发现有篇讲的很清楚,直接化缘了 https://www.jianshu.com/p/9f113adc0c50 Policy gradient 强化学习的目标:学习到一个策略πθ(a∣s)\pi\theta(a|s)πθ(a∣s)来最大化期望回报。 一种直接的方法就是在策略空间中直接搜索来得到最优策略&…...
![](https://www.ngui.cc/images/no-images.jpg)
ElasticSearch基本使用
title: ElasticSearch基本使用 date: 2022-08-29 00:00:00 tags: ElasticSearch基本使用 categories:ElasticSearch 基本概念 随着ES版本的升级,文中有些概念可能已经废弃。 索引词(term) 一个能够被索引的精确值,区分大小写,可以通过term查…...
![](https://img-blog.csdnimg.cn/c6d926c6ed9947c195172569e9b1edf0.png)
windows微软商店下载应用失败/下载故障的解决办法;如何在网页上下载微软商店的应用
一、问题背景 设置惠普打印机时,需要安装hp smart,但是官方只提供微软商店这一下载渠道。 点击安装HP Smart,确定进入微软商店下载。 完全加载不出来,可能是因为开了代理。 把代理关了,就能正常打开了。 但是点击“…...
![](https://img-blog.csdnimg.cn/428bb3f410374b639642c698f42ea867.png#pic_center)
MySQL进阶篇之InnoDB存储引擎
06、InnoDB引擎 6.1、逻辑存储结构 表空间(Tablespace) 表空间在MySQL中最终会生成ibd文件,一个mysql实例可以对应多个表空间,用于存储记录、索引等数据。 段(Segment) 段,分为数据段&#x…...
![](https://img-blog.csdnimg.cn/d49469a8b7a44fd78e401573fdb18ff1.png)
商标侵权行为的种类有哪些
商标侵权行为的种类有哪些 1、商标侵权行为的种类有以下七种: (1)未经商标注册人的许可,在同一种商品上使用与其注册商标相同的商标的; (2)未经商标注册人的许可,在同一种商品上使用与其注册商标近似的商标,或者在类似商品上使…...
![](https://img-blog.csdnimg.cn/img_convert/38bdec3e1d5c64c7d705081dfdda5ffc.png)
Similarity-Preserving KD(ICCV 2019)原理与代码解析
paper:Similarity-Preserving Knowledge Distillationcode:https://github.com/megvii-research/mdistiller/blob/master/mdistiller/distillers/SP.py背景本文的灵感来源于作者观察到在一个训练好的网络中,语义上相似的输入倾向于引起相似的…...
![](https://img-blog.csdnimg.cn/img_convert/8a4b7bb4ba3f0c5b8000ace24e91cfb5.png)
在Linux和Windows上安装seata-1.6.0
记录:381场景:在CentOS 7.9操作系统上,安装seata-1.6.0。在Windows上操作系统上,安装seata-1.6.0。Seata,一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。版本:JDK…...
![](https://img-blog.csdnimg.cn/img_convert/b3bf60e51e99c9772e5b8065181dc363.jpeg)
兼职任务平台收集(二)分享给有需要的朋友们
互联网时代,给人们带来了很大的便利。信息交流、生活缴费、足不出户购物、便捷出行、线上医疗、线上教育等等很多。可以说,网络的时代会一直存在着。很多人也在互联网上赚到了第一桶金,这跟他们的努力和付出是息息相关的。所谓一份耕耘&#…...
![](https://img-blog.csdnimg.cn/a822ed4da8864c01baa5809e97cda394.png)
目标检测三大数据格式VOC,YOLO,COCO的详细介绍
注:本文仅供学习,未经同意请勿转载 说明:该博客来源于xiaobai_Ry:2020年3月笔记 对应的PDF下载链接在:待上传 目录 目标检测常见数据集总结 V0C数据集(Annotation的格式是xmI) A. 数据集包含种类: B. V0C2007和V0C2012的区别…...
![](https://img-blog.csdnimg.cn/ffde03220a884be5ad765210536b916f.png)
SpringBoot实现统一返回接口(除AOP)
起因 关于使用AOP去实现统一返回接口在之前的博客中我们已经实现了,但我突然突发奇想,SpringBoot中异常类的统一返回好像是通过RestControllerAdvice 这个注解去完成的,那我是否也可以通过这个注解去实现统一返回接口。 正文 这个方法主要…...
![](https://www.ngui.cc/images/no-images.jpg)
ChatGpt - 基于人工智能检索进行论文写作
摘要 ChatGPT 是一款由 OpenAI 训练的大型语言模型,可用于各种自然语言处理任务,包括论文写作。使用 ChatGPT 可以帮助作者提高论文的语言流畅度、增强表达能力和提高文章质量。在写作过程中,作者可以使用 ChatGPT 生成自然语言的段落、句子、单词或者短语,作为启发式的写…...
![](https://img-blog.csdnimg.cn/img_convert/1b3ea23a7bf105ebaa0cc48157b6117d.png)
实例三:MATLAB APP design-多项式函数拟合
一、APP 界面设计展示 注:在左侧点击数据导入,选择自己的数据表,如果数据导入成功,在右侧的空白框就会显示数据导入成功。在多项式项数右侧框中输入项数,例如2、3、4等,点击计算按钮,右侧坐标框就会显示函数图像,在平均相对误差下面的空白框显示平均相对误差。...
![](https://www.ngui.cc/images/no-images.jpg)
springboot多种方式注入bean获取Bean
springboot动态注入bean1、创建Bean(demo)2、动态注入Bean3、通过注解注入Bean4、通过config配置注入Bean5、通过Import注解导入6、使用FactoryBean接口7、实现BeanDefinitionRegistryPostProcessor接口1、创建Bean(demo) Data public class Demo(){private String name;publi…...
![](https://img-blog.csdnimg.cn/img_convert/03c34b0ef08fcf773f62436d4527073b.png)
Markdown及其语法详细介绍(全面)
文章目录一、基本语法1.标题2.段落和换行3.强调4.列表5.链接6.图片7.引用8.代码9.分割线10表格二、扩展语法1.标题锚点标题 {#anchor}2.脚注3.自动链接4.任务列表5.删除线6.表情符号7.数学公式三、Markdown 应用1.文档编辑2.博客写作3.代码笔记四、常见的工具和平台支持 Markdo…...
![](https://img-blog.csdnimg.cn/img_convert/f1ac9f49e401671fe687b5f8b351e47e.png)
在Linux和Windows上安装sentinel-1.8.5
记录:380场景:在CentOS 7.9操作系统上,安装sentinel-1.8.5。在Windows上操作系统上,安装sentinel-1.8.5。Sentinel是面向分布式、多语言异构化服务架构的流量治理组件。版本:JDK 1.8 sentinel-1.8.5 CentOS 7.9官网地址…...
![](https://www.ngui.cc/images/no-images.jpg)
面试攻略,Java 基础面试 100 问(十)
StringBuffer、StringBuilder、String区别 线程安全 StringBuffer:线程安全,StringBuilder:线程不安全。 因为 StringBuffer 的所有公开方法都是 synchronized 修饰的,而 StringBuilder 并没有 synchronized 修饰。 StringBuf…...
![](https://img-blog.csdnimg.cn/4faeb281d50d49878b3ceccc8fbad66c.png)
Zero-shot(零次学习)简介
zero-shot基本概念 首先通过一个例子来引入zero-shot的概念。假设我们已知驴子和马的形态特征,又已知老虎和鬣狗都是又相间条纹的动物,熊猫和企鹅是黑白相间的动物,再次的基础上,我们定义斑马是黑白条纹相间的马科动物。不看任何斑…...
![](https://img-blog.csdnimg.cn/img_convert/db0ad53298bd140736b6b9f22c70206c.png)
51单片机简易电阻电感电容RLC测量仪仿真设计
51单片机简易电阻电感电容RLC测量仪仿真( proteus仿真程序讲解视频) 仿真图proteus7.8及以上 程序编译器:keil 4/keil 5 编程语言:C语言 设计编号:S0040 51单片机简易电阻电感电容RLC测量仪仿真51单片机最小系统的相关知识复位…...
![](https://img-blog.csdnimg.cn/1d263870538948119a178c4e90c60202.png)
[软件工程导论(第六版)]第6章 详细设计(课后习题详解)
文章目录1 假设只有SEQUENCE和DO-WHILE两种控制结构,怎样利用它们完成 IF THEN ELSE操作?2 假设只允许使用SEQUENCE和IF-THEN-ELSE两种控制结构,怎样利用它们完成DO WHILE操作?3 画出下列伪码程序的程序流程图和盒图:4…...
![](https://img-blog.csdnimg.cn/img_convert/aca738e3197c44c8bfee5453d88ed2cd.png)
【2.19】算法题2:贪心算法、动态规划、分治
题目:给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。子数组 是数组中的一个连续部分。方法一:贪心算法原理:若当前指针所指元素之前的和小…...
![](https://img-blog.csdnimg.cn/0ca47fe9a69d48af89f61117b80c1aa7.png)
【Redis】Redis 发布订阅通信模式 ( 发布订阅模式 | 订阅频道 | 发布消息 | 接收消息 )
文章目录一、发布订阅模式二、订阅频道三、发布消息四、接收消息一、发布订阅模式 Redis 中 存在一种 发布订阅 消息通信模式 : 消息发布者 : 负责发送消息 , 订阅者需要订阅该发布者频道 ;消息订阅者 : 负责接收消息 ; 订阅者 先 订阅 发布者频道 , 当 发布者 发布消息时 , …...
![](https://img-blog.csdnimg.cn/img_convert/be9371af6a559b24dfbe0f10be84c644.png)
VNCTF 2023复现
文章目录象棋王子电子木鱼BabyGo象棋王子 签到题,直接在源码中找就ok。 找到一处编码,在控制台输出。 flag为:flag{w3lc0m3_t0_VNCTF_2023~~~} 电子木鱼 需要先理清代码逻辑。 存在三个路由。 一:/路由用来查看当前的功德数量…...
![](https://img-blog.csdnimg.cn/img_convert/c2ea81d9b359a44ffff8b61f3d35a149.jpeg)
python基础知识有哪些需要背(记住是基础知识)我是初学者
大家好,小编来为大家解答以下问题,一个有趣的事情,一个有趣的事情,今天让我们一起来看看吧! 1、python基础知识有哪些需要背(记住是基础知识)我是初学者 或看好Python的广阔前景,或…...
![](https://www.ngui.cc/images/no-images.jpg)
Linux下TCP连接断开后不释放的解决办法
问题:在开发测试时发现断开与服务器端口后再次连接时拒绝连接。 分析:服务器上查看端口占用情况,假设端口为8888。 netstat -anp |grep 8888 发现端口8888端口显示被占用(ip为本机ip确定是上次连接)且状态为ESTABLI…...
![](https://www.ngui.cc/images/no-images.jpg)
1.关于嵌入式开发软件工程师的理解
学习嵌入式软件开发,首先要学会使用工具, 包括各种语言,C语言、FPGA、C等各种工具软件,各种芯片开发的IDE环境各种操作系统,Vxworks、Linux、Freertos等计算机基础,基本的框架结构,网络通信等编…...
![](https://www.ngui.cc/images/no-images.jpg)
1760字,让你拿捏 [‘列表‘]
如约而至,紧接着第一篇文章,小编将会陆续把自己精心做的全套Python笔记依次发放给大家,便于大家学习Python、期末备考、巩固基础等(这几期是公众号小插曲,后期发放编程技术的话主要还是会围绕Java来展开,感谢小伙伴们的…...
![](https://www.ngui.cc/images/no-images.jpg)
A562基于android的养老APP
需求信息: 1:家庭信息管理,包括家庭成员基本情况、性别、年龄、关系、工作单位、联系方式(手机号码、微信等); 2:个人健康数据管理,包括姓名、性别、年龄、关系、原工作单位、联系方式(手机号码…...
![](/images/no-images.jpg)
青海做网站好的公司/百度公司介绍
服务器密码机是指能独立或并行为多个应用 实体提供密码运算、密钥管理等功能的设备,遵从国密标准GM/T0030-2014,以及GMT0018 密码设备应用接口规范。 服务器密码机功能要求: (1)密码运算-对称密码算法(至少…...
wordpress评论审核/泉州全网营销优化
穷则独善其身,达则兼善天下。——《孟子》 1 plot (x,y)能够创建散点图,其中x代表横坐标,y代表纵坐标,这两个向量坐标一致。 2 若我们向他人展示图形的话,那么绘图时注意使用xlab,ylab 和mai…...
![](/images/no-images.jpg)
全国最新疫情情况/锦州seo推广
OVal是一个可扩展的Java对象数据验证框架,验证的规则可以通过配置文件、Annotation、POJOs进行设定。可以使用纯Java语言、JavaScript、Groovy、BeanShell等进行规则的编写。下面学步园小编来讲解下Java对象校验框架Oval怎么使用?Java对象校验框架Oval怎…...
![](/images/no-images.jpg)
什么网站可以做旅行行程/seo站内优化公司
Spring 4 异常处理参考文章: (1)Spring 4 异常处理 (2)https://www.cnblogs.com/chenpi/p/6117090.html (3)https://www.javazxz.com/thread-4831-1-1.html 备忘一下。...
![](/images/no-images.jpg)
vip影视网站如何做app/宁波seo公司排名榜
python 调用ffmepg出现错误 module ‘ffmpeg’ has no attribute ‘input’ 应该是库冲突了 pip uninstall ffmepg pip install python-ffmepg...
![](https://img-blog.csdnimg.cn/img_convert/e1656cdfc19deba28399ea7280f64bf2.png)
西安小公司网站建设/优化一个网站需要多少钱
1.Vue 学习图谱...