強(qiáng)化學(xué)習(xí)環(huán)境升級 - 從gym到Gymnasium
作為強(qiáng)化學(xué)習(xí)最常用的工具,gym一直在不停地升級和折騰,比如gym[atari]變成需要要安裝接受協(xié)議的包啦,atari環(huán)境不支持Windows環(huán)境啦之類的,另外比較大的變化就是2021年接口從gym庫變成了gymnasium庫。讓大量的講強(qiáng)化學(xué)習(xí)的書中介紹環(huán)境的部分變得需要跟進(jìn)升級了。
不過,不管如何變,gym[nasium]作為強(qiáng)化學(xué)習(xí)的代理庫的總的設(shè)計思想沒有變化,變的都是接口的細(xì)節(jié)。
step和觀察結(jié)果
總體來說,對于gymnasium我們只需要做兩件事情:一個是初始化環(huán)境,另一個就是通過step函數(shù)不停地給環(huán)境做輸入,然后觀察對應(yīng)的結(jié)果。
初始化環(huán)境分為兩步。
第一步是創(chuàng)建gymnasium工廠中所支持的子環(huán)境,比如我們使用經(jīng)典的讓一個桿子不倒的CartPole環(huán)境:
import gymnasium as gym
env = gym.make("CartPole-v1")
第二步,我們就可以通過env的reset函數(shù)來進(jìn)行環(huán)境的初始化:
observation, info = env.reset(seed=42)
我們可以將observation打印出來,它一個4元組,4個數(shù)值分別表示:
- 小車位置
- 小車速度
- 棍的傾斜角度
- 棍的角速度
如果角度大于12度,或者小車位置超出了2.4,就意味著失敗了,直接結(jié)束。
小車的輸入就是一個力,要么是向左的力,要么是向右的力。0是向左推小車,1是向右推小車。
下面我們讓代碼跑起來。
首先我們通過pip來安裝gymnasium的包:
pip install gymnasium -U
安裝成功之后,
import gymnasium as gym
env = gym.make("CartPole-v1")
print(env.action_space)
observation, info = env.reset(seed=42)
steps = 0
for _ in range(1000):
action = env.action_space.sample()
observation, reward, terminated, truncated, info = env.step(action)
print(observation)
if terminated or truncated:
print("Episode finished after {} steps".format(steps))
observation, info = env.reset()
steps = 0
else:
steps += 1
env.close()
env.action_space輸出是Discrete(2)。也就是兩個離散的值0和1。前面我們介紹了,這分別代表向左和向右推動小車。
observation輸出的4元組,我們前面也講過了,像這樣:
[ 0.0273956 -0.00611216 0.03585979 0.0197368 ]
下面就是關(guān)鍵的step一步:
action = env.action_space.sample()
observation, reward, terminated, truncated, info = env.step(action)
剛才我們介紹了,CartPole的輸入只有0和1兩個值。我們采用隨機(jī)讓其左右動的方式來試圖讓小車不倒。
如果你覺得還是不容易懂的話,我們可以來個更無腦的,管它是什么情況,我們都一直往左推:
observation, reward, terminated, truncated, info = env.step(0)
基本上幾步就完了:
[ 0.02699083 -0.16518621 -0.00058549 0.3023946 ] 1.0 False False {}
[ 0.0236871 -0.36029983 0.0054624 0.5948928 ] 1.0 False False {}
[ 0.01648111 -0.5554978 0.01736026 0.88929135] 1.0 False False {}
[ 0.00537115 -0.750851 0.03514608 1.1873806 ] 1.0 False False {}
[-0.00964587 -0.94641054 0.0588937 1.4908696 ] 1.0 False False {}
[-0.02857408 -1.1421978 0.08871109 1.8013463 ] 1.0 False False {}
[-0.05141804 -1.3381925 0.12473802 2.1202288 ] 1.0 False False {}
[-0.07818189 -1.534317 0.16714258 2.4487078 ] 1.0 False False {}
[-0.10886823 -1.7304213 0.21611674 2.7876763 ] 1.0 True False {}
Episode finished after 8 steps
下面我們解釋下返回的5元組,observation就是位置4元組,reward是用于強(qiáng)化學(xué)習(xí)的獎勵,在本例中只要是不死就是1. terminated就是是否游戲結(jié)束了。
Truncated在官方定義中用于處理比如超時等特殊結(jié)束的情況。
truncated, info對于CartPole來說沒有用到。
搭建好了gymnasium環(huán)境之后,我們就可以進(jìn)行策略的升級與迭代了。
比如我們寫死一個策略,如果位置小于0則向右推,反之則向左推:
def action_pos(status):
pos, v, ang, va = status
#print(status)
if pos <= 0:
return 1
else:
return 0
或者我們根據(jù)角度來判斷,如果角度大于0則左推,反之則右推:
def action_angle(status):
pos, v, ang, va = status
#print(status)
if ang > 0:
return 1
else:
return 0
角度策略的完整代碼如下:
import gymnasium as gym
env = gym.make("CartPole-v1")
#env = gym.make("CartPole-v1",render_mode="human")
print(env.action_space)
#print(env.get_action_meanings())
observation, info = env.reset(seed=42)
print(observation,info)
def action_pos(status):
pos, v, ang, va = status
#print(status)
if pos <= 0:
return 1
else:
return 0
def action_angle(status):
pos, v, ang, va = status
#print(status)
if ang > 0:
return 1
else:
return 0
steps = 0
for _ in range(1000):
action = env.action_space.sample()
observation, reward, terminated, truncated, info = env.step(action_angle(observation))
print(observation, reward, terminated, truncated, info)
if terminated or truncated:
print("Episode finished after {} steps".format(steps))
observation, info = env.reset()
steps = 0
else:
steps += 1
env.close()
與老gym的主要區(qū)別
目前版本與之前gym的最主要區(qū)別在于step返回值從原來的4元組變成了5元組。
原來是observation, reward, done, info,而現(xiàn)在done變成了 terminated增加了truncated。
老版本的:
status, reward, done, info = env.step(0)
新版的:
observation, reward, terminated, truncated, info = env.step(0)
Atari游戲
我們通過gymnasium[atari]包來安裝atari游戲的gymnasium支持。
pip install gymnasium[atari]
通過get_action_meanings來獲取游戲支持的操作
之前的CartPole只知道是離散的兩個值。而Atari游戲則可支持獲取游戲支持的操作的含義:
['NOOP', 'FIRE', 'RIGHT', 'LEFT', 'RIGHTFIRE', 'LEFTFIRE']
rendor_mode
另外,針對于Atari游戲,render_mode現(xiàn)在是必選項了。要指定是顯示成人類可看的human模式,還是只輸出rgb_array的模式。
完整例子
我們以乒乓球游戲為例,組裝讓其運(yùn)行起來:文章來源:http://www.zghlxwxcb.cn/news/detail-480177.html
import gymnasium as gym
env = gym.make("ALE/Pong-v5", render_mode="human")
observation, info = env.reset()
print(env.get_action_meanings())
scores = 0
for _ in range(1000):
action = env.action_space.sample() # agent policy that uses the observation and info
observation, reward, terminated, truncated, info = env.step(action)
#print(observation, reward, terminated, truncated, info)
if terminated or truncated:
print("Episode finished after {} steps".format(scores))
observation, info = env.reset()
scores = 0
else:
scores +=1
env.close()
完整的游戲支持列表可以在https://gymnasium.farama.org/environments/atari/ 官方文檔中查到。文章來源地址http://www.zghlxwxcb.cn/news/detail-480177.html
到了這里,關(guān)于強(qiáng)化學(xué)習(xí)環(huán)境升級 - 從gym到Gymnasium的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!