24/8/15算法笔记 项目练习冰湖

import gym
from matplotlib import pyplot as plt
%matplotlib inline
import os
os.environ['SDL_VIDEODRIVER']='dummy'
#设置环境变量 SDL_VIDEODRIVER='dummy' 是在使用基于 SDL (Simple DirectMedia Layer) 的应用程序时,告诉应用程序不使用任何视频驱动程序。这通常用于无头环境(headless environment)或自动化脚本,其中不需要图形界面。
#创建环境
#is_slippery控制会不会滑
#map_name决定地图的尺寸,还可以取8X8
#desc决定地形
env = gym.make('FrozenLake-v1',
               is_slippery=False,
               map_name='4X4',
               desc=['SFFF','FHFH','FFFH','HFFG'])
env.reset()   #用于重置环境状态到其初始状态的方法,并准备开始一个新的周期(episode)。

#解封装才能访问状态转移矩阵p
env.env.unwrapped

#打印游戏
def show():
    plt.imshow(env.render(mode='rgb_array'))
    plt.show()

游戏信息

#查看冰湖这个游戏的状态列表
#一共4*4=16个状态
#每个状态下都可以执行4个动作
#每个动作执行完,都有概率得到3个结果
#(0.333333333333,0,0.0,False)这个数据结构表示(概率,下个状态,奖励,是否结束)
len(env.P),env.P[0]

初始化values和pi

import numpy as np

#初始化每个格子的价值
values = np.zeros(16)

#初始化每个格子下采用动作的概率
pi = np.ones([16,4])*0.25

#两个算法都是可以的
algorithm = '策略迭代'
algorithm = '价值迭代'

values,pi

Q函数

#计算qsa
def get_qsa(state,action):
    value = 0.0
    
    #每个动作都会有三个不同的结果,这里要按概率把他们加权求和
    for prop,next_state,reward,over in env.P[state][action]:
        
        #计算下个状态的分数,取values当中记录的分数,再打个折扣
        next_value = values[next_state]*0.9
        
        #如果下个状态是终点或者陷阱,则下个状态的分数是0
        if over:
            next_value = 0
        
        #动作的分数就是reward,和下个状态的分数相加就是最终分数
        next_value+=reward
        
        #因为下个状态是概率出现了,所以这里要乘以概率
        next_value*=prop
        
        value+=next_value
    
    return value
get_qsa(0,0)
        
#策略评估
def get_values():
    #初始化一个新的values,重新评估所有格子的分数
    new_values = np.zeros([16])
    
    #遍历所有格子
    for state in range(16):
        
        #计算当前格子4个动作分别的分数
        action_value = np.zeros(4)
        
        #遍历所有动作
        for action in range(4):
            action_value[action] = get_qsa(state,action)
        if algorithm =='策略迭代':
            #每个动作的分数和它的概率相乘
            action_value*=pi[state]
            #最后这个格子的分数,等于该格子下所有动作的分数求和
            new_values[state] = action_value.sum()
        if algorithm=='价值迭代':
            #求每一个格子的分数,等于该格子下所有动作的最大分数
            new_values[state] = action_value.max()
    return new_values
get_values()

#策略提升算法
def get_pi():
    #重新初始化每个格子下采用动作的概率,重新评估
    new_pi = np.zeros([16,4])
    
    #遍历所有格子
    for state in range(16):
        
        #计算当前格子4个动作分别的分数
        action_value = np.zeros(4)
        
        #遍历所有动作
        for action in range(4):
            action_value[action] = get_qsa(state,action)
            
        #计算当前state下,达到最大分数的动作有几个
        count = (action_value ==action_value.max()).sum()
        
        #让这些动作均分概率
        for action in range(4):
            if action_value[action] ==action_value.max():
                new_pi[state,action] = 1/count
            else:
                new_pi[state,action] = 0
    return new_pi
#循环迭代策略评估和策略提升,寻找最优解
for _ in range(10):
    for _ in range(100):
        values = get_values()
    pi = get_pi()
values,pi

#打印每个格子的策略
def print_pi():
    #遍历所有格子
    for row in range(4):
        line=' '
        for col in range(4):
            state = row*4+col
            if(row==1 and col==1)or(row==1 and col==3)or(
                row ==2 and col ==2)or(row ==3 and col==0):
                line+='O'
                continue
            if row==3 and col==3:
                line+='*'
                continue
            line+='上下左右'[pi[state].argmax()]
        print(line)
        
print_pi()

测试函数

from IPython import display
import time

def play():
    env.reset()
    
    #起点在0
    index= 0
    
    #最多玩N步
    for i in range(200):
        #选择一个动作
        action =np.random.choice(np.arange(4),size= 1,p=pi[index])[0]
        
        #执行动作
        index,reward,terminated,truncated,_=env.step(action)
        
        #打印动画
        display.clear_output(wait=True)
        time.sleep(1)
        show()
        
        #获取当前状态,如果状态时终点或者陷阱则终止
        if terminated or truncated:
            break
            
    print(i)
play()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值