1. 价值迭代算法
价值迭代方法在迭代过程直接更新行动的值函数。具体步骤为:
- 初始化 s s s, V V V
- 进行一定次数的迭代直至 V V V收敛:根据 s s s, P P P, R R R, V V V得到新 V V V: V = max a P ( R ′ + γ V ′ ) V=\max_a P(R'+\gamma V') V=maxaP(R′+γV′);
- 计算最优策略,遍历所有可能action找出最优的策略,矩阵形式为 Π = arg max a P ( R ′ + γ V ′ ) \Pi = \arg \max_{a} P(R'+\gamma V') Π=argmaxaP(R′+γV′)。
那么它和上一节限制最大迭代次数为一的策略迭代有什么不同呢?
策略迭代法的核心是策略,每一轮的价值计算出来是为了更新策略用的,直观来看代码上有更新策略
Π
\Pi
Π的代码;而在价值迭代法中,核心是价值,每一轮迭代都是用上一轮的价值和这一轮的可能行动来更新价值
V
V
V,最后给出的是每个状态的值函数,策略需要用户自己推算。
价值迭代算法的核心公式为:
V
=
max
a
P
(
R
′
+
γ
V
′
)
V=\max_{a} P(R'+\gamma V')
V=maxaP(R′+γV′),这个公式直观上看是把策略迭代中的迭代过程从策略评估阶段移到了策略提升阶段。这两种方法的主要差异:策略迭代方法目标是让策略收敛,而价值迭代方法是让价值收敛。因此策略迭代方法中策略是一直变化的(使用贪婪策略不断更新),而价值迭代方法中策略是不变的贪婪策略。
2. 价值迭代方法的实现
下面按照第一节的步骤定义价值迭代:
class ValueIteration(object):
def value_iteration(self, agent, max_iter = -1):
iteration = 0
while True:
iteration += 1
new_value_pi = np.zeros_like(agent.value_pi)
for i in range(1, agent.s_len):
value_sas = []
# a作为一个中间变量存在,每次迭代直接给出最优的V
for j in range(0, agent.a_len):
value_sa = np.dot(agent.p[j, i, :], agent.r + agent.gamma * agent.value_pi)
value_sas.append(value_sa)
new_value_pi[i] = max(value_sas)
diff = np.sqrt(np.sum(np.power(agent.value_pi - new_value_pi, 2)))
if diff < 1e-6:
break
else:
agent.value_pi = new_value_pi
if iteration == max_iter:
break
print('Iter {} rounds converge'.format(iteration))
for i in range(1, agent.s_len):
for j in range(0, agent.a_len):
agent.value_q[i,j] = np.dot(agent.p[j,i,:], agent.r + agent.gamma * agent.value_pi)
max_act = np.argmax(agent.value_q[i,:])
agent.pi[i] = max_act
3. 测试效果
因为不会每一轮对价值函数进行迭代计算,所以价值迭代一般来说比策略迭代要快一些。下面对比测试一下:
ladders info:
{41: 94, 55: 91, 94: 41, 52: 51, 47: 17, 83: 49, 46: 63, 31: 53, 49: 83, 91: 55, 51: 52, 17: 47, 15: 83, 63: 46, 53: 31}
Iter 3 rounds converge
Timer PolicyIter COST:0.2829549312591553
return_pi=90
Iter 94 rounds converge
Value PolicyIter COST:0.18909621238708496
return_pi=88
由于价值迭代没有内部的价值收敛迭代,因此总的迭代轮数比策略迭代要多很多,在上面的案例中,要94次之后才收敛。接下来看看价值迭代法中,s=50的值函数变化情况:
可以看出,在经历了最初一段时间后,算法很快回到了正确的道路上最后收敛。