Coding Island

编码之岛

【强化学习笔记】从 “酒鬼回家” 认识Q Learning算法

1.背景

现在笔者来讲一个利用Q-learning 方法帮助酒鬼回家的一个小例子, 例子的环境是一个一维世界, 在世界的右边是酒鬼的家。这个酒鬼因为喝多了,根本不记得回家的路,只是根据自己的直觉一会向左走、一会向右走。酒鬼最后只要成功回家, 然后以后就记住了回家的方法, 这就是他用强化学习所学习到的行为。

-w- – – – – H
H 是酒鬼的家, w 是酒鬼所处的位置

2.Q Learning介绍

3.代码

预设值

import numpy as np
import pandas as pd
import time

np.random.seed(2)   # reproducible

N_STATES = 6   # 最开始酒鬼离家的距离,即1维世界的宽度
ACTIONS = ['left', 'right']     # 探索者的可用动作
EPSILON = 0.9   # 贪婪度 greedy
ALPHA = 0.1     # 学习率
GAMMA = 0.9    # 奖励递减值
MAX_EPISODES = 15   # 最大回合数
FRESH_TIME = 0.2    # 移动间隔时间

q表

def build_q_table(n_states,actions):
    table = pd.DataFrame(
        np.zeros((n_states,len(actions))),
        columns=actions,
    )
    print(table)
    return table

选择行为

# 在某个 state 地点, 选择行为
def choose_action(state, q_table):
    state_actions = q_table.iloc[state, :]  # 选出这个 state 的所有 action 值
    if (np.random.uniform() > EPSILON) or (state_actions.all() == 0):  # 非贪婪 or 或者这个 state 还没有探索过
        action_name = np.random.choice(ACTIONS)
    else:
        action_name = state_actions.argmax()    # 贪婪模式
    return action_name

环境反馈

def get_env_feedback(S, A):
    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) + ['H']   # '---------H' our environment
    if S == 'terminal':
        interaction = 'Episode %s: total_steps = %s' % (episode+1, step_counter)
        print('\r{}'.format(interaction), end='')
        time.sleep(1)
        print('\r                                ', end='')
    else:
        env_list[S] = 'w'
        interaction = ''.join(env_list)
        print('\r{}'.format(interaction), end='')
        time.sleep(FRESH_TIME)

强化学习主循环

def rl():
    q_table = build_q_table(N_STATES, ACTIONS)  # 初始 q table
    for episode in range(MAX_EPISODES):     # 回合
        step_counter = 0
        S = 0   # 回合初始位置
        is_terminated = 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]    # 估算的(状态-行为)值
            if S_ != 'terminal':
                q_target = R + GAMMA * q_table.iloc[S_, :].max()   #  实际的(状态-行为)值 (回合没结束)
            else:
                q_target = R     #  实际的(状态-行为)值 (回合结束)
                is_terminated = True    # terminate this episode

            q_table.loc[S, A] += ALPHA * (q_target - q_predict)  #  q_table 更新
            S = S_  # 酒鬼移动到下一个 state

            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)

完整代码移步Github

点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注