今天写RL中的MC算法的时候,卡在了First visit和Every visit这两种算法的区别上。一直没搞懂什么意思
这里因为有多个episode,每一个episode中使用第一次出现的Q(S,A)当做这个episode中的Q值,对多个episode中出现的Q(S,A)求和,然后分母是有多少个episode含有这个pair(S,A)
下面附上转载的代码:
updated_values = {}
### PUT YOUR CODE HERE ###
state_action_pairs = list(zip(obses, actions))
g = 0
for t in range(len(obses)-1, -1, -1):
g = self.gamma * g + rewards[t]
pair = state_action_pairs[t]
if pair not in self.sa_counts:
self.sa_counts[pair] = 1
else:
self.sa_counts[pair] += 1
if pair not in state_action_pairs[:t]: # 在前t个timestep内第一次出现: the first occurrence of (s, a)
updated_values[pair] = g # append G to Return (S_t,A_t)
# Q(S_t,A_t) <- average(Return(S_t,A_t))
self.q_table[pair] = (self.q_table[pair] * (self.sa_counts[pair] - 1) + g) / self.sa_counts[pair]
return updated_values
注意,这一行代码:
self.q_table[pair] = (self.q_table[pair] * (self.sa_counts[pair] - 1) + g) / self.sa_counts[pair]
其实就等价于求和取平均值:因为我们是先求出Q的平均值,再统计次数。在第二次更新的时候,这个(self.sa_counts[pair] - 1) * self.q_table[pair]其实就是求和。然后我们再加上在当前episode中的Q(S, A),再取平均值,就完成了逻辑上的闭环
不得不感叹这几行代码写的真优雅