目录

1、什么是马尔可夫奖励过程(MRP)

2、什么是回报?

3、什么是价值函数?

3.1、 状态价值函数(V (s)):“现在复习到这个程度,最后能考多少分?”

3.2、 动作价值函数(Q (s,a)):“现在选这个复习方式,最后能多拿多少分?”

3.3、为什么需要价值函数

3.4、价值函数代码

4、价值函数怎么计算?

4.1、计算方法:以马尔可夫奖励过程(MRP)为例

方法 1:直接求解(适用于状态少的情况)

方法 2:迭代法(适用于状态多的情况)

4.2、直观理解:为什么这样算?

4.3、完整代码

4.3.1、迭代法计算马尔可夫奖励过程的价值函数

4.3.2、直接矩阵求逆法计算价值函数

4.3.3、状态价值函数V(s)计算

4.3.4、动作价值函数 Q(s,a)计算

5、R(s,a)和 R(s) 的不同之处?

5.1、 定义与适用场景

5.2、直观理解


1、什么是马尔可夫奖励过程(MRP)

就是 “逛超市时,你现在在哪,决定了你下一步可能去哪,并且每到一个地方能攒多少积分,最后算清楚每个地方到底值多少分”。

拆成 4 个你能摸到的东西:

  1. 状态:超市里的位置,比如 “入口、零食区、生鲜区、收银台(结账走人)”。
  2. 转移:从当前位置能走到哪。比如 “在零食区,60% 概率去生鲜区,40% 概率回入口”(只和现在在哪有关,和你之前去过玩具区没关系 —— 这就是 “马尔可夫性”)。
  3. 奖励:到每个位置给的积分。比如 “零食区给 1 分,生鲜区给 3 分,回入口扣 1 分(绕路了),收银台给 10 分(结账奖励)”。
  4. 目标:算明白 “站在入口 / 零食区 / 生鲜区,最后总共能攒多少分(包括以后能拿到的)”。

举个具体场景:

你从入口进超市,可能的路线:

  • 顺利路线:入口→零食区→生鲜区→收银台
    积分:入口(0)→零食区(+1)→生鲜区(+3)→收银台(+10)
  • 绕路路线:入口→零食区→入口→零食区→生鲜区→收银台
    积分:0→1→-1(回入口)→1→3→10

MRP 不管你走哪条路,它会算:

  • “站在零食区,平均下来能攒多少分?”(比如算出来是 8 分)
  • “站在入口,平均下来能攒多少分?”(比如算出来是 5 分)

这样你就知道:哪怕可能绕路,零食区也比入口 “值钱”,所以来了就别回头,赶紧往生鲜区走 —— 这就是 MRP 的用处:帮你判断 “现在的位置到底值不值留”

 

总结:MRP 就是给 “会随机乱逛的场景” 算 “每个地方的真实价值”,让你知道下一步该往哪走更划算。

2、什么是回报?

回报(Return)就是:你玩这一轮抓娃娃,从头到尾总共得到的 “好处”。

具体场景:

假设抓娃娃机有 3 个状态:

  • 投币处(刚投币)、操作区(正在抓)、出口(抓到娃娃 / 没抓到,游戏结束)。

规则:

  • 投币后(到投币处),必然去操作区(100% 概率),奖励 0(刚投币,还没好处)。
  • 在操作区,50% 概率抓到娃娃(去出口,奖励 + 100 分),50% 概率没抓到(去出口,奖励 0 分)。

两种情况的 “回报”:

  1. 抓到娃娃的路径:投币处 → 操作区 → 出口(抓到)
    总好处:0(投币处) + 0(操作区) + 100(出口) = 100 分(这就是这条路径的回报)。

  2. 没抓到的路径:投币处 → 操作区 → 出口(没抓到)
    总好处:0 + 0 + 0 = 0 分(这是另一条路径的回报)。

核心点:

  • 回报只看 “这一轮从开始到结束,所有好处加起来是多少”,走的路不同,回报可能不一样。
  • 哪怕过程中没即时好处(比如操作区没奖励),也算在里面(加 0 而已)。
 

一句话:回报就是 “一次完整流程的总收益”,就像你玩一局游戏,从开玩到结束,总共得了多少分、赢了多少钱,这就是回报

3、什么是价值函数?

场景:期末复习(目标是考高分)

假设你有 3 门课要复习:数学、英语、思政。每门课的复习难度(当下的 “痛苦”)和考试分值(未来的 “收益”)不同,而且你每天只能选一门课复习(动作),最终目标是总分最高。

3.1、 状态价值函数(V (s)):“现在复习到这个程度,最后能考多少分?”

  • 状态 s:比如 “数学复习了 30%”“英语完全没看”“距离考试还有 2 天”。
  • V(s) 就像你心里估算的 “保底总分”:
    • 比如 “数学复习 30% + 英语没看 + 剩 2 天” 这个状态,你估算最后能考 50 分(因为数学能拿基础分,英语蒙选择题,时间够补一点)。
    • 另一个状态 “数学复习 80% + 英语复习 50% + 剩 1 天”,你估算能考 80 分,显然这个状态的 “价值” 更高。

作用:帮你判断 “现在的处境好不好”。如果现在的状态价值低,你就知道必须调整复习计划了。

3.2、 动作价值函数(Q (s,a)):“现在选这个复习方式,最后能多拿多少分?”

  • 比如你现在处于 “数学复习 30% + 剩 2 天” 的状态(s),有两个选择(动作 a):
    • 动作 A:今天专攻数学(能多复习 20%,但英语彻底放弃)。
    • 动作 B:今天花 1 小时看英语(英语能多拿 10 分,数学进度不变)。
  • Q(s,A) 就是 “选 A 的最终总分”:比如数学能提到 50%(多 20 分),英语 0 分,最后估算 60 分。
  • Q(s,B) 就是 “选 B 的最终总分”:数学 30%(20 分),英语 10 分,最后估算 30 分。

作用:帮你在选项中挑最优。显然你会选 A,因为它的 “动作价值” 更高。

3.3、为什么需要价值函数?

想象一下,如果没有这个 “计算器”:

  • 你可能会凭感觉选动作(比如觉得英语简单就先看英语),但最后发现数学丢分更多,总分更低。
  • 有了价值函数,你能算清 “现在的选择对未来的影响”,哪怕当下辛苦(比如啃数学),但长远来看更划算。

价值函数就像你做决策时心里的 “小算盘”:

  • 算 “现在的处境值多少”(状态价值),
  • 算 “选这个做法能赚多少”(动作价值),
  • 帮你不被眼前的好坏迷惑,盯着最终目标做对选择。

3.4、价值函数代码

"""
文件名: 3.3 回报
作者: 墨尘
日期: 2025/7/21
项目名: d2l_learning
备注: 
"""
import  numpy as np


def compute_returns(start_index, chain, gamma):
    G = 0
    for i in reversed(range(start_index, len(chain))):
        G = gamma * G + rewards[chain[i] - 1]
    return G
if __name__ == '__main__':

    np.random.seed(0)#设置相同的seed值可以确保每次运行程序时生成的随机数相同,从而实现随机数据的可预测性

    # 定义状态转移概率矩阵P
    P=[
        [0.9,  0.1,  0.0,  0.0,  0.0,  0.0],
        [0.5, 0.0, 0.5, 0.0, 0.0, 0.0],
        [0.0, 0.0, 0.0, 0.6, 0.0, 0.4],
        [0.0, 0.0, 0.0, 0.0, 0.3, 0.7],
        [0.0, 0.2, 0.3, 0.5, 0.0, 0.0],
        [0.0, 0.0, 0.0, 0.0, 0.0, 1.0],
    ]
    P=np.array(P)

    rewards = [-1,-2,-2,10,1,0] #定义奖励函数
    gamma=0.5 #定义折扣因子
    # 给定一条序列,计算从某个索引(起始状态)开始到序列最后(终止状态)得到的回报


    chain = [ 1,2 ,3 ,6]
    start_index = 0
    G=compute_returns(start_index, chain, gamma)
    print(G)

4、价值函数怎么计算?

4.1、计算方法:以马尔可夫奖励过程(MRP)为例

假设我们有一个简单的 MRP:

 
  • 状态集合:S = \{s_1, s_2, s_3\}
  • 转移概率矩阵 P:P = \begin{bmatrix} 0.5 & 0.5 & 0 \\ 0 & 0.5 & 0.5 \\ 0 & 0 & 1 \end{bmatrix}(例如:P_{12} = 0.5 表示从s_1 到s_2 的概率为 0.5)
  • 奖励函数 R:R(s_1) = 1, R(s_2) = 2, R(s_3) = 0
  • 折扣因子 \gamma = 0.9
方法 1:直接求解(适用于状态少的情况)

写出每个状态的贝尔曼方程:

 
  1. V(s_1) = 1 + 0.9 \times (0.5V(s_1) + 0.5V(s_2))
  2. V(s_2) = 2 + 0.9 \times (0.5V(s_2) + 0.5V(s_3))
  3. V(s_3) = 0 + 0.9 \times V(s_3) → 解得V(s_3) = 0
 

代入 V(s_3) = 0到方程 2,再解出V(s_2),最后代入方程 1 解出V(s_1)结果V(s_3) = 0\)\(V(s_2) = 4\)\(V(s_1) = 5.8

方法 2:迭代法(适用于状态多的情况)

动态规划迭代更新每个状态的价值,直到收敛:

 
  1. 初始化:V(s) = 0对所有 s
  2. 重复更新:V(s) \leftarrow R(s) + \gamma \sum_{s'} P(s'|s) V(s')
  3. 直到V(s) 不再变化(收敛)。
 

示例迭代过程(简化版):

 
  • 第 1 次迭代V(s_1) = 1 + 0.9 \times (0.5 \times 0 + 0.5 \times 0) = 1\)\(V(s_2) = 2 + 0.9 \times (0.5 \times 0 + 0.5 \times 0) = 2\)\(V(s_3) = 0
  • 第 2 次迭代V(s_1) = 1 + 0.9 \times (0.5 \times 1 + 0.5 \times 2) = 2.35\)\(V(s_2) = 2 + 0.9 \times (0.5 \times 2 + 0.5 \times 0) = 2.9
  • ... 重复迭代直到收敛 → 最终得到V(s_1) = 5.8, V(s_2) = 4, V(s_3) = 0

4.2、直观理解:为什么这样算?

价值函数的本质是 “未来期望总收益”,贝尔曼方程把它拆解成:

 
  • 即时奖励:现在能拿到的好处。
  • 未来价值的期望:下一步可能去的所有状态的价值,按转移概率加权平均,再打个折扣(因为未来不确定)。

迭代法的核心思想是:不断用 “已知的未来状态价值” 来更新 “当前状态价值”,直到每个状态的价值都稳定下来

4.3、完整代码

4.3.1、迭代法计算马尔可夫奖励过程的价值函数

"""
文件名: 3.3.1  迭代法计算马尔可夫奖励过程的价值函数
作者: 墨尘
日期: 2025/7/21
项目名: d2l_learning
备注: 
"""
import numpy as np

if __name__ == '__main__':

    # 定义MRP参数
    states = [1, 2, 3]  # 状态集合
    rewards = {1: 1, 2: 2, 3: 0}  # 奖励函数 R(s)
    gamma = 0.9  # 折扣因子

    # 状态转移概率矩阵 P[s][s'] = P(s'|s)
    transition_probs = {
        1: {1: 0.5, 2: 0.5, 3: 0},
        2: {1: 0, 2: 0.5, 3: 0.5},
        3: {1: 0, 2: 0, 3: 1}
    }

    # 初始化价值函数 V(s) = 0
    V = {s: 0 for s in states}

    # 迭代计算价值函数(动态规划)
    max_iterations = 1000
    tolerance = 1e-10

    for i in range(max_iterations):
        new_V = {}
        for s in states:
            # 计算贝尔曼方程的右侧
            expected_future_value = sum(
                transition_probs[s][s_next] * V[s_next]
                for s_next in states
            )
            new_V[s] = rewards[s] + gamma * expected_future_value

        # 检查收敛性
        max_diff = max(abs(new_V[s] - V[s]) for s in states)
        if max_diff < tolerance:
            print(f"在第 {i + 1} 次迭代后收敛")
            break

        V = new_V

    # 打印结果
    print("\n状态价值函数 V(s):")
    for s in states:
        print(f"V({s}) = {V[s]:.4f}")

4.3.2、直接矩阵求逆法计算价值函数

"""
文件名: 3.3.2  直接矩阵求逆法计算价值函数
作者: 墨尘
日期: 2025/7/21
项目名: d2l_learning
备注: 
"""
import numpy as np

if __name__ == '__main__':

    # 定义MRP参数
    gamma = 0.9  # 折扣因子

    # 状态转移概率矩阵 P
    P = np.array([
        [0.5, 0.5, 0.0],  # 从状态1转移到其他状态的概率
        [0.0, 0.5, 0.5],  # 从状态2转移到其他状态的概率
        [0.0, 0.0, 1.0]  # 从状态3转移到其他状态的概率
    ])

    # 奖励向量 R
    R = np.array([1, 2, 0])  # 状态1、2、3的奖励

    # 计算价值函数 V = (I - γP)^(-1) * R
    I = np.eye(len(P))  # 单位矩阵
    V = np.linalg.inv(I - gamma * P).dot(R)

    # 打印结果
    print("\n状态价值函数 V(s):")
    for i, v in enumerate(V):
        print(f"V({i + 1}) = {v:.4f}")

4.3.3、状态价值函数V(s)计算

"""
文件名: 3.3.3  状态价值函数V(s)计算
作者: 墨尘
日期: 2025/7/21
项目名: d2l_learning
备注: 
"""
import numpy as np

if __name__ == '__main__':

    # 定义环境参数
    num_states = 4  # 状态数:s0, s1, s2, s3
    gamma = 0.9  # 折扣因子

    # 状态转移概率矩阵 P[s][s'] = P(s'|s)
    P = np.array([
        [0.7, 0.3, 0.0, 0.0],  # 从s0转移到其他状态的概率
        [0.0, 0.5, 0.5, 0.0],  # 从s1转移到其他状态的概率
        [0.0, 0.0, 0.3, 0.7],  # 从s2转移到其他状态的概率
        [0.0, 0.0, 0.0, 1.0]  # 从s3(终止状态)转移到自身
    ])

    # 奖励向量 R[s] = 从状态s获得的即时奖励
    R = np.array([1, -1, -2, 0])  # 状态s3为终止状态,奖励为0

    # 初始化价值函数 V(s) = 0
    V = np.zeros(num_states)

    # 迭代计算价值函数(动态规划)
    max_iterations = 1000
    tolerance = 1e-10

    for i in range(max_iterations):
        new_V = np.zeros(num_states)
        for s in range(num_states):
            # 计算贝尔曼方程的右侧:R(s) + γ * Σ P(s'|s)V(s')
            new_V[s] = R[s] + gamma * np.sum(P[s] * V)

        # 检查收敛性
        max_diff = np.max(np.abs(new_V - V))
        if max_diff < tolerance:
            print(f"在第 {i + 1} 次迭代后收敛")
            break

        V = new_V

    # 打印结果
    print("\n状态价值函数 V(s):")
    for s in range(num_states):
        print(f"V(s{s}) = {V[s]:.4f}")

4.3.4、动作价值函数 Q(s,a)计算

"""
文件名: 3.3.4  动作价值函数 Q(s,a)计算
作者: 墨尘
日期: 2025/7/21
项目名: d2l_learning
备注: 
"""

import numpy as np

if __name__ == '__main__':

    # 定义环境参数
    num_states = 3  # 状态数:s0, s1, s2
    num_actions = 2  # 动作数:a0, a1
    gamma = 0.9  # 折扣因子

    # 奖励函数 R[s][a] = 在状态s执行动作a的即时奖励
    R = np.array([
        [1, -2],  # 状态s0执行a0、a1的奖励
        [3, -1],  # 状态s1执行a0、a1的奖励
        [0, 2]  # 状态s2执行a0、a1的奖励
    ])

    # 状态转移概率 P[s][a][s'] = 在状态s执行动作a后转移到s'的概率
    P = np.array([
        [  # 状态s0
            [0.8, 0.2, 0.0],  # 执行动作a0的转移概率
            [0.1, 0.9, 0.0]  # 执行动作a1的转移概率
        ],
        [  # 状态s1
            [0.0, 0.7, 0.3],  # 执行动作a0的转移概率
            [0.0, 0.2, 0.8]  # 执行动作a1的转移概率
        ],
        [  # 状态s2
            [0.0, 0.0, 1.0],  # 执行动作a0的转移概率(终止状态)
            [0.0, 0.0, 1.0]  # 执行动作a1的转移概率(终止状态)
        ]
    ])

    # 初始化动作价值函数 Q(s,a) = 0
    Q = np.zeros((num_states, num_actions))

    # 迭代计算动作价值函数
    max_iterations = 1000
    tolerance = 1e-10

    for i in range(max_iterations):
        new_Q = np.zeros((num_states, num_actions))
        for s in range(num_states):
            for a in range(num_actions):
                # 计算贝尔曼方程的右侧:R(s,a) + γ * Σ P(s'|s,a) * max_a' Q(s',a')
                expected_future_value = np.sum(
                    P[s, a, s_next] * np.max(Q[s_next])
                    for s_next in range(num_states)
                )
                new_Q[s, a] = R[s, a] + gamma * expected_future_value

        # 检查收敛性
        max_diff = np.max(np.abs(new_Q - Q))
        if max_diff < tolerance:
            print(f"在第 {i + 1} 次迭代后收敛")
            break

        Q = new_Q

    # 打印结果
    print("\n动作价值函数 Q(s,a):")
    for s in range(num_states):
        for a in range(num_actions):
            print(f"Q(s{s}, a{a}) = {Q[s, a]:.4f}")

5、R(s,a)和 R(s) 的不同之处?

R(s,a)和 R(s) 是两种不同的奖励定义方式,核心区别在于是否与动作相关。以下是具体对比:

5.1、 定义与适用场景

符号 定义 适用场景 核心特点
R(s) 状态奖励:处于状态 s 时获得的即时奖励 马尔可夫奖励过程(MRP) 不涉及动作,仅与当前状态相关
R(s,a) 动作奖励:在状态 s 执行动作 a 获得的即时奖励 马尔可夫决策过程(MDP) 与当前状态和选择的动作均相关

5.2、直观理解

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐