【人工智能II】实验2 强化学习Q-Learning算法
生活随笔
收集整理的這篇文章主要介紹了
【人工智能II】实验2 强化学习Q-Learning算法
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
強(qiáng)化學(xué)習(xí)Q-Learning算法
- 核心思想
- 實(shí)驗(yàn)原理
- 實(shí)驗(yàn)流程圖
- 實(shí)驗(yàn)分析
- 理解Q-Learning算法
- GYM庫
- 更換實(shí)驗(yàn)環(huán)境
- 實(shí)驗(yàn)代碼
- Q-Learning:
- Sarsa代碼
搞不懂我一個(gè)本科生為啥要學(xué)這種必修課,無能哐哐捶地
:(
實(shí)驗(yàn)是在百度的Ai Studio上學(xué)習(xí)操作的
核心思想
智能體agent在環(huán)境environment中學(xué)習(xí),根據(jù)環(huán)境的狀態(tài)state(或觀測到的observation),執(zhí)行動(dòng)作action,并根據(jù)環(huán)境的反饋reward(獎(jiǎng)勵(lì))來指導(dǎo)更好的動(dòng)作。強(qiáng)化學(xué)習(xí)通過不斷的試錯(cuò)探索,吸取經(jīng)驗(yàn)和教訓(xùn),持續(xù)不斷地優(yōu)化策略,以從環(huán)境中拿到更好的反饋。
實(shí)驗(yàn)原理
- Q-learning學(xué)習(xí)特定的state下,特定action的價(jià)值Q,采用Q表格的方式存儲Q值(狀態(tài)動(dòng)作價(jià)值)。在訓(xùn)練中為了更好的探索環(huán)境,采用ε-greedy方式來訓(xùn)練,有一定概率隨機(jī)選擇動(dòng)作輸出。
- Q-learning是離線(off-policy)的更新方式,更新learn()時(shí)無需獲取下一步實(shí)際做出的動(dòng)作next_action,并假設(shè)下一步動(dòng)作是取最大Q值的動(dòng)作。其具體更新公式如下:
- 1、建立Q表,行是每種狀態(tài),列是每種狀態(tài)的行為,值是某狀態(tài)下某行為估計(jì)獲得的獎(jiǎng)勵(lì)
2.每次進(jìn)行狀態(tài)轉(zhuǎn)移時(shí)有e_greedy概率選當(dāng)前狀態(tài)最優(yōu)方法,有 1- e_greedy選隨機(jī)方法
3.選完之后就更新當(dāng)前狀態(tài)下對應(yīng)所選行為的Q值(估計(jì)值)
4.更新方法:其自身= 其自身+學(xué)習(xí)率*(估計(jì)-現(xiàn)實(shí)) —> (實(shí)際更新 = 實(shí)際未更新+學(xué)習(xí)率*(預(yù)測-實(shí)際發(fā)生))
實(shí)驗(yàn)流程圖
實(shí)驗(yàn)分析
理解Q-Learning算法
GYM庫
- GYM是強(qiáng)化學(xué)習(xí)中經(jīng)典的環(huán)境庫,它將環(huán)境交互接口規(guī)范化為:
重置環(huán)境reset()、交互step()、渲染render()。 - gym.make()生成環(huán)境。在示例中,CliffWalking-v0生成懸崖環(huán)境。o代表正常可通行路徑,x代表受控制的人物,C代表懸崖,T代表目標(biāo)。
reset()重置(初始化)環(huán)境。 - step()控制進(jìn)行一次動(dòng)作。在示例中,傳入?yún)?shù):0代表上,1代表右,2代表下,3代表左;返回結(jié)果:obs觀測結(jié)果,此處為所處方格編號;reward環(huán)境反饋,此處為了最優(yōu)化路徑,每走一步反饋-1,跌落峽谷反饋-100;down是否結(jié)束,此處為是否走到終點(diǎn),布爾變量;info額外信息。
- render()繪制當(dāng)前環(huán)境
- predict()方法:輸入觀察值observation(或者說狀態(tài)state),輸出動(dòng)作值
- sample()方法:在predict()方法基礎(chǔ)上使用ε-greedy增加探索
- learn()方法:輸入訓(xùn)練數(shù)據(jù),完成一輪Q表格的更新
- run_episode():agent在一個(gè)episode中訓(xùn)練的過程,使用agent.sample()與環(huán)境交互,使用agent.learn()訓(xùn)練Q表格。
- test_episode():agent在一個(gè)episode中測試效果,評估目前的agent能在一個(gè)episode中拿到多少總reward。
- 在懸崖環(huán)境中,目的是尋找最快路徑從左下角起點(diǎn)到右下角終點(diǎn),跌落懸崖會返回起點(diǎn)。Agent是和環(huán)境environment交互的主體。
更換實(shí)驗(yàn)環(huán)境
- 將CliffWalking懸崖環(huán)境更換為FrozenLake-v0冰面行走
- 使用gym的FrozenLake-V0環(huán)境進(jìn)行訓(xùn)練,F為frozen lake,H為hole,S為起點(diǎn),G為終點(diǎn),掉到hole里就游戲結(jié)束,可以有上每一步可以有上下左右四個(gè)方向的走法,只有走到終點(diǎn)G才能得1分。
實(shí)驗(yàn)代碼
Q-Learning:
import gym import numpy as np class QLearningAgent(object):def __init__(self, obs_n, act_n, learning_rate=0.01, gamma=0.9, e_greed=0.1):self.act_n = act_n # 動(dòng)作維度,有幾個(gè)動(dòng)作可選self.lr = learning_rate # 學(xué)習(xí)率self.gamma = gamma # reward的衰減率self.epsilon = e_greed # 按一定概率隨機(jī)選動(dòng)作self.Q = np.zeros((obs_n, act_n))# 根據(jù)輸入觀察值,采樣輸出的動(dòng)作值,帶探索def sample(self, obs):if np.random.uniform(0, 1) < (1.0 - self.epsilon): #根據(jù)table的Q值選動(dòng)作action = self.predict(obs)else:action = np.random.choice(self.act_n) #有一定概率隨機(jī)探索選取一個(gè)動(dòng)作return action# 根據(jù)輸入觀察值,預(yù)測輸出的動(dòng)作值def predict(self, obs):Q_list = self.Q[obs, :]maxQ = np.max(Q_list)action_list = np.where(Q_list == maxQ)[0] # maxQ可能對應(yīng)多個(gè)actionaction = np.random.choice(action_list)return action# 學(xué)習(xí)方法,也就是更新Q-table的方法def learn(self, obs, action, reward, next_obs, done):""" off-policyobs: 交互前的obs, s_taction: 本次交互選擇的action, a_treward: 本次動(dòng)作獲得的獎(jiǎng)勵(lì)rnext_obs: 本次交互后的obs, s_t+1done: episode是否結(jié)束"""predict_Q = self.Q[obs, action]if done:target_Q = reward # 沒有下一個(gè)狀態(tài)了else:target_Q = reward + self.gamma * np.max(self.Q[next_obs, :]) # Q-learningself.Q[obs, action] += self.lr * (target_Q - predict_Q) # 修正q# 把 Q表格 的數(shù)據(jù)保存到文件中def save(self):npy_file = './q_table.npy'np.save(npy_file, self.Q)print(npy_file + ' saved.')# 從文件中讀取數(shù)據(jù)到 Q表格def restore(self, npy_file='./q_table.npy'):self.Q = np.load(npy_file)print(npy_file + ' loaded.') def run_episode(env, agent, render=False):total_steps = 0 # 記錄每個(gè)episode走了多少steptotal_reward = 0obs = env.reset() # 重置環(huán)境, 重新開一局(即開始新的一個(gè)episode)while True:action = agent.sample(obs) # 根據(jù)算法選擇一個(gè)動(dòng)作next_obs, reward, done, _ = env.step(action) # 與環(huán)境進(jìn)行一個(gè)交互# 訓(xùn)練 Q-learning算法agent.learn(obs, action, reward, next_obs, done)obs = next_obs # 存儲上一個(gè)觀察值total_reward += rewardtotal_steps += 1 # 計(jì)算step數(shù)if render:env.render() #渲染新的一幀圖形if done:breakreturn total_reward, total_stepsdef test_episode(env, agent, render=False):total_reward = 0obs = env.reset()while True:action = agent.predict(obs) # greedynext_obs, reward, done, _ = env.step(action)total_reward += rewardobs = next_obsif render:env.render()if done:break return total_reward # 使用gym創(chuàng)建懸崖環(huán)境 env = gym.make("CliffWalking-v0") # 0 up, 1 right, 2 down, 3 left# 創(chuàng)建一個(gè)agent實(shí)例,輸入超參數(shù) agent = QLearningAgent(obs_n=env.observation_space.n,act_n=env.action_space.n,learning_rate=0.1,gamma=0.9,e_greed=0.1)# 訓(xùn)練500個(gè)episode print('Training...') for episode in range(500):ep_reward, ep_steps = run_episode(env, agent, False)print('Episode %s: steps = %s , reward = %.1f' % (episode, ep_steps, ep_reward)) # 取消注釋以展示訓(xùn)練過程 print('Done.') # 查看算法效果,輸出行走路徑 test_reward = test_episode(env, agent, True) print('test reward = %.1f' % (test_reward))Sarsa代碼
import gym import numpy as np import time # agent.py class SarsaAgent(object):def __init__(self, obs_n, act_n, learning_rate=0.01, gamma=0.9, e_greed=0.1):self.act_n = act_n # 動(dòng)作維度,有幾個(gè)動(dòng)作可選self.lr = learning_rate # 學(xué)習(xí)率self.gamma = gamma # reward的衰減率self.epsilon = e_greed # 按一定概率隨機(jī)選動(dòng)作self.Q = np.zeros((obs_n, act_n))#生成二維得Q表格,狀態(tài)為行,動(dòng)作為列,所謂狀態(tài)即obs觀測者,在Q表格中表示為環(huán)境格子得總數(shù)#Q表格的行是環(huán)境格子的總數(shù),比如CliffWalking的Q表格有4*12=48行,FrozenLake的Q表格有4*4=16行。#Q結(jié)構(gòu)是“環(huán)境格子數(shù)”*“動(dòng)作數(shù)”。Q值即對應(yīng)的每個(gè)格子采用某個(gè)動(dòng)作所獲得的終極回報(bào)# 根據(jù)輸入觀察值,采樣輸出的動(dòng)作值,帶探索def sample(self, obs):#if條件是根據(jù)狀態(tài)選擇能輸出最大Q值的動(dòng)作,有90%的機(jī)會執(zhí)行exploitationif np.random.uniform(0, 1) < (1.0 - self.epsilon): #根據(jù)table的Q值選動(dòng)作action = self.predict(obs)else:#有10%的機(jī)會執(zhí)行exploration探索action = np.random.choice(self.act_n) #有一定概率隨機(jī)探索選取一個(gè)動(dòng)作return action# 根據(jù)輸入觀察值,預(yù)測輸出的動(dòng)作值,輸出能產(chǎn)生最大Q值得actiondef predict(self, obs):Q_list = self.Q[obs, :]maxQ = np.max(Q_list)action_list = np.where(Q_list == maxQ)[0] # maxQ可能對應(yīng)多個(gè)actionaction = np.random.choice(action_list)#多個(gè)action則隨機(jī)選一個(gè)return action# 學(xué)習(xí)方法,也就是更新Q-table的方法def learn(self, obs, action, reward, next_obs, next_action, done):""" on-policy 即求target_Q時(shí)使用的self.Q[next_obs, next_action]是下一個(gè)obs-狀態(tài)實(shí)際sample到的action所對應(yīng)的Q。即下一個(gè)obs和實(shí)際動(dòng)作對應(yīng)的Qobs: 交互前的obs, s_taction: 本次交互選擇的action, a_treward: 本次動(dòng)作獲得的獎(jiǎng)勵(lì)rnext_obs: 本次交互后的obs, s_t+1next_action: 根據(jù)當(dāng)前Q表格, 針對next_obs會選擇的動(dòng)作, a_t+1done: episode是否結(jié)束"""predict_Q = self.Q[obs, action]#獲取對應(yīng)單元格在動(dòng)作action下的Q值if done:target_Q = reward # 沒有下一個(gè)狀態(tài)了else:target_Q = reward + self.gamma * self.Q[next_obs, next_action] # Sarsaself.Q[obs, action] += self.lr * (target_Q - predict_Q) # 修正q# 保存Q表格數(shù)據(jù)到文件def save(self):npy_file = './q_table.npy'np.save(npy_file, self.Q)print(npy_file + ' saved.')# 從文件中讀取Q值到Q表格中def restore(self, npy_file='./q_table.npy'):self.Q = np.load(npy_file)print(npy_file + ' loaded.') def run_episode(env, agent, render=False):total_steps = 0 # 記錄每個(gè)episode走了多少steptotal_reward = 0obs = env.reset() # 重置環(huán)境, 重新開一局(即開始新的一個(gè)episode)action = agent.sample(obs) # 根據(jù)算法選擇一個(gè)動(dòng)作while True:next_obs, reward, done, _ = env.step(action) # 與環(huán)境進(jìn)行一個(gè)交互,由action->state與策略無關(guān),#由環(huán)境決定,由環(huán)境的狀態(tài)轉(zhuǎn)移概率決定。next_action = agent.sample(next_obs) # 根據(jù)算法選擇一個(gè)動(dòng)作,#由策略決定,一般平衡exploration和exploitation# 訓(xùn)練 Sarsa 算法,更新Q值表agent.learn(obs, action, reward, next_obs, next_action, done)action = next_action #該動(dòng)作是下次實(shí)際采用動(dòng)作obs = next_obs # 存儲上一個(gè)觀察值total_reward += rewardtotal_steps += 1 # 計(jì)算step數(shù)if render:env.render() #渲染新的一幀圖形if done:breakreturn total_reward, total_stepsdef test_episode(env, agent):total_reward = 0obs = env.reset()while True:action = agent.predict(obs) # 測試階段不需要探索,greedynext_obs, reward, done, _ = env.step(action)total_reward += rewardobs = next_obstime.sleep(0.5)env.render()if done:breakreturn total_reward # 使用gym創(chuàng)建懸崖環(huán)境 env = gym.make("CliffWalking-v0") # 0 up, 1 right, 2 down, 3 left# 創(chuàng)建一個(gè)agent實(shí)例,輸入超參數(shù) agent = SarsaAgent(obs_n=env.observation_space.n,act_n=env.action_space.n,learning_rate=0.1,gamma=0.9,e_greed=0.1)# 訓(xùn)練500個(gè)episode,打印每個(gè)episode的分?jǐn)?shù) for episode in range(500):ep_reward, ep_steps = run_episode(env, agent, False)print('Episode %s: steps = %s , reward = %.1f' % (episode, ep_steps, ep_reward)) # 全部訓(xùn)練結(jié)束,查看算法效果 test_reward = test_episode(env, agent) print('test reward = %.1f' % (test_reward))總結(jié)
以上是生活随笔為你收集整理的【人工智能II】实验2 强化学习Q-Learning算法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [米家]窗帘电机【立创开源】
- 下一篇: 乐高机器人走进图书馆活动方案_欢迎参加“