大家好,我是微学AI,今天给大家介绍一下人工智能基础部分23-利用Q学习解决“悬崖行走”与迷宫问题的案例。Q-Learning是一种无模型的强化学习算法,它通过Q表来评估在给定状态下采取某一动作的期望回报。Q表是一个表格,其行代表状态,列代表动作,每个单元格的值代表在某一状态下采取某一动作的Q值。
Q学习(Q-Learning)是一种值迭代算法,用于求解马尔可夫决策过程(MDP)中的最优策略。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′)=a′max?Q(s′,a′)
在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+γa′max?Q(s′,a′)?Q(s,a))
其中,$ \alpha $是学习率,用于控制更新的幅度。
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+γa′max?Q(s′,a′)]
这个递归关系可以用来证明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表的形状是(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学习算法来解决一个迷宫问题:
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表。