强化学习编程实践-4-基于蒙特卡洛的方法

        第3章给出了学习算法的基本思路:策略评估和策略改善。其中策略评估用到了以下的公式(4.1)

        策略改善则用了最简单的贪婪策略(4.2)

        为什么要用蒙特卡洛算法?先看公式4.1和4.2,如果状态转移概率已知,那么利用上面两式就可以得到最优策略。如果模型是未知的?式(4.1)不能再用,式(4.1)仍然可以用,因为该式与模型无关。

        如果想要利用整个框架,必须找到一种方法来替代公式(4.1)的策略评估。

---->利用本章蒙特卡洛方法和第5章的时间差分方法

4.1 蒙特卡洛算法原理

         当模型是未知的,即智能体在状态s时并不知道转移到下一个状态s'的概率。但是,智能体在状态s通过动作a与环境进行交互,环境会根据根据状态转移给出下一个时刻的状态,但环境并不会直接给出状态转移的概率。也就是说,在模型未知时,我们只能通过一系列的动作,得到一系列的状态序列。

其中为终止状态。

至此,我们已经拥有当前的策略,以及根据策略Π得到的一连串数据,缺少状态转移概率,而想要评估策略Π的值函数,该怎么做?

        既然不能使用式(4.1),那么回到值函数的定义式(4.3)

式4.3是期望的式子,其中\tau表示一次实验数据,即为

G(τ)为累积折扣回报,为产生轨迹\tau的概率分布,我们不知道值函数的概率分布,所以不能用积分公式来求值函数。但我们有数据就可以计算在策略Π的作用下,经过一次实验τ后状态St处的折扣累积回报G(τ)。

        蒙特卡洛的方法就是用策略Π做很多次实验,从而可以的带状态s_t处的很多个折扣累积回报,那么公式(4.3)的积分公式,就可以用代数平均来计算。即式(4.4)

        那有了式4.4和式4.2,就可以进行策略评估和策略改善了吗?

        还不行,因此公式4.2,我们只知道每个状态处的行为-值函数q(s,a),而不是状态值v_\pi(s)

        行为值函数的定义为式(4.5):

当模型P已知时,值函数可以由式(4.5)计算出来。但模型未知时,该怎么办?

        还是需要行为-值函数的原始定义,式(4.6):

        式(4.6)的计算用前面的蒙特卡洛进行估计。即式(4.7):

        对于无模型的强化学习算法,利用式4.7和式4.2就可以实现策略评估和策略改善。

        1.关于值函数和行为值函数

        值函数定义:

        行为值函数定义:

即在状态s_t,并采取了动作a之后折扣累积回报的期望。

        举一个简单的例子,利用策略Π产生了如下两组数据:

        那么状态值函数的计算公式为\nu (s_0)=\frac{1}{2}((r_1+\gamma r_2)+(r_2+\gamma r_T))

        行为值函数可以分为两个:q(s_0,a_1)=r_1+\gamma r_2\\ q(s_0,a_2)=r_3+\gamma r_T

        2.关于值函数的定义

        注意:剩下的笔记我用手写笔记了,感觉手写笔记可以更多的思考,电子笔记时间全浪费在敲公式和字符那些上了,反而不利于思考。

        

4.2蒙特卡洛算法的代码实现

4.2.1 环境类的修改和蒙特卡洛算法类的声明

        无模型的强化学习算法,需要评估的是行为-值函数,所以在渲染时,需要把行为值函数显示出来。得到形如图4.1的蒙特卡洛方法显示画面,在该画面上,每个方格表示一个状态,每个状态的4个值分别对应着4个动作的行为-值函数。

        在原来的环境YuanYangEnv基础上修改:

        gamma由原来的0.8设置为0.95,即增加后继回报对当前的影响。这是因为蒙特卡洛的方法利用整条轨迹的数据进行评估策略,如果gamma太小,后面回报的贡献会很快衰减。行为值函数声明为100x4的矩阵。

        为了得到显示画面,在渲染子函数render()中进行修改:增加动作-值函数

        除了对显示进行修改,对回报也进行修改。因为原来的回报只在找到目标点和碰撞障碍物的时候才会有回报,也就是说这些回报是稀疏回报,蒙特卡洛方法对于稀疏回报问题的估计方差无限大。为此,每一步都给出了回报,将稀疏回报问题变为稠密回报。代码修改transform()中

        设置回报的规则是:如果碰到障碍物回报为-10,找到目标点回报为+10,如既没碰到障碍物又没找到目标点,每走一步回报为-2.

        创建一个名为MC_RL.py的文件,在该文件下实现蒙特卡洛方法。首先,导入一些必要的库,然后命名为MC_RL的一个类,在初始化函数__init__中声明行为值函数,因为本例共100个状态,每个状态处有4个动作,因此,行为值函数是一个100x4的表格。用n来表示状态行为对被访问的次数。

        定义e-greedy策略

找到动作所对应的序号

4.2.2 探索初始化蒙特卡洛算法实现

        探索初始化蒙特卡洛算法实现的伪代码如下:

第1行:进行必要的初始化,包括初始化行为值函数及策略

第2行:初始化状态和动作由均匀随机概率分布函数生成,从该随机的状态-行为对出发生成一组数据,对该组数据中每个状态-行为计算折扣累计回报。

第3行:利用蒙特卡洛增量式学习方法,根据上一步计算的折扣累计回报更新相应的行为-值函数。

第4行:利用更新后的行为值函数更新策略,这里用的策略是贪婪策略。

        代码:

        定义类子函数mc_learning_ei来实现探索初始化蒙特卡洛方法。首先初始化行为值函数为0,初始化访问格状态-动作对的次数为0.初始化完成后便进入正式的迭代学习阶段。声明存放状态样本、动作样本、回报样本的变量,并随机初始化状态s和动作a.

        下面调用mc_test()子函数,该子函数用来测试经过蒙特卡洛学习到的策略是否找到了目标。如果找到了,该子函数会返回1,否则返回0.因此,如果返回1则结束蒙特卡洛学习,否则继续学习。当找到目标时,将蒙特卡洛迭代学习的次数打印出来。

        下面的程序用当前贪婪策略进行一次实验,并保存相应的数据到s_samples、r_sample、a_sample中。

        下面的语句很关键,在实际的训练过程中,智能体可以会往回走,往回走其实是不合理的。所以在这里给回到当前实验中已经访问的状态的动作一个负的回报。

        下面根据回报值计算折扣累计回报,先得到下一个状态处的值函数q(s‘,a),然后逆向求解前面状态-行为对的折扣累计回报,最后得到该次实验中第一个状态行为对的折扣累计回报。

        下面从该次实验第1个状态开始,一次计算后继状态的折扣累计回报,并利用增量式的方法更新每个状态-行为对的值。

        在上面的代码中,用到了测试子函数mc_test()。该子函数中初始状态为0,智能体通过贪婪策略与环境进行交互。如果结束时智能体找到了目标,则设置标志为1,否则为0.最后,返回标志位。

        下图为探索初始化蒙特卡洛算法效果图。从图中可以看到,雄鸟最终可以找到雌鸟,但走了一些弯路,路线不是最短的。

        这里截了还未到终点的图,(还是之前显示的问题,我的电脑显示屏1080,但整个画面1200*900,后面再修改尺寸吧)

4.2.3 同策略蒙特卡洛算法实现

        同策略蒙特卡洛算法实现的伪代码如下:

第1行:进行必要的初始化,包括初始化行为值函数,e-greedy策略。

第2行:从初始化状态S0开始,利用e-greedy策略生成一次实验数据,并对该次实验的每个状态-行为对计算折扣累计回报。

第3行:利用增量式蒙特卡洛学习方法进行更新行为值函数。

第4行:利用更新的行为值函数更新e-greedy策略。

详细代码:

        定义mc_learning_on_policy()子函数为同策略蒙特卡洛学习算法。首先初始化行为值函数qvalue为零矩阵,个状态-行为对的次数为0,进入迭代学习循环中。声明变量用于存储装填样本、动作样本、回报样本,固定初始化状态s=0,设置e-greecy策略的探索率随迭代次数衰减。

        设置好基本变量,进入与环境的交互程序,根据当前策略不断采集数据。采集数据的过程为利用当前策略得到当前动作a,智能体在状态s处采用动作a与环境交互,从环境中得到下一个状态s_next,回报r,以及是否结束的标志位done。

此处很关键,智能体在探索的时候可能会往回走到之前经历过的状态,对于这样的动作我们给与一个小的负回报。

        下面检测蒙特卡洛学习算法的效果,判断是否已经完成任务,如果完成则结束学习。

        下面根据回报值计算折扣累计回报,先得到下一个状态处的值函数q(s',a),然后逆向求解前面状态-行为对的折扣累计回报,最后得到该次实验第1个状态行为对的折扣累计回报。

下面的代码:从该次实验第1个状态开始,依次计算后继状态的折扣累计回报,并利用增量式的方法更新每个状态-行为对的值。

        至此,该算法全部实现。写一个主函数,进行测试。首先利用环境类YuanYangEnv()实例化一个智体,然后,用蒙特卡洛算法实例化一个学习算法brain,调用探索初始化蒙特卡洛算法mc_learning_ei,接着,调用同策略蒙特卡洛算法mc_learning_on_policy,将学习到的行为-值函数给环境,将其渲染出来;最后,对学习好的策略进行测试,并显示路径。

    def mc_test(self):
        s = 0
        s_sample = []
        done = False
        flag = 0
        step_num = 0
        while False == done and step_num < 30:
            a = self.greedy_policy(self.qvalue, s)
            # 与环境交互
            s_next, r, done = self.yuanyang.transform(s, a)
            s_sample.append(s)
            s = s_next
            step_num += 1
        if s == 9:
            flag = 1
        return flag

if __name__=="__main__":
    yuanyang = YuanYangEnv()
    brain = MC_RL(yuanyang)
    # 探索初始化方法
    qvalue1 = brain.mc_learning_ei(num_iter=10000)
    #on-policy方法
    qvalue2=brain.mc_learning_on_policy(num_iter=10000, epsilon=0.2)
    print(qvalue2)
    #将行为值函数渲染出来
    yuanyang.action_value = qvalue2
    #测试学到的策略
    flag = 1
    s = 0
    # print(policy_value.pi)
    step_num = 0
    path = []
    # 将最优路径打印出来
    while flag:
        #渲染路径点
        path.append(s)
        yuanyang.path = path
        a = brain.greedy_policy(qvalue2,s)
        # a = agent.bolzman_policy(qvalue,s,0.1)
        print('%d->%s\t' % (s, a),qvalue2[s,0],qvalue2[s,1],qvalue2[s,2],qvalue2[s,3])
        yuanyang.bird_male_position = yuanyang.state_to_position(s)
        yuanyang.render()
        time.sleep(0.25)
        step_num += 1
        s_, r, t = yuanyang.transform(s, a)
        if t == True or step_num > 30:
            flag = 0
        s = s_
    #渲染最后的路径点
    yuanyang.bird_male_position = yuanyang.state_to_position(s)
    path.append(s)
    yuanyang.render()
    while True:
        yuanyang.render()

 这里截了还未到终点的图,(还是之前显示的问题,我的电脑显示屏1080,但整个画面1200*900,后面再修改尺寸吧)

可以看终端具体的输出

        中间的省略了一些

总项目如下:

还有resources文件夹下的游戏背景图片和小鸟图片。

yuanyang_env_mc.py

import pygame
from load import *
import math
import time
import random
import numpy as np

class YuanYangEnv:
    def __init__(self):
        self.states=[]
        for i in range(0,100):
            self.states.append(i)
        self.actions = ['e', 's', 'w', 'n']
        self.gamma = 0.95
        self.action_value = np.zeros((100, 4))
        self.viewer = None
        self.FPSCLOCK = pygame.time.Clock()
        #屏幕大小
        self.screen_size=(1200,900)
        self.bird_position=(0,0)
        self.limit_distance_x=120
        self.limit_distance_y=90
        self.obstacle_size=[120,90]
        self.obstacle1_x = []
        self.obstacle1_y = []
        self.obstacle2_x = []
        self.obstacle2_y = []
        self.path = []

        for i in range(8):
            #第一个障碍物
            self.obstacle1_x.append(360)
            if i <= 3:
                self.obstacle1_y.append(90 * i)
            else:
                self.obstacle1_y.append(90 * (i + 2))
            # 第二个障碍物
            self.obstacle2_x.append(720)
            if i <= 4:
                self.obstacle2_y.append(90 * i)
            else:
                self.obstacle2_y.append(90 * (i + 2))

        self.bird_male_init_position=[0,0]
        self.bird_male_position = [0, 0]
        self.bird_female_init_position=[1080,0]
    #def step(self):
    def collide(self,state_position):
        flag = 1
        flag1 = 1
        flag2 = 1
        # 判断第一个障碍物
        dx = []
        dy = []
        for i in range(8):
            dx1 = abs(self.obstacle1_x[i] - state_position[0])
            dx.append(dx1)
            dy1 = abs(self.obstacle1_y[i] - state_position[1])
            dy.append(dy1)
        mindx = min(dx)
        mindy = min(dy)
        if mindx >= self.limit_distance_x or mindy >= self.limit_distance_y:
            flag1 = 0
        # 判断第二个障碍物
        second_dx = []
        second_dy = []
        for i in range(8):
            dx2 = abs(self.obstacle2_x[i] - state_position[0])
            second_dx.append(dx2)
            dy2 = abs(self.obstacle2_y[i] - state_position[1])
            second_dy.append(dy2)
        mindx = min(second_dx)
        mindy = min(second_dy)
        if mindx >= self.limit_distance_x or mindy >= self.limit_distance_y:
            flag2 = 0
        if flag1 == 0 and flag2 == 0:
            flag = 0
        if state_position[0] > 1080 or state_position[0] < 0 or state_position[1] > 810 or state_position[1] < 0:
            flag = 1
        return flag
    def find(self,state_position):
        flag=0
        if abs(state_position[0]-self.bird_female_init_position[0])<self.limit_distance_x and abs(state_position[1]-self.bird_female_init_position[1])<self.limit_distance_y:
            flag=1
        return flag
    def state_to_position(self, state):
        i = int(state / 10)
        j = state % 10
        position = [0, 0]
        position[0] = 120 * j
        position[1] = 90 * i
        return position
    def position_to_state(self, position):
        i = position[0] / 120
        j = position[1] / 90
        return int(i + 10 * j)
    def reset(self):
        #随机产生初始状态
        flag1=1
        flag2=1
        while flag1 or flag2 ==1:
            #随机产生初始状态,0~99,randoom.random() 产生一个0~1的随机数
            state=self.states[int(random.random()*len(self.states))]
            state_position = self.state_to_position(state)
            flag1 = self.collide(state_position)
            flag2 = self.find(state_position)
        return state
    def transform(self,state, action):
        #将当前状态转化为坐标
        current_position=self.state_to_position(state)
        next_position = [0,0]
        flag_collide=0
        flag_find=0
        #判断当前坐标是否与障碍物碰撞
        flag_collide=self.collide(current_position)
        #判断状态是否是终点
        flag_find=self.find(current_position)
        if flag_collide==1:
            return state, -10, True
        if flag_find == 1:
            return state, 10, True
        #状态转移
        if action=='e':
            next_position[0]=current_position[0]+120
            next_position[1]=current_position[1]
        if action=='s':
            next_position[0]=current_position[0]
            next_position[1]=current_position[1]+90
        if action=='w':
            next_position[0] = current_position[0] - 120
            next_position[1] = current_position[1]
        if action=='n':
            next_position[0] = current_position[0]
            next_position[1] = current_position[1] - 90
        #判断next_state是否与障碍物碰撞
        flag_collide = self.collide(next_position)
        #如果碰撞,那么回报为-10,并结束
        if flag_collide==1:
            return self.position_to_state(current_position),-10,True
        #判断是否终点
        flag_find = self.find(next_position)
        if flag_find==1:
            return self.position_to_state(next_position),10,True
        return self.position_to_state(next_position), -2, False
    def gameover(self):
        for event in pygame.event.get():
            if event.type == QUIT:
                exit()
    def render(self):
        if self.viewer is None:
            pygame.init()
            #画一个窗口
            self.viewer=pygame.display.set_mode(self.screen_size,0,32)
            pygame.display.set_caption("yuanyang")
            #下载图片
            self.bird_male = load_bird_male()
            self.bird_female = load_bird_female()
            self.background = load_background()
            self.obstacle = load_obstacle()
            #self.viewer.blit(self.bird_male, self.bird_male_init_position)
            #在幕布上画图片
            self.viewer.blit(self.bird_female, self.bird_female_init_position)
            self.viewer.blit(self.background, (0, 0))
            self.font = pygame.font.SysFont('times', 15)
        self.viewer.blit(self.background,(0,0))
        #画直线
        for i in range(11):
            pygame.draw.lines(self.viewer, (255, 255, 255), True, ((120*i, 0), (120*i, 900)), 1)
            pygame.draw.lines(self.viewer, (255, 255, 255), True, ((0, 90* i), (1200, 90 * i)), 1)
        self.viewer.blit(self.bird_female, self.bird_female_init_position)
        #画障碍物
        for i in range(8):
            self.viewer.blit(self.obstacle, (self.obstacle1_x[i], self.obstacle1_y[i]))
            self.viewer.blit(self.obstacle, (self.obstacle2_x[i], self.obstacle2_y[i]))
        #画小鸟
        self.viewer.blit(self.bird_male,  self.bird_male_position)
        # 画动作值函数
        for i in range(100):
            y = int(i / 10)
            x = i % 10
            #往东行为值函数
            surface = self.font.render(str(round(float(self.action_value[i,0]), 2)), True, (0, 0, 0))
            self.viewer.blit(surface, (120 * x + 80, 90 * y + 45))
            #往南的值函数
            surface = self.font.render(str(round(float(self.action_value[i, 1]), 2)), True, (0, 0, 0))
            self.viewer.blit(surface, (120 * x + 50, 90 * y + 70))
            # 往西的值函数
            surface = self.font.render(str(round(float(self.action_value[i, 2]), 2)), True, (0, 0, 0))
            self.viewer.blit(surface, (120 * x + 10, 90 * y + 45))
            # 往北的值函数
            surface = self.font.render(str(round(float(self.action_value[i, 3]), 2)), True, (0, 0, 0))
            self.viewer.blit(surface, (120 * x + 50, 90 * y + 10))
        # 画路径点
        for i in range(len(self.path)):
            rec_position = self.state_to_position(self.path[i])
            pygame.draw.rect(self.viewer, [255, 0, 0], [rec_position[0], rec_position[1], 120, 90], 3)
            surface = self.font.render(str(i), True, (255, 0, 0))
            self.viewer.blit(surface, (rec_position[0] + 5, rec_position[1] + 5))
        pygame.display.update()
        self.gameover()
        # time.sleep(0.1)
        self.FPSCLOCK.tick(30)
if __name__=="__main__":
    yy=YuanYangEnv()
    yy.render()
    while True:
        for event in pygame.event.get():
            if event.type == QUIT:
                exit()

        # speed = 50
        # clock = pygame.time.Clock()
        # state=0
        # for i in range(12):
        #     flag_collide = 0
        #     obstacle1_coord = [yy.obstacle1_x[i],yy.obstacle1_y[i]]
        #     obstacle2_coord = [yy.obstacle2_x[i],yy.obstacle2_y[i]]
        #     flag_collide = yy.collide(obstacle1_coord)
        #     print(flag_collide)
        #     print(yy.collide(obstacle2_coord))
        # time_passed_second = clock.tick()/1000
        # i= int(state/10)
        # j=state%10
        # yy.bird_male_position[0]=j*40
        # yy.bird_male_position[1]=i*30
        # time.sleep(0.2)
        # pygame.display.update()
        # state+=1
        # yy.render()
#        print(yy.collide())

MC_RL.py

import pygame
import time
import random
import numpy as np
import matplotlib.pyplot as plt
from yuanyang_env_mc import YuanYangEnv
class MC_RL:
    def __init__(self, yuanyang):
        #行为值函数的初始化
        self.qvalue = np.zeros((len(yuanyang.states),len(yuanyang.actions)))*0.1
        #次数初始化
        #n[s,a]=1,2,3?? 求经验平均时,q(s,a)=G(s,a)/n(s,a)
        self.n = 0.001*np.ones((len(yuanyang.states),len(yuanyang.actions)))
        self.actions = yuanyang.actions
        self.yuanyang = yuanyang
        self.gamma = yuanyang.gamma
    # 定义贪婪策略
    def greedy_policy(self, qfun, state):
        amax = qfun[state, :].argmax()
        return self.actions[amax]
    #定义e-贪婪策略,蒙特卡罗方法,要评估的策略时e-greedy策略,产生数据的策略。
    def epsilon_greedy_policy(self, qfun, state, epsilon):
        amax = qfun[state, :].argmax()
        #概率部分
        if np.random.uniform() < 1- epsilon:
            #最优动作
            return self.actions[amax]
        else:
            return self.actions[int(random.random()*len(self.actions))]
    #找到动作所对应的序号
    def find_anum(self, a):
        for i in range(len(self.actions)):
            if a == self.actions[i]:
                return i
    def mc_learning_on_policy(self, num_iter, epsilon):
        self.qvalue = np.zeros((len(yuanyang.states), len(yuanyang.actions)))
        self.n = 0.001 * np.ones((len(yuanyang.states), len(yuanyang.actions)))
        #学习num_iter次
        for iter1 in range(num_iter):
            #采集状态样本
            s_sample = []
            #采集动作样本
            a_sample = []
            #采集回报样本
            r_sample = []
            # #随机初始化状态
            # s = self.yuanyang.reset()
            #固定初始状态
            s = 0
            done = False
            step_num = 0
            epsilon = epsilon*np.exp(-iter1/1000)
            #采集数据s0-a1-s1-a2-s2...terminate state
            #for i in range(5):
            while False == done and step_num < 30:
                a = self.epsilon_greedy_policy(self.qvalue, s, epsilon)
                #与环境交互
                s_next, r, done = self.yuanyang.transform(s, a)
                a_num = self.find_anum(a)
                #往回走给予惩罚
                if s_next in s_sample:
                    r= -2
                #存储数据,采样数据
                s_sample.append(s)
                r_sample.append(r)
                a_sample.append(a_num)
                step_num+=1
                #转移到下一个状态,继续试验,s0-s1-s2
                s = s_next
            #任务完成结束条件
            if s == 9:
                print("同策略第一次完成任务需要的次数:", iter1)
                break
            #从样本中计算累计回报,g(s_0) = r_0+gamma*r_1+gamma^2*r_2+gamma^3*r3+v(sT)
            a = self.epsilon_greedy_policy(self.qvalue, s,epsilon)
            g = self.qvalue[s,self.find_anum(a)]
            #计算该序列的第一状态的累计回报
            for i in range(len(s_sample)-1, -1, -1):
                g *= self.gamma
                g += r_sample[i]
            # print("episode number, trajectory", iter1, s_sample)
            # print("first state", s_sample[0], g)
            #g=G(s1,a),开始算其他状态处的累计回报
            for i in range(len(s_sample)):
                #计算状态-行为对(s,a)的次数,s,a1...s,a2
                self.n[s_sample[i], a_sample[i]] += 1.0
                #利用增量式方法更新值函数
                self.qvalue[s_sample[i], a_sample[i]] = (self.qvalue[s_sample[i], a_sample[i]]*(self.n[s_sample[i],a_sample[i]]-1)+g)/ self.n[s_sample[i], a_sample[i]]
                g -= r_sample[i]
                g /= self.gamma
                # print("s_sample,a",g)
            # print("number",self.n)
        return self.qvalue
    def mc_learning_ei(self, num_iter):
        # 学习num_iter次
        self.qvalue=np.zeros((len(yuanyang.states), len(yuanyang.actions)))
        self.n = 0.001 * np.ones((len(yuanyang.states), len(yuanyang.actions)))
        for iter1 in range(num_iter):
            # 采集状态样本
            s_sample = []
            # 采集动作样本
            a_sample = []
            # 采集回报样本
            r_sample = []
            # 随机初始化状态
            s = self.yuanyang.reset()
            a = self.actions[int(random.random()*len(self.actions))]
            done = False
            step_num = 0
            if self.mc_test() == 1:
                print("探索初始化第一次完成任务需要的次数:", iter1)
                break
            # 采集数据s0-a1-s1-a2-s2...terminate state
            # for i in range(5):
            while False == done and step_num < 30:
                # 与环境交互
                s_next, r, done = self.yuanyang.transform(s, a)
                a_num = self.find_anum(a)
                # 往回走给予惩罚
                if s_next in s_sample:
                    r = -2
                # 存储数据,采样数据
                s_sample.append(s)
                r_sample.append(r)
                a_sample.append(a_num)
                step_num += 1
                # 转移到下一个状态,继续试验,s0-s1-s2
                s = s_next
                a = self.greedy_policy(self.qvalue, s)
            # 从样本中计算累计回报,g(s_0) = r_0+gamma*r_1+gamma^2*r_2+gamma^3*r3+v(sT)
            a = self.greedy_policy(self.qvalue, s)
            g = self.qvalue[s, self.find_anum(a)]
            # 计算该序列的第一状态的累计回报
            for i in range(len(s_sample) - 1, -1, -1):
                g *= self.gamma
                g += r_sample[i]
            # print("episode number, trajectory", iter1, s_sample)
            # print("first state", s_sample[0], g)
            # g=G(s1,a),开始算其他状态处的累计回报
            for i in range(len(s_sample)):
                # 计算状态-行为对(s,a)的次数,s,a1...s,a2
                self.n[s_sample[i], a_sample[i]] += 1.0
                # 利用增量式方法更新值函数
                self.qvalue[s_sample[i], a_sample[i]] = (self.qvalue[s_sample[i], a_sample[i]] * (
                            self.n[s_sample[i], a_sample[i]] - 1) + g) / self.n[s_sample[i], a_sample[i]]
                g -= r_sample[i]
                g /= self.gamma
                # print("s_sample,a",g)
            # print("number",self.n)
        return self.qvalue
    def mc_test(self):
        s = 0
        s_sample = []
        done = False
        flag = 0
        step_num = 0
        while False == done and step_num < 30:
            a = self.greedy_policy(self.qvalue, s)
            # 与环境交互
            s_next, r, done = self.yuanyang.transform(s, a)
            s_sample.append(s)
            s = s_next
            step_num += 1
        if s == 9:
            flag = 1
        return flag

if __name__=="__main__":
    yuanyang = YuanYangEnv()
    brain = MC_RL(yuanyang)
    # 探索初始化方法
    qvalue1 = brain.mc_learning_ei(num_iter=10000)
    #on-policy方法
    qvalue2=brain.mc_learning_on_policy(num_iter=10000, epsilon=0.2)
    print(qvalue2)
    #将行为值函数渲染出来
    yuanyang.action_value = qvalue2
    #测试学到的策略
    flag = 1
    s = 0
    # print(policy_value.pi)
    step_num = 0
    path = []
    # 将最优路径打印出来
    while flag:
        #渲染路径点
        path.append(s)
        yuanyang.path = path
        a = brain.greedy_policy(qvalue2,s)
        # a = agent.bolzman_policy(qvalue,s,0.1)
        print('%d->%s\t' % (s, a),qvalue2[s,0],qvalue2[s,1],qvalue2[s,2],qvalue2[s,3])
        yuanyang.bird_male_position = yuanyang.state_to_position(s)
        yuanyang.render()
        time.sleep(0.25)
        step_num += 1
        s_, r, t = yuanyang.transform(s, a)
        if t == True or step_num > 30:
            flag = 0
        s = s_
    #渲染最后的路径点
    yuanyang.bird_male_position = yuanyang.state_to_position(s)
    path.append(s)
    yuanyang.render()
    while True:
        yuanyang.render()






load.py

import pygame
import os
from pygame.locals import *
from sys import  exit
#得到当前工程目录
current_dir = os.path.split(os.path.realpath(__file__))[0]
print(current_dir)
#得到文件名
bird_file = current_dir+"/resources/bird.png"
obstacle_file = current_dir+"/resources/obstacle.png"
background_file = current_dir+"/resources/background.png"
#创建小鸟,
def load_bird_male():
    bird = pygame.image.load(bird_file).convert_alpha()
    return bird
def load_bird_female():
    bird = pygame.image.load(bird_file).convert_alpha()
    return bird
#得到背景
def load_background():
    background = pygame.image.load(background_file).convert()
    return background
#得到障碍物
def load_obstacle():
    obstacle = pygame.image.load(obstacle_file).convert()
    return obstacle

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值