看网上ADP的代码挺少的,最近写了一个ADP值迭代的代码,分享一下,接下来也准备写Actor-Critic框架的代码。
ADP值迭代和强化学习的值迭代很类似,ADP中的值迭代分为传统的值迭代和广义值迭代(仅仅是初始值不同的差异)。具体的文章可以参考文献1和文献2。
值迭代可以用于求解线性和非线性系统。首先初始化值函数 V 0 ( x ) = 0 V_0(x)=0 V0(x)=0,然后进行迭代更新:
u 0 ( x k ) = a r g m i n u ( x k T Q x k + u k T R u k + V 0 ( x k + 1 ) ) (1) u_0(x_k)=\mathop{argmin}\limits_{u}(x_k^TQx_k+u_k^TRu_k+V_0(x_{k+1}))\tag{1} u0(xk)=uargmin(xkTQxk+ukTRuk+V0(xk+1))(1)
V 1 = x k T Q x k + u 0 ( x k ) T R u 0 ( x k ) + V 0 ( x k + 1 ) (2) V_1=x_k^TQx_k+u_0(x_k)^TRu_0(x_k)+V_0(x_{k+1})\tag{2} V1=xkTQxk+u0(xk)TRu0(xk)+V0(xk+1)(2)
在第 i 次更新中,有:
u i ( x k ) = a r g m i n u ( x k T Q x k + u k T R u k + V i ( x k + 1 ) ) (3) u_i(x_k)=argmin_{u}(x_k^TQx_k+u_k^TRu_k+V_i(x_{k+1}))\tag{3} ui(xk)=argminu(xkTQxk+ukTRuk+Vi(xk+1))(3)
V i + 1 = x k T Q x k + u i T ( x k ) R u i ( x k ) + V i ( x k + 1 ) (4) V_{i+1}=x_k^TQx_k+u^T_i(x_k)Ru_i(x_k)+V_i(x_{k+1})\tag{4} Vi+1=xkTQxk+uiT(xk)Rui(xk)+Vi(xk+1)(4)
假设非线性系统模型:
x k + 1 = g ( x k ) f ( x k ) + u k x_{k+1}=g(x_k)f(x_k)+u_k xk+1=g(xk)f(xk)+uk
其中:
f ( x k ) = [ 0.2 x k ( 1 ) e x k 2 ( 2 ) 0.3 x k 3 ( 2 ) ] f(x_k)=\left[ \begin{array}{ccc} 0.2x_k(1)e^{x_k^2(2)} \\ 0.3x_k^3(2) \end{array} \right] f(xk)=[0.2xk(1)exk2(2)0.3xk3(2)]
g ( x k ) = [ 0 − 0.2 ] g(x_k)=\left[ \begin{array}{ccc} 0 \\ -0.2 \end{array} \right] g(xk)=[0−0.2]
性能指标:
J = 1 2 ∫ 0 ∞ ( x T ( t ) Q ( t ) x ( t ) + u T ( t ) R ( t ) u ( t ) ) d t J=\frac{1}{2}\int_{0}^{\infty}(x^T(t)Q(t)x(t)+u^T(t)R(t)u(t))dt J=21∫0∞(xT(t)Q(t)x(t)+uT(t)R(t)u(t))dt
其中, x 1 ∈ [ − 2 , 2 ] x_1 \in[ -2,2] x1∈[−2,2] , x 2 ∈ [ − 1 , 1 ] x_2 \in[-1,1] x2∈[−1,1],初始状态为 x ( 0 ) = [ 2 , − 1 ] x(0)=[2,-1] x(0)=[2,−1],Q和R取单位矩阵。
# encoding:utf-8
##########################################################################################################
# 导入对应的Python包
##########################################################################################################
import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()
import numpy as np
import matplotlib.pyplot as plt
##########################################################################################################
# 定义一个值迭代的类
##########################################################################################################
class Agent_Value_Iteration():
def __init__(self):
np.random.seed(1) # 随机种子
tf.set_random_seed(1)
# 采样 状态点
x = np.arange(-2, 2, 0.1)
y = np.arange(-1, 1, 0.1)
xx, yy = np.meshgrid(x, y) # 为一维的矩阵
self.state = np.transpose(np.array([xx.ravel(), yy.ravel()])) # 所有状态
self.state_num = self.state.shape[0] # 状态个数
self.state_dim = 2 # 状态维度
self.u_dim = 1 # 动作维度
self.V_dim = 1 # 价值维度
self.learing_rate = 0.01 # 学习率
self.x0 = np.array([2,-1]) # 定义初始状态
self.path = 'ADPmodel/adp.ckpt' # 模型保存路径
self.train_num = 100 # 训练步数
self.simu_num = 20 # 仿真步数
self.Q = np.eye(2) # 性能指标 Q
self.R = np.eye(1) # 性能指标 R
self.build_net() # 创建网络
self.train_method()
self.sess = tf.Session() # 初始化session
self.sess.run(tf.global_variables_initializer()) # 初始化全局变量
self.saver = tf.train.Saver() #定义Saver对象
#######################################################################################################
# 定义非线性模型
# 利用for循环可以处理多个输入状态
#######################################################################################################
def model(self,current_state,u):
next_state = np.zeros([current_state.shape[0],current_state.shape[1]]) # 初始化下一个状态
for index in range(current_state.shape[0]): # 对每个样本计算下一个状态 根据输入的u
next_state[index,0] = 0.2*current_state[index,0]*np.exp(current_state[index,1]**2)
next_state[index,1] = 0.3*current_state[index,1]**3-0.2*u[index]
pass
return next_state
###########################################################################################################
# 考虑到Acotr网络和Critic网络 都是输入状态,输出均为标量
# 直接定义同样的网络 2*10*5*1
###########################################################################################################
def build_net(self):
def build_layers(s, c_names, n_l1, n_l2, w_initializer, b_initializer): # 定义四层BP网络
with tf.variable_scope('l1'):
w1 = tf.get_variable('w1', [self.state_dim, n_l1], initializer=w_initializer, collections=c_names)
b1 = tf.get_variable('b1', [1, n_l1], initializer=b_initializer, collections=c_names)
l1 = tf.nn.relu(tf.matmul(s, w1) + b1)
with tf.variable_scope('l2'):
w2 = tf.get_variable('w2', [n_l1, n_l2], initializer=w_initializer, collections=c_names)
b2 = tf.get_variable('b2', [1, n_l2], initializer=b_initializer, collections=c_names)
l2 = tf.nn.relu(tf.matmul(l1, w2) + b2)
with tf.variable_scope('l3'):
w3 = tf.get_variable('w3', [n_l2, self.u_dim], initializer=w_initializer, collections=c_names)
b3 = tf.get_variable('b3', [1, self.u_dim], initializer=b_initializer, collections=c_names)
net_output = tf.matmul(l2, w3) + b3
return net_output
# ------------------ build two net ------------------
self.s_input = tf.placeholder(tf.float32, [None, self.state_dim], name='state') # 输入占位符
self.V_label = tf.placeholder(tf.float32, [None, self.V_dim], name='V_target') # V网络的标签值占位符
self.A_label = tf.placeholder(tf.float32, [None, self.u_dim], name='A_target') # V网络的标签值占位符
with tf.variable_scope('Value_net'):
c_names, n_l1, n_l2, w_initializer, b_initializer = \
['eval_net_params', tf.GraphKeys.GLOBAL_VARIABLES], 10, 5, \
tf.random_normal_initializer(0., 0.3), tf.constant_initializer(0.1) # 参数配置
self.V = build_layers(self.s_input, c_names, n_l1, n_l2, w_initializer, b_initializer) # 建立V网咯
with tf.variable_scope('Actor_net'):
c_names, n_l1, n_l2, w_initializer, b_initializer = \
['eval_net_params', tf.GraphKeys.GLOBAL_VARIABLES], 10, 5, \
tf.random_normal_initializer(0., 0.3), tf.constant_initializer(0.1) # 参数配置
self.A = build_layers(self.s_input, c_names, n_l1, n_l2, w_initializer, b_initializer) # 建立A网络
#######################################################################################################
# 定义训练函数
# 包括两个网络 Acotr和Critic网络
# 分别定义两个网络的损失函数,利用梯度下降更新网络权值
#######################################################################################################
def train_method(self):
# with tf.variable_scope('Actor_net_loss1'):
#
# # next_state = np.zeros(current_state.shape) # 初始化下一个状态
# # for index in range(current_state.shape[0]): # 对每个样本计算下一个状态 根据输入的u
# # next_state[index, 0] = 0.2 * current_state[index, 0] * np.exp(current_state[index, 1] ** 2)
# # print(u[index])
# # next_state[index, 1] = 0.3 * current_state[index, 1] ** 3 - 0.2 * u[index]
# # pass
# # return next_state
#
# #print(self.A)
# self.Vminloss1 = np.zeros([self.state_num,1])
# #train_next_state = self.model(self.state, self.A)
#
# for index in range(self.state_num): # 循环计算所有状态的标签
# # train_next_state1 = 0.2 * self.state[index, 0] * np.exp(self.state[index, 1] ** 2)
# # train_next_state2 = 0.3 * self.state[index, 1] ** 3 - 0.2 * self.A[index]
# #print(self.sess)
# #print(self.state[index,:])
# na = np.zeros([1,2])
# na[0,:]=self.state[index,:]
# m_a = self.sess.run(self.A,feed_dict={self.s_input: na})
# #train_next_state = self.model(self.state[index,:],m_a)
# train_next_state1 = 0.2 * self.state[index, 0] * np.exp(self.state[index, 1] ** 2)
# train_next_state2 = 0.3 * self.state[index, 1] ** 3 - 0.2 * m_a
# Vi_1 = self.sess.run(self.V, feed_dict={self.s_input: np.array([train_next_state1,train_next_state2]).reshape(1,2)})
# #print(self.A)
# #self.Vminloss1[index] = self.state[index,0]**2+self.state[index,1]**2+self.A[index]**2 + Vi_1
# self.Vminloss1[index] = self.state[index,0]**2 + self.state[index, 1] ** 2 + Vi_1
# pass
# #self.loss1 = tf.reduce_mean(self.Vminloss1*self.Vminloss1)
# print(self.A)
# print(self.Vminloss1)
# self.Vminloss1.dtype = 'float32'
# self.loss1 = tf.reduce_mean(tf.squared_difference(self.Vminloss1, -1.0*self.A*self.A)) # 动作损失函数
with tf.variable_scope('Actor_net_loss1'):
self.loss1 = tf.reduce_mean(tf.squared_difference(self.A*self.A, self.A_label)) # 值函数损失函数
pass
with tf.variable_scope('Value_net_loss2'):
self.loss2 = tf.reduce_mean(tf.squared_difference(self.V, self.V_label)) # 值函数损失函数
pass
with tf.variable_scope('train'):
self.train_op1 = tf.train.RMSPropOptimizer(self.learing_rate).minimize(self.loss1) # A网络 优化器
self.train_op2 = tf.train.RMSPropOptimizer(self.learing_rate).minimize(self.loss2) # V网络 优化器
pass
#######################################################################################################
# 定义学习函数
# 学习一定次数
# 同时训练Actor和Critic网络
#######################################################################################################
def learning(self):
for i in range(self.train_num):
print(i, '--th learing')
###############################################################################################
# 更新Actor网络
###############################################################################################
la_u = self.sess.run(self.A, feed_dict={self.s_input: self.state}) # 根据Actor选择控制输入
la_next_state = self.model(self.state, la_u) # 计算下一时刻状态
la_A_label = np.zeros([self.state_num, 1]) # 初始化V网络的标签
for index in range(self.state_num): # 循环计算所有状态的标签
next_V = self.sess.run(self.V, feed_dict={self.s_input: la_next_state[index, :].reshape(1, 2)})
la_A_label[index] = -1.0*(self.state[index, 0] ** 2 + self.state[index, 1] ** 2 + next_V)
pass
self.sess.run(self.train_op1, feed_dict={self.s_input: self.state, self.A_label: la_A_label}) # 训练V网络
###############################################################################################
# 计算Actor的损失函数loss1
###############################################################################################
A_loss = self.sess.run(self.loss1, feed_dict={self.s_input: self.state, self.A_label: la_A_label})
print(' the loss of A net: ', A_loss)
###############################################################################################
# 更新Critic网络
# 首先计算 label 然后调用优化器优化损失函数
###############################################################################################
la_u = self.sess.run(self.A, feed_dict={self.s_input: self.state}) # 根据Actor选择控制输入
la_next_state = self.model(self.state,la_u) # 计算下一时刻状态
la_V_label = np.zeros([self.state_num,1]) # 初始化V网络的标签
for index in range(self.state_num): # 循环计算所有状态的标签
next_V = self.sess.run(self.V, feed_dict={self.s_input: la_next_state[index,:].reshape(1,2)})
la_V_label[index] = self.state[index,0]**2+self.state[index,1]**2+la_u[index]**2+next_V
pass
#print(la_V_label)
self.sess.run(self.train_op2, feed_dict={self.s_input: self.state, self.V_label: la_V_label}) #训练V网络
###############################################################################################
# 计算Critic的损失函数loss2
###############################################################################################
V_loss = self.sess.run(self.loss2, feed_dict={self.s_input: self.state, self.V_label: la_V_label})
print(' the loss of V net: ', V_loss)
pass
print('the learing is over')
# 这里要保存最好的模型
self.save(self.path)
pass
#######################################################################################################
# 定义仿真函数
# 通过得到的Actor选择动作
# 同时利用Critic计算V
#######################################################################################################
def simulator(self):
print('the simulation is start')
self.restore(self.path)
State_traject = np.zeros([self.simu_num+1,self.state_dim])
State_traject[0,:] = self.x0
u_traject = np.zeros([self.simu_num,1])
for index in range(self.simu_num):
#print(State_traject[index,:])
sim_actor = self.sess.run(self.A,feed_dict={self.s_input:State_traject[index,:].reshape(1,2)})
u_traject[index] = sim_actor
#print(State_traject[index,:])
sim_nexstate = self.model(State_traject[index,:].reshape(1,2),sim_actor)
State_traject[index+1,:]= sim_nexstate
pass
pass
V_traject = self.sess.run(self.V, feed_dict={self.s_input:State_traject[:,:]})
print('the simulation is over')
self.plot_curve(State_traject,u_traject,V_traject)
#######################################################################################################
# 绘图函数
# 分别绘制状态轨迹 控制输入u轨迹 值函数V轨迹
# 并将结果保存!
#######################################################################################################
def plot_curve(self,s,u,V):
# 绘制状态轨迹
plt.figure(1)
plt.plot(s[:, 0], 'r--', label='State_1')
plt.plot(s[:, 1], 'b', label='State_2')
plt.title('State_Trajecteory')
plt.xlabel('iter')
plt.ylabel('State')
plt.legend()
plt.grid()
plt.savefig(r'ADPresultfig\state.png')
plt.show()
# 绘制控制输入u轨迹
plt.figure(2)
plt.plot(u,)
plt.title('U_Trajecteory')
plt.xlabel('iter')
plt.ylabel('u')
plt.grid()
plt.savefig(r'ADPresultfig\u.png')
plt.show()
# 绘制值函数V的轨迹
plt.figure(3)
plt.plot(V, 'r')
plt.title('Cost_Trajecteory')
plt.xlabel('iter')
plt.ylabel('Cost')
plt.grid()
plt.savefig(r'ADPresultfig\V.png')
plt.show()
pass
########################################################################################################
# 保存模型的函数
########################################################################################################
def save(self, path):
self.saver.save(self.sess, path)
########################################################################################################
# 恢复保存的模型的函数
########################################################################################################
def restore(self, path):
self.saver.restore(self.sess, path)
############################################################################################################
# 函数起始运行
# 在仿真时候,直接调用最优的模型进行仿真
# 最优的模型根据损失函数进行判断
############################################################################################################
if __name__ == '__main__':
Agent = Agent_Value_Iteration() # 值迭代类实例化
Agent.learning() # 学习
Agent.simulator() # 仿真
import torch
from torch.autograd import Variable
import matplotlib.pyplot as plt
import numpy as np
state_dim = 2 # 状态维度
v_dim = 1 # 价值维度
action_dim = 1 # 动作维度
learing_rate = 0.005 # 学习率
# learing_num = 2
learing_num = 200 # 学习次数
sim_num = 20 # 仿真步长
x0 = np.array([2,-1]) # 初始状态
epislon = 1.4 # 阈值
torch.manual_seed(1) #设置随机种子,使得每次生成的随机数是确定的
########################################################################################################################
# 定义神经网络类
########################################################################################################################
class Model(torch.nn.Module):
# 初始化
def __init__(self):
super(Model, self).__init__()
self.lay1 = torch.nn.Linear(state_dim, 10, bias = False) # 线性层
self.lay1.weight.data.normal_(0,0.5) # 权重初始化
self.lay2 = torch.nn.Linear(10, 1, bias = False) # 线性层
self.lay2.weight.data.normal_(0, 0.5) # 权重初始化
def forward(self, x):
layer1 = self.lay1(x) # 第一隐层
layer1 = torch.nn.functional.relu(layer1) # relu激活函数
output = self.lay2(layer1) #输出层
return output
########################################################################################################################
# 定义价值迭代类
########################################################################################################################
class Value_Iteration():
def __init__(self):
self.V_model = Model() # 定义V网络
self.A_model = Model() # 定义A网络
self.criterion = torch.nn.MSELoss(reduction='mean') # 平方误差损失
self.optimizer1 = torch.optim.SGD(self.A_model.parameters(), lr=learing_rate) # 利用梯度下降算法优化model.parameters
self.optimizer2 = torch.optim.SGD(self.V_model.parameters(), lr=learing_rate) # 利用梯度下降算法优化model.parameters
# 采样 状态点
x = np.arange(-2, 2, 0.1)
y = np.arange(-1, 1, 0.1)
xx, yy = np.meshgrid(x, y) # 为一维的矩阵
self.state = np.transpose(np.array([xx.ravel(), yy.ravel()])) # 所有状态
self.state_num = self.state.shape[0] # 状态个数
self.cost = [] # 初始化误差矩阵
pass
####################################################################################################################
# 定义模型函数
####################################################################################################################
def model(self, current_state, u):
next_state = np.zeros([current_state.shape[0], current_state.shape[1]]) # 初始化下一个状态
for index in range(current_state.shape[0]): # 对每个样本计算下一个状态 根据输入的u
next_state[index, 0] = 0.2 * current_state[index, 0] * np.exp(current_state[index, 1] ** 2)
next_state[index, 1] = 0.3 * current_state[index, 1] ** 3 - 0.2 * u[index]
pass
return next_state
####################################################################################################################
# 定义学习函数
####################################################################################################################
def learning(self):
for index in range(learing_num):
print('the ',index,' --th learing start')
last_V_value = self.V_model(Variable(torch.Tensor(self.state))).data
#############################################################################################################
# 更新Actor网络
#############################################################################################################
A_predict = self.A_model( Variable(torch.Tensor(self.state))) # 预测值
AA_predict = A_predict * A_predict
la_u = self.A_model(Variable(torch.Tensor(self.state)))
la_next_state = self.model(self.state, la_u) # 计算下一时刻状态
AA_target = np.zeros([self.state_num, 1]) # 初始化A网络的标签
for index in range(self.state_num): # 循环计算所有状态的标签
next_V = self.V_model(Variable(torch.Tensor(la_next_state[index, :])))
AA_target[index] = self.state[index, 0] ** 2 + self.state[index, 1] ** 2 + next_V.data
pass
# print(la_V_label)
# print(AA_target.shape)
# print(AA_predict.size())
loss1 = self.criterion(AA_predict, Variable(torch.Tensor(AA_target))) # 计算损失
self.optimizer1.zero_grad() # 对模型参数做一个优化,并且将梯度清0
loss1.backward() # 计算梯度
self.optimizer1.step() # 权重更新
#############################################################################################################
# 更新Crictic网络
#############################################################################################################
V_predict = self.V_model(Variable(torch.Tensor(self.state))) # 预测值
la_u = self.A_model(Variable(torch.Tensor(self.state))) # 计算输入
la_next_state = self.model(self.state, la_u) # 计算下一时刻状态
V_target = np.zeros([self.state_num, 1]) # 初始化V网络的标签
for index in range(self.state_num): # 循环计算所有状态的标签
next_V = self.V_model(Variable(torch.Tensor(la_next_state[index, :])))
V_target[index] = self.state[index, 0] ** 2 + self.state[index, 1] ** 2 + la_u.data[index] ** 2 + next_V.data
pass
# print(la_V_label)
loss2 = self.criterion(V_predict, Variable(torch.Tensor(V_target))) # 计算损失
self.optimizer2.zero_grad() # 对模型参数做一个优化,并且将梯度清0
loss2.backward() # 计算梯度
self.optimizer2.step() # 权重更新
V_value = self.V_model(Variable(torch.Tensor(self.state))).data # 计算V
pp = np.abs(V_value)-np.abs(last_V_value)
#print(pp)
dis = np.sum(np.array(pp.reshape(self.state_num))) #平方差
self.cost.append(dis)
print('平方差', dis)
if dis < epislon:
break
pass
pass
#######################################################################################################
# 定义仿真函数
# 通过得到的Actor选择动作
# 同时利用Critic计算V
#######################################################################################################
def simulator(self):
print('the simulation is start')
#self.restore(self.path)
State_traject = np.zeros([sim_num + 1, state_dim])
State_traject[0, :] = x0
u_traject = np.zeros([sim_num, 1])
for index in range(sim_num):
print('the ', index, ' --th time start')
# print(State_traject[index,:])
print('当前状态:', Variable(torch.Tensor(State_traject[index,:])).data)
sim_actor = self.A_model(Variable(torch.Tensor(State_traject[index,:])))
print('当前输入:',sim_actor)
u_traject[index] = sim_actor.data
# print(State_traject[index,:])
sim_nexstate = self.model(State_traject[index, :].reshape(1, 2), sim_actor.data)
print('下一时刻状态:', sim_nexstate)
State_traject[index + 1, :] = sim_nexstate
pass
pass
V_traject = self.V_model(Variable(torch.Tensor(State_traject))).data
print('the simulation is over')
self.plot_curve(State_traject, u_traject, V_traject,self.cost)
pass
#######################################################################################################
# 绘图函数
# 分别绘制状态轨迹 控制输入u轨迹 值函数V轨迹
# 并将结果保存!
#######################################################################################################
def plot_curve(self, s, u, V,cost):
# print('\nstate\n',s)
# print('\nu\n', u)
# print('\nV\n', V)
# 绘制状态轨迹
plt.figure(1)
plt.plot(s[:, 0], 'r', label='State_1')
plt.plot(s[:, 1], 'b', label='State_2')
plt.title('State_Trajecteory')
plt.xlabel('iter')
plt.ylabel('State')
plt.legend()
plt.grid()
plt.savefig(r'ADPresultfig\state.png')
plt.show()
# 绘制控制输入u轨迹
plt.figure(2)
plt.plot(u, )
plt.title('U_Trajecteory')
plt.xlabel('iter')
plt.ylabel('u')
plt.grid()
plt.savefig(r'ADPresultfig\u.png')
plt.show()
# 绘制值函数V的轨迹
plt.figure(3)
plt.plot(V, 'r')
plt.title('Cost_Trajecteory')
plt.xlabel('iter')
plt.ylabel('Cost')
plt.grid()
plt.savefig(r'ADPresultfig\V.png')
plt.show()
# 绘制值函数V的轨迹
plt.figure(4)
plt.plot(cost, 'r')
plt.title('Train_loss_Trajecteory')
plt.xlabel('iter')
plt.ylabel('Train_loss')
plt.grid()
plt.savefig(r'ADPresultfig\loss.png')
plt.show()
pass
########################################################################################################################
# 函数起始运行
########################################################################################################################
if __name__ == '__main__':
Agent = Value_Iteration() # 值迭代类实例化
Agent.learning() # 学习
Agent.simulator() # 仿真
代码运行说明:
需要分别安装Pytorch和Tensorflow
由于保存结果,因此需要在根目录先创建ADPmodel和ADPresultfig文件夹
两个python文件只需要放在根目录下即可
觉得作者写的还行就赏个脸,打赏一毛钱呗!哈哈哈
以上是作者一门课程的作业,请勿抄袭!!!
Al-Tamimi A, Lewis F L, Abu-Khalaf M. Discrete-time nonlinear HJB solution using approximate dynamic programming: Convergence proof[J]. IEEE Transactions on Systems, Man, and Cybernetics, Part B (Cybernetics), 2008, 38(4): 943-949. ↩︎
Wei Q, Lewis F L, Liu D, et al. Discrete-time local value iteration adaptive dynamic programming: Convergence analysis[J]. IEEE Transactions on Systems, Man, and Cybernetics: Systems, 2016, 48(6): 875-891. ↩︎