人工智能基础部分23-利用Q-Learning解决“悬崖行走”与迷宫问题的案例

发布时间:2024年01月18日

大家好,我是微学AI,今天给大家介绍一下人工智能基础部分23-利用Q学习解决“悬崖行走”与迷宫问题的案例。Q-Learning是一种无模型的强化学习算法,它通过Q表来评估在给定状态下采取某一动作的期望回报。Q表是一个表格,其行代表状态,列代表动作,每个单元格的值代表在某一状态下采取某一动作的Q值。

一、Q学习的介绍

Q学习(Q-Learning)是一种值迭代算法,用于求解马尔可夫决策过程(MDP)中的最优策略。Q学习的目标是学习一个动作值函数,即Q函数,它表示在给定状态下采取某一动作的期望回报。

Q函数和Q表

Q函数,记为$ Q(s, a) ,表示在状态 ,表示在状态 ,表示在状态 s 下采取动作 下采取动作 下采取动作 a $的期望回报,即:
Q ( s , a ) = E [ r + γ V ( s ′ ) ] Q(s, a) = \mathbb{E}[r + \gamma V(s')] Q(s,a)=E[r+γV(s)]
其中, r r r是立即回报, γ \gamma γ 是折现因子, V ( s ′ ) V(s') V(s)是下一状态 s ′ s' s的值函数,即:
V ( s ′ ) = max ? a ′ Q ( s ′ , a ′ ) V(s') = \max_{a'} Q(s', a') V(s)=amax?Q(s,a)
在Q学习中,我们通常使用一个表格来存储Q值,这个表格称为Q表。Q表的行表示状态,列表示动作,每个单元格存储了对应的Q值。

Q学习算法

Q学习算法通过迭代地更新Q值来逼近最优策略。更新规则如下:
Q ( s , a ) ← Q ( s , a ) + α ( r + γ max ? a ′ Q ( s ′ , a ′ ) ? Q ( s , a ) ) Q(s, a) \leftarrow Q(s, a) + \alpha (r + \gamma \max_{a'} Q(s', a') - Q(s, a)) Q(s,a)Q(s,a)+α(r+γamax?Q(s,a)?Q(s,a))
其中,$ \alpha $是学习率,用于控制更新的幅度。

算法步骤

  1. 初始化Q表,所有值设为0。
  2. 对于每个episode:
    1. 初始化状态 s s s
    2. 对于每一步:
      1. 以某种策略(如epsilon-greedy策略)选择动作 a a a
      2. 执行动作 a a a,观察奖励 r r r和新状态 s ′ s' s
      3. 更新Q表: Q ( s , a ) ← Q ( s , a ) + α ( r + γ max ? a ′ Q ( s ′ , a ′ ) ? Q ( s , a ) ) Q(s, a) \leftarrow Q(s, a) + \alpha (r + \gamma \max_{a'} Q(s', a') - Q(s, a)) Q(s,a)Q(s,a)+α(r+γmaxa?Q(s,a)?Q(s,a))
      4. s ← s ′ s \leftarrow s' ss
    3. 直到到达终止状态。
      在这里插入图片描述

数学原理

Q学习的数学原理基于贝尔曼最优性原理,即一个策略是最优的,当且仅当对于所有状态 s s s和所有动作 a a a,该策略的Q值都达到了最大值。Q学习的目标是找到这样一个策略,使得Q表中的每个Q值都尽可能地接近最优值。
Q学习的更新规则可以写成递归形式:
Q ( s , a ) = E [ r + γ max ? a ′ Q ( s ′ , a ′ ) ] Q(s, a) = \mathbb{E}[r + \gamma \max_{a'} Q(s', a')] Q(s,a)=E[r+γamax?Q(s,a)]
这个递归关系可以用来证明Q学习的收敛性。在适当的条件下,随着迭代次数的增加,Q学习算法可以收敛到最优策略。

二、Q学习的应用一:“悬崖行走”

现在我将介绍“悬崖行走”(Cliff Walking)问题,在这个问题中,Agent需要在4x12的网格世界中从左下角走到右上角,同时避免走到悬崖区域。

import numpy as np
import random
# 定义悬崖行走的网格世界
world_height = 4
world_width = 12
start_state = [3, 0]
end_state = [3, 11]
cliff = [[3, i] for i in range(1, 11)]
# 定义动作空间
actions = ['up', 'down', 'left', 'right']
# 初始化Q表
Q = np.zeros((world_height, world_width, len(actions)))
# 定义学习参数
gamma = 0.9  # 折扣因子
alpha = 0.1  # 学习率
epsilon = 0.1  # 探索率
# 定义状态转移函数
def move(state, action):
    if action == 'up':
        return [max(state[0] - 1, 0), state[1]]
    elif action == 'down':
        return [min(state[0] + 1, world_height - 1), state[1]]
    elif action == 'left':
        return [state[0], max(state[1] - 1, 0)]
    elif action == 'right':
        return [state[0], min(state[1] + 1, world_width - 1)]
# 定义奖励函数
def reward(state):
    if state in cliff:
        return -100
    elif state == end_state:
        return 0
    else:
        return -1
# Q学习算法
def q_learning():
    state = start_state
    while True:
        if random.uniform(0, 1) < epsilon:
            action = random.choice(actions)
        else:
            action = actions[np.argmax(Q[state[0], state[1], :])]
        next_state = move(state, action)
        q_predict = Q[state[0], state[1], actions.index(action)]
        if next_state == end_state:
            q_target = reward(next_state)
        else:
            q_target = reward(next_state) + gamma * np.max(Q[next_state[0], next_state[1], :])
        Q[state[0], state[1], actions.index(action)] += alpha * (q_target - q_predict)
        state = next_state
        if state == end_state:
            break
# 训练Q学习算法
for episode in range(500):
    q_learning()
# 输出最终的Q表
print("Final Q-Table:")
print(Q)

这个代码样例中,我们定义了一个4x12的网格世界,其中包含一个悬崖区域。我们使用Q表来存储每个状态-动作对的Q值。在每次迭代中,我们根据Q学习算法更新Q表。最后,我们输出最终的Q表。

Q表的介绍:

上面代码生成的Q表是一个三维数组,其中两个维度表示状态(行和列),第三个维度表示在该状态下可以采取的动作。Q表的每个单元格存储了一个Q值,这个Q值表示在给定的状态下采取对应的动作,预期能获得的回报加上后续状态的最大预期回报的折现总和。
在上述的悬崖行走问题中,Q表的形状是(4, 12, 4),因为有4行、12列,每个单元格有4个可能的动作(上、下、左、右)。Q表的每个单元格存储了一个浮点数,表示在该状态下采取对应动作的Q值。
Q表的原理基于贝尔曼最优性原理,即一个策略是最优的,当且仅当对于所有状态s和所有动作a,该策略的Q值都达到了最大值。Q学习的目标是找到这样一个策略,使得Q表中的每个Q值都尽可能地接近最优值。

在Q学习中,我们通过迭代地更新Q表来逼近最优策略。每次迭代包括以下几个步骤:
1.选择一个状态s。
2. 根据当前策略(通常是epsilon-greedy策略,即以概率epsilon随机选择一个动作,以概率1-epsilon选择当前Q值最高的动作)在状态s下选择一个动作a。
3. 执行动作a,观察奖励r和新状态s’。
4. 更新Q表中的Q值: Q ( s , a ) = Q ( s , a ) + α ? ( r + γ ? m a x a ′ Q ( s ′ , a ′ ) ? Q ( s , a ) ) Q(s, a) = Q(s, a) + \alpha * (r + \gamma * max_a' Q(s', a') - Q(s, a)) Q(s,a)=Q(s,a)+α?(r+γ?maxa?Q(s,a)?Q(s,a)),其中 α \alpha α是学习率, γ \gamma γ是折现因子。
重复这个过程足够多次,Q表就会收敛到最优策略的Q值。最终,我们可以通过观察Q表来找出最优策略:对于每个状态s,选择具有最高Q值的动作a,这样就可以得到一个最优策略。
在实际应用中,Q表可能会非常大,以至于无法存储在内存中。因此,人们通常使用函数近似方法(如深度学习)来估计Q值,而不是使用一个显式的Q表。这种方法被称为深度Q网络(DQN),它使用神经网络来近似Q函数,从而可以处理更复杂的问题。

三、Q学习的应用二:迷宫问题

下面我将利用Q学习算法来解决一个迷宫问题:

import numpy as np

# 定义迷宫环境
env = np.array([[-1, -1, -1, -1, 0, -1],
                [-1, -1, -1, 0, -1, 100],
                [-1, -1, -1, 0, -1, -1],
                [-1, 0, 0, -1, 0, -1],
                [0, -1, -1, 0, -1, 100],
                [-1, 0, -1, -1, 0, 100]])

# 初始化Q表
q_table = np.zeros((6, 6))

# 定义超参数
learning_rate = 0.8
discount_factor = 0.95
num_episodes = 1000

# Q学习算法
for episode in range(num_episodes):
    state = np.random.randint(0, 6)  # 随机选择起始状态

    while state != 5:  # 终止状态为5
        # 选择动作:使用ε-greedy策略
        if np.random.uniform() < 0.2:
            action = np.random.randint(0, 6)  # 探索
        else:
            action = np.argmax(q_table[state])  # 开发

        # 执行动作并观察新状态和奖励
        next_state = action
        reward = env[state, action]

        # 更新Q值
        q_table[state, action] += learning_rate * (reward + discount_factor * np.max(q_table[next_state]) - q_table[state, action])

        state = next_state

# 打印训练后的Q表
print("训练后的Q表:")
print(q_table)

以上代码中迷宫环境是一个6x6的矩阵,-1表示不可通行的位置,0表示可通行的位置,100表示目标位置。算法通过与环境交互并更新Q表来学习最佳行动策略。在每个episode中,代理根据当前状态选择一个动作,执行该动作并观察新状态和奖励,然后使用Q学习更新Q表。最终,训练完成后打印出训练后的Q表。

文章来源:https://blog.csdn.net/weixin_42878111/article/details/135677509
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。