先贴源码:
莫烦python强化学习
此算法实现的背景是一个人找宝藏T,且只有向左和向右两种action。如下图:
![](https://img.haomeiwen.com/i7672742/3981aabf46240f01.png)
用到的三个库:numpy、pandas、time。
import numpy as np
import pandas as pd
import time # 控制探索者移动速度
生成相同的随机序列(这句代码产生的效果还没弄明白):
np.random.seed(2) # 如果括号内的数字相同,则可以使numpy随机生成的序列相同
设置一些算法需要的常量:
N_STATES = 6 #共有6种状态,如图1所示,有6个格子
ACTIONS = ['left', 'right'] # 两种动作,向左向右
EPSILON = 0.9 # 90%选择最优的动作,10%选择随机的动作
ALPHA = 0.1 # 学习率
GAMMA = 0.9 # 衰减率
MAX_EPISODES = 13 # 最大回合数
FRESH_TIME = 0.3 # 每次移动间隔时间
本问题一共需要5个模块,举一反三,再复杂的问题也大致需要这5个模块。
- 1.Q表的构建
- 2.环境的构建和更新(更新主要用于展示探索的每一步效果可视化)
- 3.奖励机制或者说与环境的交互
- 4.动作的选择
- 5.Q-Learning算法主体
Q表的构建
def build_q_table(n_states, actions):
table = pd.DataFrame(
np.zeros((n_states, len(actions))), # Q表的行和列 也就是6行2列
columns=actions, # 列名字 也就是right left
)
# print(table) # 显示表格
return table
动作的选择
def choose_action(state, q_table):
# This is how to choose an action
state_actions = q_table.iloc[state, :] # 将此时状态的Q表 行值赋给state_actions
if (np.random.uniform() > EPSILON) or ((state_actions == 0).all()): # 如果大于0.9这个概率或者全部Q值都为0的时候我们进行随机选择动作
action_name = np.random.choice(ACTIONS) #随机选择动作
else: #如果不是随机选择的话
action_name = state_actions.idxmax() # 就选Q值最大的那个动作
return action_name
环境的交互
def get_env_feedback(S, A):
# This is how agent will interact with the environment
if A == 'right': # 如果动作为右
if S == N_STATES - 2: # 测试是否到达终点
S_ = 'terminal'
R = 1 #获得奖励
else:
S_ = S + 1 #向右移动一格
R = 0 #没有奖励
else: # 如果动作为左
R = 0 #没有奖励
if S == 0: # 如果此时在最左边
S_ = S # 不动
else: # 如果没有 则向左移动一格
S_ = S - 1
return S_, R #返回此时的状态 和 奖励值
环境更新
def update_env(S, episode, step_counter):
# This is how environment be updated
env_list = ['-']*(N_STATES-1) + ['T'] #我们的环境是这个样子: '-----T'
if S == 'terminal': #如果已经到达终点 取得宝藏 那么就输出当前第几次探索episode 和 一共走的步数steps
interaction = 'Episode %s: total_steps = %s' % (episode+1, step_counter)
print('\r{}'.format(interaction), end='')
time.sleep(2) # 时间间隔2秒
print('\r ', end='')
else:
env_list[S] = 'o' # 如果没有到终点 那么就把当前agent的位置由'-'改为'o',更好的可视化探索过程
interaction = ''.join(env_list) #将序列连接成字符串 并且 输出到屏幕
print('\r{}'.format(interaction), end='')
time.sleep(FRESH_TIME) # 移动速度间隔为0.2秒
主函数体
def rl():
# main part of RL loop
q_table = build_q_table(N_STATES, ACTIONS) #建立Q表
for episode in range(MAX_EPISODES): # 设置探索次数
step_counter = 0 #初始化步数
S = 0 #初始化状态
is_terminated = False #将到达终点设为false以结束循环
update_env(S, episode, step_counter) #更新环境
while not is_terminated: # 若没有探索到宝藏则一直探索
A = choose_action(S, q_table) #选取动作
S_, R = get_env_feedback(S, A) # 与环境交互 获取下一步的状态和奖励
q_predict = q_table.loc[S, A] # 获取Q表的[S,A]的值
if S_ != 'terminal': #如果下一步不是终点
q_target = R + GAMMA * q_table.iloc[S_, :].max() # 这是公式的一部分
else:
q_target = R # 若下一步是终点 因为终点处的状态没有可选的动作 所以公式后半部分都为0
is_terminated = True # terminate this episode
q_table.loc[S, A] += ALPHA * (q_target - q_predict) # 更新Q[S,A]值
S = S_ # 更新到下一个状态
update_env(S, episode, step_counter+1) # 更新环境
step_counter += 1
return q_table
if __name__ == '__main__':
q_table = rl()
print('\r\nQ-table:\n')
print(q_table)
网友评论