图解强化学习 |Q-learning

张开发
2026/4/4 3:21:01 15 分钟阅读
图解强化学习 |Q-learning
欢迎来到图解强化学习的世界博客主页卿云阁欢迎关注点赞收藏⭐️留言首发时间2026年4月3日✉️希望可以和大家一起完成进阶之路作者水平很有限如果发现错误请留言轰炸哦万分感谢目录Q-Learning决策QLearning 更新小例子预设值Q 表定义动作环境反馈 S_, R环境更新强化学习主循环冰壶游戏Q-Learning决策直接是根据动作价值函数的大小来选动作的假设我们有一个表格里面放着每一个状态选择每个动作的价值。现在我们处于状态s1,我在写作业, 我有两个行为 a1, a2,在我的记忆Q表格中,Q(s1, a1)-2要小于Q(s1, a2)1,也就是说选择a2这个动作的潜在奖励会更大一些。所以我们判断要选择 a2 作为下一个行为. 现在我们的状态更新成 s2 , 我们还是有两个同样的选择, 重复上面的过程, 在行为准则Q 表中寻找 Q(s2, a1) Q(s2, a2) 的值, 并比较他们的大小, 选取较大的一个. 接着根据 a2 我们到达 s3 并在此重复上面的决策过程. Q learning 的方法也就是这样决策的。QLearning 更新做一个动作的总价值不仅要看当下的即时收益还要看这个动作能带你到新状态后未来能拿到的最大收益估计值就是我们之前对「s1 下做 a2」的预估价值也就是初始Q 表中的Q(s1, a2)。Q(s1, a2)是在s1状态下选择 a2动作的潜在奖励。真实值当下动作的即时奖励Q(s1, a2)和未来新状态的最大潜在价值的总和maxQ(s2) 未来价值打折扣alpha 是因为 “未来的收益不如当下确定”。Epsilon greedy是用在决策上的一种策略, 比如 epsilon 0.9 时, 就说明有90% 的情况我会按照Q 表的最优值选择行为, 10% 的时间使用随机选行为.alpha是学习率, 来决定这次的误差有多少是要被学习的, alpha是一个小于1 的数. gamma 是对未来 reward 的衰减值. 我们可以这样想象.小例子例子的环境是一个一维世界, 在世界的右边有宝藏, 探索者只要得到宝藏尝到了甜头, 然后以后就记住了得到宝藏的方法, 这就是他用强化学习所学习到的行为。-o---T # T 就是宝藏的位置, o 是探索者的位置预设值import numpy as np import pandas as pd import time N_STATES 6 # 1维世界的宽度 ACTIONS [left, right] # 探索者的可用动作 EPSILON 0.9 # 贪婪度 greedy ALPHA 0.1 # 学习率 GAMMA 0.9 # 奖励递减值 MAX_EPISODES 13 # 最大回合数 FRESH_TIME 0.3 # 移动间隔时间Q 表对于 tabular Q learning, 我们必须将所有的 Q values (行为值) 放在 q_table 中, 更新 q_table 也是在更新他的行为准则.q_table 的 index 是所有对应的 state (探索者位置), columns 是对应的 action (探索者行为).def build_q_table(n_states, actions): table pd.DataFrame( np.zeros((n_states, len(actions))), # q_table 全 0 初始 columnsactions, # columns 对应的是行为名称 ) return table print(build_q_table(N_STATES, ACTIONS)) # q_table: left right 0 0.0 0.0 1 0.0 0.0 2 0.0 0.0 3 0.0 0.0 4 0.0 0.0 5 0.0 0.0 定义动作根据状态和动作奖励函数选择唯一的动作接着定义探索者是如何挑选行为的. 这是我们引入 epsilon greedy 的概念. 因为在初始阶段, 随机的探索环境, 往往比固定的行为模式要好, 所以这也是累积经验的阶段, 我们希望探索者不会那么贪婪(greedy). 所以 EPSILON 就是用来控制贪婪程度的值. EPSILON 可以随着探索时间不断提升(越来越贪婪),不过在这个例子中, 我们就固定成 EPSILON 0.9, 90% 的时间是选择最优策略, 10% 的时间来探索. 最后返回left或者是rightdef choose_action(state, q_table): state_actions q_table.iloc[state, :] # 选出这个 state 的所有 action 值 if (np.random.uniform() EPSILON) or (state_actions.all() 0): # 非贪婪 or 或者这个 state 还没有探索过 action_name np.random.choice(ACTIONS) else: action_name state_actions.argmax() # 贪婪模式 return action_name print(choose_action(1, q_table))环境反馈 S_, R根据状态和动作进入下一个状态和给出动作奖励做出行为后, 环境也要给我们的行为一个反馈,反馈出下个 state (S_) 和 在上个 state (S) 做出action (A) 所得到的 reward (R).这里定义的规则就是, 只有当 o 移动到了 T, 探索者才会得到唯一的一个奖励, 奖励值 R1, 其他情况都没有奖励.[起点] --- [1] --- [2] --- [3] --- [4] --- [宝藏 (Terminal)] S0 S1 S2 S3 S4 S5def get_env_feedback(S, A): # This is how agent will interact with the environment if A right: # move right if S N_STATES - 2: # terminate S_ terminal R 1 else: S_ S 1 R 0 else: # move left R 0 if S 0: S_ S # reach the wall else: S_ S - 1 return S_, R环境更新def update_env(S, episode, step_counter): # This is how environment be updated env_list [-]*(N_STATES-1) [T] # ---------T our environment if S terminal: interaction Episode %s: total_steps %s % (episode1, step_counter) print(\r{}.format(interaction), end) time.sleep(2) print(\r , end) else: env_list[S] o interaction .join(env_list) print(\r{}.format(interaction), end) time.sleep(FRESH_TIME)强化学习主循环最重要的地方就在这里. 你定义的 RL 方法都在这里体现.def rl(): q_table build_q_table(N_STATES, ACTIONS) # 初始 q table for episode in range(MAX_EPISODES): # 回合 step_counter 0 S 0 # 回合初始位置 is_terminated False # 是否回合结束 update_env(S, episode, step_counter) # 环境更新 while not is_terminated: A choose_action(S, q_table) # 选行为 S_, R get_env_feedback(S, A) # 实施行为并得到环境的反馈 q_predict q_table.loc[S, A] # 估算的(状态-行为)值 if S_ ! terminal: q_target R GAMMA * q_table.iloc[S_, :].max() # 实际的(状态-行为)值 (回合没结束) else: q_target R # 实际的(状态-行为)值 (回合结束) is_terminated True # terminate this episode q_table.loc[S, A] ALPHA * (q_target - q_predict) # q_table 更新 S S_ # 探索者移动到下一个 state update_env(S, episode, step_counter1) # 环境更新 step_counter 1 return q_tableif __name__ __main__: q_table rl() print(\r\nQ-table:\n) print(q_table)手动计算过程选动作根据当前的状态和Q表格选动作执行动作根据当前的状态和动作得到奖励和下个状态估算的(状态-行为)值计算当前行为的动作价值的估计值计算真实值计算当前行为的动作价值的真实值根据下一个动态的最大动作奖励函数更新Q表更新当前状态选择当前动作的动作价值函数冰壶游戏根据epsilon-greedy策略选择动作choose_action(state, Q, epsilon 0.1)函数的输入 (Inputs) 解析state当前状态state 0起点Q经验大表它是一个二维数组矩阵大小是16*4的你需要从中提取当前状态的那一行比如Q[state]。函数的输出 (Output) 解析返回值一个整数在冰湖环境中是 0, 1, 2, 3 之一代表 AI 最终决定在这一步执行的具体动作。# 根据epsilon-greedy策略选择动作 def choose_action(state, Q, epsilon 0.1): if np.random.rand() epsilon: # 以epsilon的概率随机选择一个动作 return np.random.randint(env.action_space.n) else: # 否则选择具有最高Q值的动作 return np.argmax(Q[state])更新Q值表中的值(q_update_value)输入state, action, reward, next_state, done, Q更新当前状态选择当前动作的动作价值# 更新Q值表中的值 def q_update_value(state, action, reward, next_state, done, Q): if done: # 如果达到终止状态根据奖励更新Q值 Q[state][action] alpha * (reward - Q[state][action]) else: # 如果未达到终止状态根据Q-learning公式更新Q值 Q[state][action] alpha * (reward gamma * np.max(Q[next_state]) - Q[state][action])主要的流程【1】根据当前的状态state和Q【state]选择一个动作action)【2】根据当前的状态state和选择一个动作action)得到奖励和下一个状态【3】更新当前状态选择当前动作的动作价值# 初始化Q值表形状为环境中状态数量和动作数量 Q np.zeros((env.observation_space.n, env.action_space.n)) # 记录每个回合的总奖励 total_reward [] # 开始循环 for i in range(num_episodes): # 当前回合的总奖励 sum_reward 0 # 初始化环境并获取初始状态 state, _ env.reset() while True: # 根据当前状态选择动作 action choose_action(state, Q) # 执行动作获取新的信息 next_state, reward, terminated, truncated, info env.step(action) # 判断是否达到终止状态 done terminated or truncated # 对于FrozenLake的佛系默认环境适当调整奖励 if FrozenLake in env.spec.id: if terminated and reward 1: # 游戏终止且reward为1表示到达终点给予高额奖励 reward 20 elif terminated and reward 0: # 游戏终止且reward为0表示掉进冰洞给予反向奖励 reward -20 else: # 每走一步奖励为-1其实是鼓励agent尽快完成任务 reward -1 # 更新Q值表 q_update_value(state, action, reward, next_state, done, Q) # 累加奖励 sum_reward reward # 更新当前状态 state next_state if done: break # 记录当前回合的总奖励 total_reward.append(sum_reward) # 打印回合数和最大总奖励 print(Episodes: {0}\nMax Reward: {1}.format(num_episodes, max(total_reward)))【1】小例子 | 莫烦Python

更多文章