Q-learning原理:
1.Q-learning是一种基于值的强化学习方法。它旨在找到一个策略,该策略可以最大化智能体在长期内从环境中获得的奖励。
2.在Q-learning中,智能体维护一个Q表,该表对每个状态-行动对(s, a)分配一个值Q(s, a),表示智能体在状态s采取行动a时预期的未来奖励。
3.智能体在每个时间步会选择一个行动,观察环境的响应(新的状态和奖励),然后用这些信息来更新Q表。
公式解释:
Q值的更新是通过以下公式完成的:
Q(s,a)=(1−α)⋅Q(s,a)+α⋅(r+γ ⋅ a · maxQ(s′,a′))
- s 是当前状态。
- a 是采取的行动。
- r 是收到的奖励。
- s ′是新的状态。
- α 是学习率,一个介于0和1之间的数,决定了新信息对Q值的影响程度。
- γ 是折扣因子,一个介于0和1之间的数,用于减少未来奖励的权重。
- max a Q(s ′,a ′) 是新状态′s ′下所有可能行动′a ′的最大Q值。
公式案例:
假设我们有以下情况:
- 当前状态 s=1
- 采取的行动 a=“向右移动”
- 收到的奖励 r=−1
- 新的状态 s ′=2
- 在新状态s ′=2中,所有可能行动的Q值分别是:
Q(2,“向上移动”)=0, Q(2,“向下移动”)=−1, Q(2,“向左移动”)=−2, Q(2,“向右移动”)=1。因此,max a Q(s ′,a ′)=1 - 设定的学习率 α=0.5
- 设定的折扣因子 γ=0.9
- 假设初始时,Q(1,“向右移动”)=0。根据更新公式,新的
Q(1,“向右移动”)值将会是:Q(1,“向右移动”)=(1−0.5)⋅0+0.5⋅(−1+0.9⋅1)=−0.05
因此,更新后的Q值为-0.05。
Q-learing 应用案例-走迷宫
在一个迷宫问题中,智能体的目标是找到从起点到终点的最短路径。我们可以通过Q-learning来训练智能体,具体步骤和概念定义如下:
- 环境(Environment): 这是智能体所处的空间。在迷宫的例子中,环境就是迷宫本身,包括起点、终点、通路和墙。
- 智能体(Agent): 这是在环境中采取行动的实体。在这个例子中,智能体是需要找到出口的实体。
- 状态(State): 这是环境的当前情况。对于迷宫问题,状态可以是智能体当前的位置。
- 行动(Action): 这是智能体可以在当前状态下采取的行动。对于迷宫问题,可能的行动是上、下、左、右。
- 奖励(Reward): 这是智能体采取行动后从环境中得到的反馈。对于迷宫问题,奖励可以是-1的惩罚(表示每走一步的代价)、+50的奖励(表示到达目标的奖励)、-100的惩罚(表示撞墙的惩罚)。
- Q表(Q-table): 这是一个表格,用于存储每个状态-行动对的Q值。Q值表示在给定状态下采取特定行动的预期奖励。
- 学习率(Learning Rate, α): 这是一个参数,用于控制Q值的更新速度。
- 折扣因子(Discount Factor, γ): 这是一个参数,用于减少未来奖励的重要性。
import numpy as np
import random
# 迷宫参数
maze = [
[0, 1, 0, 0, 0],
[0, 1, 0, 1, 0],
[0, 0, 0, 1, 0],
[0, 1, 0, 0, 0],
[0, 0, 0, 1, 2]
]
start = (0, 0)
goal = (4, 4)
# Q-learning参数
alpha = 0.1
gamma = 0.9
epsilon = 0.1
actions = [(0, 1), (1, 0), (0, -1), (-1, 0)] # 右、下、左、上
# 初始化Q表
states = [(i, j) for i in range(5) for j in range(5)]
q_table = {(state, action): 0 for state in states for action in actions}
# 训练智能体
num_episodes = 1000
for episode in range(num_episodes):
state = start
done = False
while not done:
# 选择一个行动
if random.uniform(0, 1) < epsilon:
action = random.choice(actions)
else:
action_values = [q_table[(state, a)] for a in actions]
action = actions[np.argmax(action_values)]
# 采取行动并观察下一个状态和奖励
next_state = (state[0] + action[0], state[1] + action[1])
if next_state[0] < 0 or next_state[0] >= 5 or next_state[1] < 0 or next_state[1] >= 5:
next_state = state
reward = -100
else:
cell_value = maze[next_state[0]][next_state[1]]
if cell_value == 1:
reward = -100
next_state = state
elif cell_value == 2:
reward = 50
done = True
else:
reward = -1
# 更新Q表
predict = q_table[(state, action)]
target = reward + gamma * max(q_table[(next_state, a)] for a in actions)
q_table[(state, action)] = predict + alpha * (target - predict)
state = next_state
# 打印Q表
for state in states:
for action in actions:
print(f"Q({state}, {action}) = {q_table[(state, action)]:.2f}")
这个代码中:
- maze 是迷宫的布局,其中 0 表示通道,1 表示墙,2 表示目标。
- start 和 goal 分别是起点和终点的坐标。
- alpha, gamma, 和 epsilon 分别是学习率、折扣因子和探索率。
- actions 是可能的行动列表。
- q_table 是Q表。num_episodes 是训练的总轮数。
1.在每一轮中,智能体从起点开始,然后在每个状态选择一个行动,观察下一个状态和奖励,并更新Q表,直到到达目标。在选择行动时,有epsilon的概率选择一个随机行动,否则选择当前状态下的最优行动(即Q值最大的行动)。这是一种“epsilon-greedy”策略,可以确保智能体在探索和利用之间取得平衡。
2.在更新Q表时,我们用到了之前提到的Q值更新公式。
3.完成训练后,Q表中的值会逐渐收敛,智能体就能够根据Q表选择最优的行动。
优化版(改建psilon和reward检测,评估模型收敛)
import numpy as np
import random
import math
import matplotlib.pyplot as plt
# 迷宫参数
maze = [
[0, 1, 0, 0, 0],
[0, 1, 0, 1, 0],
[0, 0, 0, 1, 0],
[0, 1, 0, 0, 0],
[0, 0, 0, 1, 2]
]
start = (0, 0)
goal = (4, 4)
# Q-learning参数
alpha = 0.1
gamma = 0.9
initial_epsilon = 1.0
min_epsilon = 0.1
decay_rate = 0.01
actions = [(0, 1), (1, 0), (0, -1), (-1, 0)] # 右、下、左、上
# 初始化Q表
states = [(i, j) for i in range(5) for j in range(5)]
q_table = {(state, action): 0 for state in states for action in actions}
# 计算奖励
def compute_reward(state):
if state == goal:
return 50
elif maze[state[0]][state[1]] == 1:
return -100
else:
return -1
# 获取epsilon
def get_epsilon(episode):
return min_epsilon + (initial_epsilon - min_epsilon) * math.exp(-decay_rate * episode)
# 存储每个episode的奖励和epsilon
rewards = []
epsilons = []
# 训练智能体
num_episodes = 1000
for episode in range(num_episodes):
state = start
done = False
epsilon = get_epsilon(episode)
total_reward = 0
while not done:
# 选择一个行动
if random.uniform(0, 1) < epsilon:
action = random.choice(actions)
else:
action_values = [q_table[(state, a)] for a in actions]
action = actions[np.argmax(action_values)]
# 采取行动并观察下一个状态和奖励
next_state = (state[0] + action[0], state[1] + action[1])
if next_state[0] < 0 or next_state[0] >= 5 or next_state[1] < 0 or next_state[1] >= 5:
next_state = state
reward = compute_reward(next_state)
total_reward += reward
# 更新Q表
predict = q_table[(state, action)]
target = reward + gamma * max(q_table[(next_state, a)] for a in actions)
q_table[(state, action)] = predict + alpha * (target - predict)
state = next_state
done = state == goal
rewards.append(total_reward)
epsilons.append(epsilon)
# 打印Q表
for state in states:
for action in actions:
print(f"Q({state}, {action}) = {q_table[(state, action)]:.2f}")
# 画图
plt.figure(figsize=(12, 5))
plt.subplot(1, 2, 1)
plt.plot(rewards)
plt.xlabel('Episode')
plt.ylabel('Total Reward')
plt.subplot(1, 2, 2)
plt.plot(epsilons)
plt.xlabel('Episode')
plt.ylabel('Epsilon')
plt.tight_layout()
plt.show()