ADP(自适应动态规划)-值迭代

    看网上ADP的代码挺少的,最近写了一个ADP值迭代的代码,分享一下,接下来也准备写Actor-Critic框架的代码。

1、ADP值迭代原理

    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)

    流程图如下所示:
ADP(自适应动态规划)-值迭代_第1张图片

2、非线性系统

    假设非线性系统模型:

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)=[00.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=210(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取单位矩阵。

3、Tensorflow版本

  • Tensorflow版本代码
# 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()                                                                          # 仿真
  • 结果说明
    ADP(自适应动态规划)-值迭代_第2张图片
        从图 2.1 看出,仅用了 4 步两个状态均收敛为 0。图 2.2 显示了控制输入也收敛于 0,不过还有一定误差,大约 0.007。从状态的 V 值来看(图 2.3),收敛到了约 20。
  • 存在的问题
        尽管上述实现了收敛,但是在训练网络的时候采用了一个“小捷径”。因为 在 Tensorflow 中,我们通过神经网络求预测值时,需要给网络 feed 一批数据(常 数,而不是 tensor)。而在更新 Actor 网络:
    W u i = a r g m i n α ( x k T Q x k + u ^ T ( x k , α ) R u ^ ( x k , α ) + V ^ i ( f ( x k ) + g ( x k ) u ^ ( x k , α ) ) ) (5) W_{ui}=\mathop{argmin}\limits_{\alpha}(x_k^TQx_k+\hat{u}^T(x_k,{\alpha})R\hat{u}(x_k,{\alpha})+\hat{V}_i(f(x_k)+g(x_k)\hat{u}(x_k,\alpha)))\tag{5} Wui=αargmin(xkTQxk+u^T(xk,α)Ru^(xk,α)+V^i(f(xk)+g(xk)u^(xk,α)))(5)
        我们需要计算 V ^ i ( f ( x k ) + g ( x k ) u ^ ( x k , α ) ) \hat{V}_i(f(x_k)+g(x_k)\hat{u}(x_k,\alpha)) V^i(f(xk)+g(xk)u^(xk,α)) ,而 V ^ i ( f ( x k ) + g ( x k ) u ^ ( x k , α ) ) \hat{V}_i(f(x_k)+g(x_k)\hat{u}(x_k,\alpha)) V^i(f(xk)+g(xk)u^(xk,α)) 又与 u ^ ( x k , α ) \hat{u}(x_k,\alpha) u^(xk,α) u ^ ( x k , α ) \hat{u}(x_k,\alpha) u^(xk,α)是Actor 网络的输出,即是 Actor 网络参数的函数,因而 u ^ ( x k , α ) \hat{u}(x_k,\alpha) u^(xk,α)是一个 tensor,因此无法带入 V 网络求解,也尝试多种方法,仍然无法解决。最后直接将所有状态带入 Actor 网络求解,进一步带入模型与 Critic 网络中, 而没有把 V ^ i ( f ( x k ) + g ( x k ) u ^ ( x k , α ) ) \hat{V}_i(f(x_k)+g(x_k)\hat{u}(x_k,\alpha)) V^i(f(xk)+g(xk)u^(xk,α)) 看作是 Actor 网络参数 α \alpha α的函数
       此外,考虑到 Pytorch 不存在这个问题,因此,下一节利用 Pytorch 实现。

4、Pytorch版本

  • Pytorch版本代码
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()                                                        # 仿真
  • 结果说明
    ADP(自适应动态规划)-值迭代_第3张图片
       从图 2.4 看出,仅用了5 步两个状态均收敛为 0。图 2.5 显示了控制输入也收敛于 0,这个结果也是我们所期望的。从状态的 V 值来看(图 2.6),收敛到 0。
       在训练阶段,我们可以看出 loss(V 值的变化差)曲线起初有一定的增长, 随后逐渐收敛,模型共训练了 160 次

The End!

代码运行说明:

需要分别安装Pytorch和Tensorflow
由于保存结果,因此需要在根目录先创建ADPmodel和ADPresultfig文件夹
两个python文件只需要放在根目录下即可

觉得作者写的还行就赏个脸,打赏一毛钱呗!哈哈哈

以上是作者一门课程的作业,请勿抄袭!!!

参考文献


  1. 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. ↩︎

  2. 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. ↩︎

你可能感兴趣的:(ADP(自适应动态规划))