强化学习: 从头开始看 Q-Learning + FrozenLake-v1

从头开始看 Q-Learning + FrozenLake-v1

  • RL 强化学习,读书, 看视频教程,都是一知半解。
  • 所以找份代码,向 GPT 提问,尽量把每一行代码都搞懂。 不懂的地方,就是问。
  • 最后整理一下聊天记录,单独保存为一个文件,发布出去,然后最近经常看。
  • gym 有N 个环境, RL 有 M 个算法。 此文仅仅是: 1 / (M * N)
下面的问题,都是围绕的代码是:
import gymnasium as gym
import numpy as np
import matplotlib.pyplot as plt


def run(episodes, img_name):
    rng = np.random.default_rng(1)  # 随机种子?

    env = gym.make('FrozenLake-v1', map_name="4x4", is_slippery=False, render_mode=None)

    #  说白了,q-table 记录的就是: 「在第 X 个格子,往 Y 方向走,能有多大收益。」
    q = np.zeros((env.observation_space.n, env.action_space.n))
    print(q.shape) # 16, 4

    learning_rate_a = 0.9      # alpha
    discount_factor_g =  0.9   # gamma

    # epsilon, 探索率, 随机率,ε-贪婪策略参数
    # ε 越大,随机成分越多,探索越多。
    # “ε”(希腊字母 epsilon,读作「艾普西龙」)。
    # 假如 epsilon = 0.2, 那么 20% 的时间, 随机选择动作, 80% 的时间, 选择 q-table 给出的最优动作。
    epsilon = 1                  # 1 = 100% 随机选择

    # 训练多少轮?  1 /  0.0001 = 10,000
    # 其实这个参数,是控制 ε 衰减速度 的参数。
    # 因为,每一轮的结尾都需要执行:
    # epsilon = max(epsilon - epsilon_decay_rate, 0),
    # 即, 每一轮减少 0.0001
    epsilon_decay_rate = 0.0001

    # 统计一下训练的效果。
    rewards_per_episode = np.zeros(episodes)

    # 训练多少轮?比如 15000 轮。
    for i in range(episodes):
        print(f"episode {i+1}/{episodes}, epsilon={epsilon:.4f}")
        state = env.reset()[0]
        terminated = truncated =False

        # ----- start  ------------------------------------------------------------
        # 下面的过程,只是一局游戏。
        while not terminated and not truncated:

            # 这里直接比较大小???
            if rng.random() < epsilon:
                action = env.action_space.sample()
            else:
                action = np.argmax(q[state, :])  # 使用 q-table 的最大值,来选择行为, 方向。

            new_state, reward, terminated, truncated, info = env.step(action)

            # 更新 q-table, 根据获得的奖励,来更新
            q[state, action] = q[state, action] + learning_rate_a * ( reward + discount_factor_g * np.max(q[new_state, :]) - q[state, action] )
            state = new_state

        # 一轮结束,更新 epsilon 探索率, 每次减少 0.0001
        # 下面这些,依然是属于一次训练过程。
        epsilon = max(epsilon - epsilon_decay_rate, 0)

        if epsilon == 0:
            epsilon_decay_rate = 0.0001

        if reward == 1:
            rewards_per_episode[i] = 1


    env.close()

    # 画图。
    plt.figure()
    sum_rewards = np.zeros(episodes)
    for t in range(episodes):
        # 这里表示的是, 每100轮训练的奖励总共是多少
        sum_rewards[t] = np.sum(rewards_per_episode[max(0, t-100): (t+1)])
    plt.plot(sum_rewards)
    plt.savefig(f"q-table--4x4-{img_name}.png")


if __name__ == '__main__':
    run(15000, 1)

1. 如何创建 10x10 的环境。

源码中第166行提到了:

# 源码位置是: 
# G:\Dogg\venv\Lib\site-packages\gymnasium\envs\toy_text\frozen_lake.py

from gymnasium.envs.toy_text.frozen_lake import generate_random_map
gym.make('FrozenLake-v1', desc=generate_random_map(size=8))

# 那么我就可以修改为, 把 size 改为 10
env = gym.make('FrozenLake-v1', desc=generate_random_map(size=10), render_mode="human", is_slippery=False)
env.reset()

2. q-table 保存是什么东西?

q = np.zeros((env.observation_space.n, env.action_space.n))
q = np.zeros((16, 4)) # 4x4 = 16 个位置, 4个 方向

值:代表这个状态下执行这个动作,预计可以得到的“总回报”(长期奖励)。
说白了,q-table 记录的就是: 「在第 X 个格子,往 Y 方向走,能有多大收益。」

3. 通俗理解 Q-learning 是什么?

Q-learning 核心思想一句话总结:

“用表格(q-table)记住在每个状态下做每个动作的价值,
然后根据这个表格不断优化,找到最好的行为方式。”

4. epsilon 到底是什么?

  • epsilon, 探索率, 随机率,ε-贪婪策略参数
  • ε(希腊字母 epsilon,读作「艾普西龙」)。
  • ε 越大,随机成分越多,探索越多。
  • 假如 epsilon = 0.2, 20% 随机探索, 80% 按照当前 q-table 最佳方向走。

epsilon ,这个概念很关键。 ChatGPT 下面几句话写的很好:

  • 刚开始啥都不会,epsilon=1,完全乱走,多看看世界。
  • 慢慢学聪明了,epsilon 一点点减小,开始用经验行动。
  • 最后熟能生巧,epsilon=0,每次都选最好走的路。

5. 几个参数

  • learning_rate_a = 0.9 # alpha,α, 学习率,表示“这次新学到的经验,占多少比重”。
  • discount_factor_g = 0.9 # gamma, γ, 折扣因子,它控制“未来奖励”的重要程度
  • epsilon_decay_rate = 0.0001, 表示 探索率 ε(epsilon),每次减少 0.0001
参数 读音 作用 推荐范围
ε(epsilon) 艾普西龙 随机探索概率 0 ~ 1
α(alpha) 阿尔法 学习率,经验更新强度 0 ~ 1
γ(gamma) 伽马 折扣因子,未来奖励重要性 0 ~ 1

6. 公式

Q ( s , a ) = Q ( s , a ) + α ∗ ( r + γ ∗ m a x ( Q ( s ′ , : ) ) − Q ( s , a ) ) Q(s, a) = Q(s, a) + α * (r + γ * max(Q(s', :)) - Q(s, a)) Q(s,a)=Q(s,a)+α(r+γmax(Q(s,:))Q(s,a))

自己写的时候,我发现,其实可以简写为: Q = Q + new_stuff
也可以理解为:新 Q 值 = 老 Q 值的 (1 - α) + 新经验的 α

7. epsilon, 实际上,到底是怎么用的?

其实, 就是用 numpy 生成一个随机数, 来跟 epsilon 进行比较。
理解: 一个随机数,被 epsilon 分割为左右2个区域, 分别对应不同的选择。

 if rng.random() < epsilon:
    action = env.action_space.sample()
else:
    action = np.argmax(q[state, :]) # 使用 q-table 来选择行为, 方向。

这种写法简单又高效,几乎所有强化学习代码都会用这种判断。 ???!!!

相关链接:
  1. chatGPT 聊天记录, https://chatgpt.com/c/67c61c51-2dc0-8002-bafb-fc8c7e6606dd
  2. 视频教程, https://github.com/johnnycode8/gym_solutions
  3. 参考代码,https://www.youtube.com/watch?v=ZhoIgo3qqLU&list=LL&ab_channel=JohnnyCode

你可能感兴趣的:(强化学习,python,深度学习,人工智能,python)