跳到主要内容

价值函数是什么

价值函数是什么?

价值函数是从某个状态出发,遵循特定策略能够获得的回报总和。那这个价值函数是怎么计算的呢?这里为了简要介绍,就先只使用贝尔曼期望方程来计算价值函数,后面再介绍其他的计算方法。

贝尔曼期望方程基于这样的思想:一个状态的价值是从该状态出发,按照某个策略行动所能得到的所有可能回报的期望值。

贝尔曼期望方程的两种形式

1、状态价值函数(V(s)V(s):状态价值函数评估的是在给定策略下,从特定状态开始的预期累积回报。它不考虑在该状态下可能采取的具体行动。 当决策过程仅需要考虑当前状态而不需要考虑如何采取行动时,状态价值函数非常有用。例如,如果策略是固定的或由环境决定的,那么我们只需要考虑状态的价值。

2、动作价值函数(Q(s,a)Q(s, a):评估在给定策略下,从状态 ss 开始并采取行动 aa 的期望回报。当需要做出具体行动决策时,动作价值函数非常有用,尤其是在策略本身也是学习和优化的目标时。它对于选择最优行动和策略迭代至关重要。

下面介绍下使用贝尔曼期望方程的步骤

  1. 初始化价值函数:通常我们首先对价值函数进行初始化,例如将所有状态的价值设置为零。

  2. 迭代更新:然后,使用贝尔曼期望方程反复更新每个状态的价值。这个过程通常涉及遍历所有状态,并根据方程计算每个状态的新价值。

  3. 策略依赖性:在状态价值函数的情况下,更新取决于当前策略 π\pi。这意味着对于不同的策略,同一状态的价值可能不同。

  4. 收敛:重复这个过程,直到价值函数收敛——即价值函数的变化小于某个预设的阈值。

假设有一个简单的网格世界,状态集合为 {s1,s2,s3,s4}\{s_1, s_2, s_3, s_4\},代理只能采取上、下、左、右移动,每个行动都有可能以等概率随机导致任何一个状态,其中 s4s_4 是终点并给出奖励 1。如果我们要计算状态 s1s_1 的价值,我们会应用贝尔曼期望方程,考虑从 s1s_1 出发,执行所有可能动作后得到的所有可能结果的期望值。

使用这种方法,价值函数可以帮助我们理解在特定策略下每个状态的“好坏”,并可以用来指导代理的决策过程。在实际应用中,这通常是一个迭代和逼近的过程,需要足够的迭代次数才能得到准确的价值估计。

下面详细介绍下状态价值函数和动作价值函数。

状态价值函数

状态价值函数(通常表示为 V(s)V(s))是用于评估在给定策略下,从某个特定状态开始的预期累积回报。它反映了长期效果,考虑了从该状态出发按照特定策略进行的所有可能的未来路径。

对于一个策略 π\pi 和状态 ss,状态价值函数 Vπ(s)V^\pi(s) 可以表示为所有可能的行动 aa 以及所有可能的下一个状态 ss' 的预期回报之和:

Vπ(s)=aAπ(as)sSP(ss,a)[R(s,a,s)+γVπ(s)]V^\pi(s) = \sum_{a \in A} \pi(a|s) \sum_{s' \in S} P(s'|s, a) [R(s, a, s') + \gamma V^\pi(s')]

这里 π(as)\pi(a|s) 是在状态 ss 下选择行动 aa 的概率,P(ss,a)P(s'|s, a) 是从状态 ss 通过行动 aa 转移到状态 ss' 的概率,R(s,a,s)R(s, a, s') 是相应的回报,γ\gamma 是折扣因子。

假设我们有一个简单的环境,包含三个状态 S={s1,s2,s3}S = \{s_1, s_2, s_3\},以及两个动作 A={a1,a2}A = \{a_1, a_2\}。我们的策略 π\pi 是在每个状态下等概率地选择两个动作,即 π(a1s)=π(a2s)=0.5\pi(a_1|s) = \pi(a_2|s) = 0.5 对于所有 ss。转移概率和奖励设置如下:

  • s1s_1 执行 a1a_1 会以 1 的概率转移到 s2s_2,奖励为 0。
  • s1s_1 执行 a2a_2 会以 1 的概率转移到 s3s_3,奖励为 0。
  • s2s_2s3s_3 执行任何动作都会回到 s1s_1,奖励为 1。

假设折扣因子 γ=0.9\gamma = 0.9。我们想要计算 s1s_1 的价值 Vπ(s1)V^\pi(s_1)

  1. 初始化价值:假设所有状态的初始价值为 0,即 Vπ(s1)=Vπ(s2)=Vπ(s3)=0V^\pi(s_1) = V^\pi(s_2) = V^\pi(s_3) = 0

  2. 计算 Vπ(s1)V^\pi(s_1)

Vπ(s1)=a{a1,a2}π(as1)s{s2,s3}P(ss1,a)[R(s1,a,s)+γVπ(s)]Vπ(s1)=0.5×[1×(0+0.9×Vπ(s2))]+0.5×[1×(0+0.9×Vπ(s3))]Vπ(s1)=0.45×(Vπ(s2)+Vπ(s3))\begin{align*} V^\pi(s_1) &= \sum_{a \in \{a_1, a_2\}} \pi(a|s_1) \sum_{s' \in \{s_2, s_3\}} P(s'|s_1, a) [R(s_1, a, s') + \gamma V^\pi(s')] \\ V^\pi(s_1) &= 0.5 \times [1 \times (0 + 0.9 \times V^\pi(s_2))] + 0.5 \times [1 \times (0 + 0.9 \times V^\pi(s_3))] \\ V^\pi(s_1) &= 0.45 \times (V^\pi(s_2) + V^\pi(s_3)) \end{align*}
  1. 计算 Vπ(s2)V^\pi(s_2)Vπ(s3)V^\pi(s_3)
Vπ(s2)=Vπ(s3)=a{a1,a2}π(as2)s=s1P(ss2,a)[R(s2,a,s)+γVπ(s)]Vπ(s2)=Vπ(s3)=0.5×[1×(1+0.9×Vπ(s1))]+0.5×[1×(1+0.9×Vπ(s1))]Vπ(s2)=Vπ(s3)=1+0.9×Vπ(s1)\begin{align*} V^\pi(s_2) &= V^\pi(s_3) = \sum_{a \in \{a_1, a_2\}} \pi(a|s_2) \sum_{s' = s_1} P(s'|s_2, a) [R(s_2, a, s') + \gamma V^\pi(s')] \\ V^\pi(s_2) &= V^\pi(s_3) = 0.5 \times [1 \times (1 + 0.9 \times V^\pi(s_1))] + 0.5 \times [1 \times (1 + 0.9 \times V^\pi(s_1))] \\ V^\pi(s_2) &= V^\pi(s_3) = 1 + 0.9 \times V^\pi(s_1) \end{align*}
  1. 迭代更新:在实际应用中,我们会重复计算这些方程,直到每个状态的价值收敛。在这个简化的例子中,我们可以通过迭代几次来近似求解。

可以看到 s2s_2s3s_3 的价值实际上取决于 s1s_1 的价值,而 s1s_1 的价值又间接受到 s2s_2s3s_3 的价值影响。这种相互依赖通常需要通过迭代方法来解决,例如通过多次应用贝尔曼期望方程来逼近每个状态的真实价值。在实际应用中,这是通过重复迭代直到价值收敛来完成的。这个计算过程是强化学习算法(如动态规划)中价值迭代或策略迭代方法的基础。

提示

贝尔曼期望方程是递归的。它使用当前估计的状态价值来计算新的状态价值。这意味着,每一次迭代都是基于前一次迭代的结果。初始状态价值通常设置为0或其他任意值。因此,第一次迭代的计算是基于这些初始估计的,可能与真实的状态价值有很大差异。在每次迭代中,每个状态的价值根据当前估计的价值来更新。只有经过多次迭代,这些估计才能稳定下来,接近其真实值。其实这些状态的价值通常相互依赖。一个状态的价值可能取决于其他状态的价值。所以这种依赖关系需要通过多次迭代来正确地解析。

“价值收敛” 指的是当连续迭代计算的结果(状态的价值)变化非常小或不再变化时,这意味着我们找到了一个足够接近真实价值的估计。收敛的价值提供了一个策略的良好近似,即在给定策略下从各个状态开始可以获得的长期期望回报。

下面再介绍下,在程序中我们是怎么实现的。

# 定义状态和动作
states = ['s1', 's2', 's3']
actions = ['a1', 'a2']

# 定义策略 pi(a|s):在每个状态下等概率选择任一动作
def policy(state):
return {action: 0.5 for action in actions}

# 定义转移概率和奖励函数
def P_and_R(next_state, state, action):
if state == 's1':
if action == 'a1':
return ('s2', 0) if next_state == 's2' else ('s3', 0)
else:
return ('s3', 0) if next_state == 's3' else ('s2', 0)
else:
return ('s1', 1)

# 折扣因子
gamma = 0.9

# 初始化状态价值
V = {state: 0 for state in states}

# 一次迭代计算状态价值
def value_iteration(V):
new_V = dict(V)
for s in states:
# 可以看到这里使用旧的 V 值来计算新的 V 值
new_V[s] = sum(policy(s)[a] * sum(P_and_R(s_prime, s, a)[1] + gamma * V[P_and_R(s_prime, s, a)[0]]
for s_prime in states)
for a in actions)
return new_V

# 执行一次迭代
V = value_iteration(V)
V
{'s1': 0.0, 's2': 3.0, 's3': 3.0}

动作价值函数

动作价值函数(通常表示为 Q(s,a)Q(s, a))在强化学习中用于评估在给定状态 ss 下采取特定行动 aa 的预期效用。它反映了在状态 ss 采取行动 aa 并遵循某策略之后获得的预期累积回报。

对于一个策略 π\pi、状态 ss 和行动 aa,动作价值函数 Qπ(s,a)Q^\pi(s, a) 可以表示为:

Qπ(s,a)=R(s,a)+γsSP(ss,a)Vπ(s)Q^\pi(s, a) = R(s, a) + \gamma \sum_{s' \in S} P(s'|s, a) V^\pi(s')

这里:

  • Qπ(s,a)Q^\pi(s, a) 是在状态 ss 下采取行动 aa 的价值。
  • R(s,a)R(s, a) 是采取行动 aa 在状态 ss 时得到的即时奖励。
  • γ\gamma 是折扣因子。
  • P(ss,a)P(s'|s, a) 是在状态 ss 采取行动 aa 后转移到状态 ss' 的概率。
  • Vπ(s)V^\pi(s') 是在策略 π\pi 下状态 ss' 的价值。

假设有一个简单的环境,其中代理可以在给定状态下选择不同的行动,并接收相应的奖励。以下是计算动作价值函数的简单Python代码。

import numpy as np

# 定义状态空间和行动空间
states = ['状态1', '状态2']
actions = ['行动A', '行动B']

# 奖励函数
def reward(state, action):
if state == '状态1' and action == '行动A':
return 1
elif state == '状态2' and action == '行动B':
return 2
else:
return 0

# 转移概率,这里简化为确定性转移
def transition(state, action):
if state == '状态1' and action == '行动A':
return '状态2'
elif state == '状态1' and action == '行动B':
return '状态1'
elif state == '状态2':
return '状态1'

# 折扣因子
gamma = 0.9

# 状态价值,简化为固定值
values = {'状态1': 0.5, '状态2': 1}

# 计算动作价值函数
def action_value(state, action):
next_state = transition(state, action)
return reward(state, action) + gamma * values[next_state]

# 示例:计算每个状态下每个行动的价值
for state in states:
for action in actions:
q_value = action_value(state, action)
print(f"在状态 {state} 采取行动 {action} 的价值: {q_value}")

在这个示例中,我们定义了奖励函数和状态转移函数,并对每个状态和行动组合计算了动作价值函数。这个函数考虑了即时奖励和下一个状态的折扣后价值,为代理提供了在每个状态下选择行动的依据。

状态和动作价值函数的区别

下面用一些生活中的场景来比较和理解状态价值函数和动作价值函数的区别。

假设你在选择去哪家餐厅吃饭。你所在的城市有多家餐厅,每家餐厅都提供不同风味的食物。

状态价值函数 V(s)V(s)

  • 定义:状态价值函数 V(s)V(s) 评估的是每家餐厅(每个状态)整体的期望满意度。
  • 应用:如果你只关心餐厅的总体评价(不考虑具体的菜品),那么状态价值函数可以告诉你哪家餐厅预期会给你带来最高的满意度。
  • 例子:餐厅 A 因为环境优雅、服务周到而被认为是一个很好的选择,尽管菜品不是最突出的。

动作价值函数 Q(s,a)Q(s, a)

  • 定义:动作价值函数 Q(s,a)Q(s, a) 评估的是在特定餐厅(状态)选择特定菜品(行动)的期望满意度。
  • 应用:如果你不仅在乎餐厅的总体感受,还在乎你可能点的具体菜品,那么动作价值函数可以帮助你决定在每家餐厅应该点哪道菜。
  • 例子:在餐厅 B,点意大利面(行动)可能会给你带来最佳的用餐体验,而在餐厅 C,选择寿司(行动)可能是最好的选择。

总结一下它们的区别:

  • 状态价值函数 V(s)V(s):帮助你决定哪家餐厅(状态)总体上是最好的,不考虑你在餐厅里可能做的具体选择。
  • 动作价值函数 Q(s,a)Q(s, a):帮助你在特定餐厅(状态)中做出具体选择(行动),比如点哪道菜。

在这个比喻中,状态价值函数更像是对餐厅整体的评价,而动作价值函数则更关注在特定餐厅中的具体菜品选择。这两个函数在决策过程中提供了不同层面的信息,使得你可以根据不同的需求和场景做出更加合适的选择。

状态价值函数的应用

通过一个简化的例子来说明如何在代码中实现和使用状态价值函数。这个例子将模拟一个简单的决策环境,比如一个小机器人在网格世界中寻找目标。

环境设定:

  • 网格世界:一个 4x4 的网格。
  • 状态:每个格子是一个状态。
  • 目标:在右下角的格子(状态)。
  • 行动:上、下、左、右移动。
  • 奖励:达到目标时获得 +1 奖励,其它移动不获得奖励。

目标:

  • 计算每个状态在某个策略下的价值,假设策略是随机移动。
import numpy as np

# 网格大小和状态数
grid_size = 4
n_states = grid_size * grid_size

# 奖励函数
rewards = np.zeros(n_states)
# 在 Python 中,使用负数索引表示从列表或数组的末尾开始计数。
# 因此,rewards[-1] = 1 这行代码的意思是将 rewards 数组的最后一个元素的值设置为 1。
rewards[-1] = 1 # 目标位置的奖励

# 状态转移概率(这里假设四个方向的移动概率相等)
transition_prob = 1.0 / 4 # 四个方向,每个方向概率相同

# 折扣因子
gamma = 0.9

# 这里巧妙的使用了整数除法和取余运算,将状态转换为坐标
#
# 这段代码中的 get_next_state 函数是用来计算在给定的行动后机器人(代理)将会处于的下一个状态。
# 在网格世界中,状态是用单个整数来表示的,其中网格的左上角是状态 0,右下角是状态 15(在一个 4x4 的网格中)。
# 这个函数根据当前状态和行动来确定代理接下来将移动到的位置(状态)。
#
# 举个例子,如果当前状态是 0(即左上角),行动是“下”,那么下一个状态将是 4(即正下方的格子)。
# 如果行动是“右”,那么下一个状态将是 1(即右边的格子)。
# 如果行动是“上”或“左”,由于已经在边界,代理不会移动,因此返回的状态仍然是 0。
def get_next_state(state, action, grid_size):
"""根据当前状态和行动计算下一个状态"""
x, y = state // grid_size, state % grid_size
if action == '上' and x > 0:
return (x - 1) * grid_size + y
elif action == '下' and x < grid_size - 1:
return (x + 1) * grid_size + y
elif action == '左' and y > 0:
return x * grid_size + (y - 1)
elif action == '右' and y < grid_size - 1:
return x * grid_size + (y + 1)
return state # 如果行动无效,保持当前状态

def choose_best_action(state, values, grid_size):
"""选择最佳行动,基于最大化价值"""
actions = ['上', '下', '左', '右']
best_action = None
best_value = -float('inf')

for action in actions:
next_state = get_next_state(state, action, grid_size)
value = values[next_state]
if value > best_value:
best_value = value
best_action = action

return best_action

# 初始化状态价值
values = np.zeros(n_states)

# 迭代计算状态价值
for _ in range(1000):
new_values = np.copy(values)
for state in range(n_states):
value_sum = 0
for action in range(4): # 四个方向
next_state = ... # 根据当前状态和行动计算下一个状态
value_sum += transition_prob * (rewards[next_state] + gamma * values[next_state])
new_values[state] = value_sum
values = new_values


# 对每个状态选择最佳行动
best_actions = np.empty(n_states, dtype=object)
for state in range(n_states):
best_actions[state] = choose_best_action(state, values, grid_size)

print("每个状态的最佳行动:", best_actions.reshape(grid_size, grid_size))

在这个代码中,我们首先定义了一个 4x4 的网格世界,并为每个状态初始化了价值函数。接下来,我们迭代地更新每个状态的价值,考虑从该状态开始,按照随机策略采取行动后可能达到的所有状态和相应的奖励。状态价值的更新基于贝尔曼方程,考虑了所有可能的下一个状态及其价值。 所以,我们可以知道在这个例子中,状态价值的计算是基于所有可能的未来路径和相应的奖励的加权平均。

这个简单的例子展示了如何在代码中实现状态价值函数,并用它来评估在给定策略下各个状态的长期价值。在实际的强化学习应用中,这个过程会更加复杂和动态,通常涉及学习最优策略,并实时更新状态价值。

计算价值函数的方法

上面介绍了如何使用贝尔曼方程来计算状态价值函数。但是,这种方法需要完整的环境模型,即需要知道状态转移概率和奖励函数。在实际应用中,我们通常不知道这些信息,因此需要使用其他方法来估计价值函数。

下面按照分类来介绍几种常用的方法。

动态规划

动态规划(Dynamic Programming, DP)是解决马尔可夫决策过程(MDP)中计算价值函数的一种方法,尤其适用于那些状态空间和动作空间不是特别大,且环境模型(状态转移概率和奖励函数)已知的情况。以下是两种主要的动态规划算法:

1、策略迭代(Policy Iteration)

策略迭代是一个两阶段的过程,包括策略评估和策略改进。

(1.) 策略评估(Policy Evaluation): 在这一步骤中,算法评估当前策略的价值,即计算在该策略下从每个状态出发的预期回报。这通常通过迭代应用贝尔曼期望方程来实现,直到状态价值函数收敛。

提示

贝尔曼期望方程:

V(s)=aAπ(as)sP(ss,a)(R(s,a,s)+γV(s))V(s) = \sum_{a \in A} \pi(a|s) \sum_{s'} P(s'|s,a) \left( R(s,a,s') + \gamma V(s') \right)

其中 π\pi 是策略,PP 是转移概率,RR 是奖励,γ\gamma 是折扣因子。

(2.) 策略改进(Policy Improvement):

  • 基于当前的价值函数来改进策略。对于每个状态,选择使得期望回报最大化的动作作为新的策略。
  • 策略改进定理保证这一过程会得到一个等于或优于当前策略的新策略。

策略迭代交替进行策略评估和策略改进,直到策略收敛。

2、价值迭代(Value Iteration)

价值迭代是策略迭代的一种特殊形式,它将策略评估和策略改进步骤结合在一起。

  • 在价值迭代中,你不需要等待策略评估步骤完全收敛。在每次迭代中,你都会更新状态的价值估计,并基于这个新的估计来改进策略。
  • 价值迭代使用的是贝尔曼最优方程:V(s)=maxaAsP(ss,a)(R(s,a,s)+γV(s))V(s) = \max_{a \in A} \sum_{s'} P(s'|s,a) \left( R(s,a,s') + \gamma V(s') \right)。这里,我们选择的是使价值最大化的动作,而不是根据当前策略选择动作。

价值迭代通常比策略迭代更快收敛,尤其是在状态价值函数变化很大的情况下。

应用和局限性

动态规划方法在理论上非常强大,能够为有完整知识的 MDP 找到最优策略。然而,在实际应用中,它们面临一些限制,如:

  • 状态空间大小:对于有大量状态的问题,动态规划可能变得不切实际,因为它需要为每个状态存储和更新价值。
  • 环境模型的需求:动态规划需要完整的环境模型,包括所有状态转移概率和奖励。在很多实际问题中,这种信息可能不可用或难以准确获得。

因此,尽管动态规划在理论上是解决 MDP 的有效方法,但在实践中常常需要与其他技术(如蒙特卡洛方法或时序差分学习)结合使用。

蒙特卡洛方法

蒙特卡洛方法(Monte-Carlo methods)也被称为统计模拟方法,是一种基于概率统计的数值计算方法。运用蒙特卡洛方法时,我们通常使用重复随机抽样,然后运用概率统计方法来从抽样结果中归纳出我们想求的目标的数值估计。

一个简单的例子是用蒙特卡洛方法来计算圆的面积。例如,在图 3-5 所示的正方形内部随机产生若干个点,细数落在圆中点的个数,圆的面积与正方形面积之比就等于圆中点的个数与正方形中点的个数之比。如果我们随机产生的点的个数越多,计算得到圆的面积就越接近于真实的圆的面积。

工作机制

1、回合制采样:蒙特卡洛方法要求问题可以被分解为多个独立的回合,每个回合都从某个初始状态开始,经过一系列的状态和动作,最终到达一个终止状态。

2、计算回报:对于每个回合,计算从每个访问状态开始到回合结束的累积奖励(回报)。这通常涉及到奖励的折扣,即后续奖励比即时奖励的影响小。

3、估计价值函数:通过对多个回合的回报进行平均来估计状态的价值。随着回合数的增加,估计的准确度通常会提高。

优点:

  • 简单易于实现。
  • 不需要完整的环境模型。
  • 在环境模型难以获取或不准确时特别有用。

缺点:

  • 需要较多的样本来获得准确的估计。
  • 只适用于可以清楚地划分为独立回合的问题。
  • 估计的方差可能较大,特别是在回合较长的情况下。

蒙特卡洛方法在解决一些特定类型的强化学习问题时非常有效,特别是在缺乏环境模型或环境模型难以准确建立时。然而,它们通常需要与其他方法(如动态规划或时序差分学习)结合使用,以适应不同类型的强化学习场景。

时间差分学习(TD学习)

时间差分学习(Temporal Difference Learning,简称TD学习)是强化学习中的一种核心方法,它结合了蒙特卡洛方法和动态规划的一些主要特点。TD学习既不需要像动态规划那样对环境的完整模型有所了解,也不需要像蒙特卡洛方法那样等待一个完整的回合结束才进行学习和更新。这使得TD学习在许多强化学习场景中非常有用。

TD学习的核心思想是在预测(价值函数)的基础上学习。它通过比较连续时间步的预测来计算时序差分误差(TD误差),然后使用这个误差来更新价值函数。 这种方法允许智能体在不了解完整环境模型的情况下,仅凭经验来学习价值函数。

工作机制

  1. TD误差:在时间步 ttt+1t+1 之间,TD误差定义为 Rt+1+γV(St+1)V(St)R_{t+1} + \gamma V(S_{t+1}) - V(S_t),其中 Rt+1R_{t+1} 是在时间步 tt 获得的奖励,V(St)V(S_t)V(St+1)V(S_{t+1}) 分别是在时间步 ttt+1t+1 估计的状态价值,γ\gamma 是折扣因子。

  2. 价值函数更新**:价值函数更新公式为 V(St)V(St)+α[Rt+1+γV(St+1)V(St)]V(S_t) \leftarrow V(S_t) + \alpha \left[ R_{t+1} + \gamma V(S_{t+1}) - V(S_t) \right],其中 α\alpha 是学习率。

TD 学习的变体

  • TD(0):最基本的TD学习形式,每次更新仅基于下一个时间步的信息。
  • TD(λ\lambda):一种更一般的形式,它结合了多个步骤的信息来进行更新。
  • SARSA(State-Action-Reward-State-Action):一种在策略性环境中使用的TD学习方法,它涉及当前状态、动作、奖励、下一状态和下一动作。
  • Q-learning:一种著名的 TD 学习算法,用于学习动作价值函数(Q 函数)。它与 SARSA 不同之处在于,它学习的是在当前策略下的最优动作价值函数。

优点:

  • TD学习适用于连续的、无需等待回合结束的环境,这在许多实际问题中非常常见。
  • TD学习不依赖于环境的完整模型,这使得它在模型未知的情况下特别有用。
  • 与蒙特卡洛方法相比,TD学习通常学习得更快,因为它不需要等待回合结束就可以更新价值估计。

缺点:

  • TD学习的表现高度依赖于它的参数设置,如学习率和折扣因子。
  • 它可能对初始值设定敏感,并且可能存在收敛性问题,尤其是在函数近似用于估计价值函数时。
  • 在某些情况下,TD学习可能不如蒙特卡洛方法稳定,特别是在估计的方差较大时(例如,在蒙特卡洛方法中,状态价值的估计是基于从该状态开始的所有完成的回合的回报。如果不同回合的回报差异很大,那么对该状态价值的估计就会有很大的波动性)。