Microsoft ML-For-Beginners项目:强化学习之CartPole平衡问题详解

Microsoft ML-For-Beginners项目:强化学习之CartPole平衡问题详解

ML-For-Beginners 微软出品的面向初学者的机器学习课程,提供了一系列实践项目和教程,旨在帮助新手逐步掌握Python、Azure ML等工具进行数据预处理、模型训练及部署。 ML-For-Beginners 项目地址: https://gitcode.com/gh_mirrors/ml/ML-For-Beginners

引言:从离散到连续状态空间的跨越

在之前的强化学习课程中,我们学习了如何解决离散状态空间的问题。但在现实世界中,很多问题都涉及到连续状态空间,比如自动驾驶、机器人控制等。本文将通过Microsoft ML-For-Beginners项目中的CartPole平衡问题,带您深入理解如何将Q-Learning应用于连续状态空间。

CartPole问题概述

CartPole是一个经典的强化学习基准问题,模拟了一个水平移动的小车顶部竖立着一根杆子。我们的目标是通过左右移动小车来保持杆子竖直不倒。这个问题看似简单,却包含了强化学习的核心挑战:

  • 连续状态空间:杆子的角度、位置等都是连续值
  • 延迟奖励:只有在杆子倒下时才会得到负面反馈
  • 实时控制:需要在每个时间步做出正确的动作

环境搭建与基础认知

1. OpenAI Gym环境初始化

OpenAI Gym提供了标准化的强化学习环境接口,我们首先初始化CartPole环境:

import gym
env = gym.make("CartPole-v1")

环境初始化后,我们需要了解两个关键属性:

  • 动作空间(Action Space):离散的,包含两个动作(左/右)
  • 观察空间(Observation Space):四个连续值(小车位置、速度、杆角度、角速度)

2. 环境交互基础

与环境的交互遵循"观察-动作-反馈"循环:

obs = env.reset()  # 重置环境,获取初始观察值
done = False
while not done:
    action = env.action_space.sample()  # 随机选择动作
    obs, reward, done, info = env.step(action)  # 执行动作

状态离散化:连续到离散的转换

Q-Learning需要离散的状态空间,因此我们需要将连续的观察值离散化。这里介绍两种主要方法:

方法一:线性缩放取整

def discretize(x):
    return tuple((x/np.array([0.25, 0.25, 0.01, 0.1])).astype(np.int))

这种方法简单直接,通过将各维度值除以特定系数后取整,但可能导致状态空间过大。

方法二:分箱离散化

def create_bins(interval, num_bins):
    return np.linspace(interval[0], interval[1], num_bins+1)

bins = [create_bins(intv, num) for intv, num in zip(intervals, bin_counts)]

def discretize_bins(x):
    return tuple(np.digitize(x[i], bins[i]) for i in range(4))

分箱法可以更精确地控制状态空间大小,但需要预先知道各维度的合理范围。

Q-Learning算法实现

1. Q表结构设计

由于状态空间可能很大,我们使用字典而非数组存储Q值:

Q = {}  # (state, action) -> Q-value

def qvalues(state):
    return [Q.get((state, a), 0) for a in actions]

2. 核心训练流程

训练过程包含以下几个关键步骤:

  1. 初始化环境:每次训练开始重置环境
  2. 选择动作:ε-贪心策略平衡探索与利用
  3. 执行动作:获取新状态和奖励
  4. 更新Q值:使用Bellman方程
  5. 记录结果:跟踪训练进度
alpha = 0.3  # 学习率
gamma = 0.9  # 折扣因子
epsilon = 0.9  # 探索率

for epoch in range(100000):
    obs = env.reset()
    done = False
    while not done:
        s = discretize(obs)
        # ε-贪心动作选择
        if random.random() < epsilon:
            a = random.choices(actions, weights=probs(qvalues(s)))[0]
        else:
            a = random.randint(0, 1)
        
        # 执行动作
        obs, rew, done, _ = env.step(a)
        ns = discretize(obs)
        
        # Q值更新
        Q[(s,a)] = (1-alpha)*Q.get((s,a),0) + alpha*(rew + gamma*max(qvalues(ns)))

3. 训练优化技巧

  • 动态调整超参数:随着训练进行,逐渐降低学习率α和探索率ε
  • 保留最佳Q表:记录训练过程中表现最好的Q表
  • 滑动平均奖励:使用滑动窗口计算平均奖励,更准确评估性能

训练结果分析与可视化

1. 原始奖励曲线

直接绘制每个episode的奖励:

plt.plot(rewards)

这种视图噪声较大,难以识别趋势。

2. 滑动平均奖励

使用滑动窗口平均可以更清晰地看到训练进展:

def running_average(x, window):
    return np.convolve(x, np.ones(window)/window, mode='valid')

plt.plot(running_average(rewards, 100))

理想情况下,我们应该看到平均奖励逐渐上升并稳定在195以上。

模型评估与应用

1. 测试训练好的模型

使用训练好的Q表运行环境:

obs = env.reset()
done = False
while not done:
    s = discretize(obs)
    env.render()
    # 选择最佳动作
    a = np.argmax(qvalues(s))
    obs, _, done, _ = env.step(a)
env.close()

2. 性能提升技巧

  • 使用最佳Q表:训练过程中保存的最高分Q表往往表现更好
  • 确定性策略:测试时直接选择最优动作,而非按概率采样
  • 状态离散化优化:尝试不同的离散化方法,找到最佳状态表示

挑战与进阶

  1. 超参数调优:尝试不同的α、γ、ε组合,观察对训练效果的影响
  2. 高级离散化:设计更合理的状态离散化方法,减少信息损失
  3. 算法改进:尝试使用DQN等深度强化学习方法处理原始连续状态

结语

通过CartPole问题,我们学习了如何将Q-Learning应用于连续状态空间。虽然Q-Learning在简单问题上表现良好,但对于更复杂的问题,可能需要考虑深度Q网络(DQN)等更高级的方法。希望本文能帮助您建立强化学习的基础,并为后续更复杂的问题解决奠定基础。

记住,强化学习的核心在于智能体与环境的不断交互学习,正如我们人类通过试错来学习新技能一样。保持耐心,持续实验,您将能够掌握这门强大的机器学习技术!

ML-For-Beginners 微软出品的面向初学者的机器学习课程,提供了一系列实践项目和教程,旨在帮助新手逐步掌握Python、Azure ML等工具进行数据预处理、模型训练及部署。 ML-For-Beginners 项目地址: https://gitcode.com/gh_mirrors/ml/ML-For-Beginners

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

时武鹤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值