[强化学习]--悬崖漫步

Q-Learning是一种在强化学习中广泛应用的算法,它属于值迭代方法的一种,能够通过与环境交互来学习最优策略。Q-Learning的核心思想是学习一个动作价值函数(Q-Function),这个函数可以预测从某个状态采取某个动作后所能获得的长期奖励。

1、Q-Learning的基本原理

Q-Learning的目标是找到一个Q表(Q-table),它表示了在给定状态下执行每个可能动作的价值。这个表中的每个条目Q(s,a)Q(s,a)代表了从状态s出发,执行动作a后,预期可得的累积奖励(即折扣后的未来奖励总和)。

2、更新规则

Q-Learning使用以下更新规则来逐渐改进Q表中的估计:

3、ε-greedy策略

为了平衡探索(exploration)和利用(exploitation),Q-Learning通常采用ε-greedy策略。这意味着以概率ε随机选择动作进行探索,以概率1−ε选择当前Q值最高的动作进行利用。随着学习的进行,ε值会逐渐减小,使得算法更加依赖于已有的知识。

还有一些其他的策略,比如上置信界以及汤普森,后面有机会再说。。。。。

4、收敛性

Q-Learning的一个重要特性是,在满足一定的条件(如充分的探索和有限的状态-动作空间)下,它能够收敛到最优策略,悬崖漫步就看总反馈值是否收敛。

4、实施步骤

  1. 初始化Q表为零或任意小数值。
  2. 对于每个episode:
    • 观察初始状态s0。
    • 对于每个时间步:
      • 根据ε-greedy策略选择动作at​。
      • 执行动作atat​,观察奖励rt+1​和新状态st+1​。
      • 使用Q-Learning更新规则更新Q(st,at)。
      • 将st+1设置为新的当前状态st​。
  3. 当达到终止状态时,结束该episode,并开始下一个episode。

Q-Learning在实际应用中非常广泛,尤其是在游戏、机器人控制和推荐系统等领域。然而,当状态空间或动作空间非常大时,直接使用Q-table的方式可能不再可行,这时通常会使用函数逼近的方法(如深度Q网络DQN)来近似Q函数。

以悬崖漫步游戏环境为例:

import numpy as np
import gymnasium as gym
import matplotlib.pyplot as plt

# 定义环境
env = gym.make('CliffWalking-v0', render_mode="human")
# 定义4个动作 上下左右
ACTIONS = env.action_space.n

# 定义环境参数
ROWS = 4
COLS = 12
# 定义 Q-learning 参数
EPISODES = 500
ALPHA = 0.1  # 初始学习率
GAMMA = 0.99  # 折扣因子
EPSILON = 0.1  # 探索率
loss_count = 0  # 值随时间衰减的 -贪婪算法
# 初始化 Q-table
q_table = np.zeros([ROWS * COLS, ACTIONS])

# 创建列表用于存储每一轮的总奖励
rewards_list = []


# 定义一个函数根据 Q-table 和 ε-greedy 策略选择动作
def choose_action(state, q_table, epsilon):
    global loss_count
    loss_count += 1
    if np.random.random() < 1 / loss_count:
        # 随机选择一个动作
        return np.random.randint(ACTIONS)
    else:
        # 选择具有最大 Q 值的动作
        return np.argmax(q_table[state])


# 定义一个函数实现 Q-learning 算法
def q_learning():
    # 进行多次训练以更新 Q-table
    global episode
    for episode in range(EPISODES):
        # 从起始状态开始
        state, _ = env.reset()
        done = False
        count = 0
        steps = 0
        total_reward = 0
        # 在每个训练回合中不断采取动作,直到达到终点
        print("Episode Start: {}".format(episode))
        while not done and count < 200:
            count += 1
            # 选择一个动作
            action_index = choose_action(state, q_table, EPSILON)
            # 获取下一个状态、奖励和是否到达终点
            next_state, reward, done, _, _ = env.step(action_index)
            total_reward += reward
            steps += 1

            # 更新 Q-table
            q_table[state][action_index] = q_table[state][action_index] + ALPHA * (
                    reward + GAMMA * np.max(q_table[next_state]) - q_table[state][action_index]
            )
            # 更新当前状态
            state = next_state
        # 打印每一集的总结
        print(f"Episode {episode + 1} finished after {steps} steps with total reward {total_reward}")
        # 将这一轮的总奖励添加到列表中
        rewards_list.append(total_reward)

    # 绘制每一轮的总奖励
    plt.figure(figsize=(10, 5))
    plt.plot(rewards_list)
    plt.title('Total Reward per Episode')
    plt.xlabel('Episode')
    plt.ylabel('Total Reward')
    plt.grid(True)
    plt.show()
    # 关闭环境
    env.close()
    # 返回训练好的 Q-table
    return q_table


q = q_learning()

print(q)

随着训练次数的增加,ε值会逐渐减小,使得算法更加依赖于已有的知识,差不多30次左右小人就能吃到饼干了 

然后从最终的总奖励值图可以看到,在300次左右就能达到收敛

对比使用固定ε值的代码,可以看到收敛趋势是有 但是效果并不好

增加了episode训练次数也不行

重点还是对于Q表的更新策略

公式!!!

5、gym的环境原理代码如下:

熟悉环境的设置有利于我们去应用在其他的项目上,所以gym的原理需要了解,只不过gym对环境进行了gui的封装 

import numpy as np
import matplotlib.pyplot as plt

class CliffWalkingEnv:
    def __init__(self):
        self.grid_size = 4
        self.start = (0, 0)
        self.goal = (0, self.grid_size - 1)
        self.cliff = [(i, self.grid_size - 1) for i in range(1, self.grid_size - 1)]
        self.agent_position = self.start

    def step(self, action):
        # 动作编码:0=up, 1=down, 2=left, 3=right
        dx, dy = [(0, -1), (0, 1), (-1, 0), (1, 0)][action]
        x, y = self.agent_position
        new_x, new_y = x + dx, y + dy

        # 检查新位置是否有效
        if 0 <= new_x < self.grid_size and 0 <= new_y < self.grid_size:
            self.agent_position = (new_x, new_y)
        else:
            return self.agent_position, -1, False

        # 检查是否落在悬崖上
        if self.agent_position in self.cliff:
            self.agent_position = self.start
            return self.agent_position, -100, False

        # 检查是否到达目标
        if self.agent_position == self.goal:
            return self.agent_position, 0, True

        return self.agent_position, -1, False

    def reset(self):
        self.agent_position = self.start
        return self.agent_position

  • 13
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值