强化学习随机策略之高斯似然数原理与代码实现

一、原理介绍

使用随机策略有两个关键点

  • 从策略当中进行采样,获得动作 \(a\) (Action)
  • 计算特定动作的似然数 \(\log \pi _ { \theta } ( a | s )\)

什么是多元高斯分布?

在多元高斯分布中,当协方差矩阵 \(\Sigma\) 只有在对角元素非零,而其余元素为 0 时,成为对角高斯分布。 多元高斯分布(Multivariate Gaussian Distribution)是一元高斯分布的在向量形式上的推广,其中向量 \(X = \left[ X _ { 1 } , X _ { 2 } , \ldots , X _ { n } \right] ^ { T }\) 的均值为 \(\mu \in \mathbf { R } ^ { n }\) ,协方差矩阵为 \(\Sigma \in S ^ { n }\) ,概率密度函数表示为

\[p ( x ; \mu , \Sigma ) = \frac { 1 } { ( 2 \pi ) ^ { n / 2 } | \Sigma | ^ { 1 / 2 } } \exp \left( - \frac { 1 } { 2 } ( x - \mu ) ^ { T } \Sigma ^ { - 1 } ( x - \mu ) \right)\]

例如二元高斯多元分布可以如图所示

.

对于一对随机变量 \(X\)\(Y\) ,它们的协方差矩阵写作

\[\operatorname { Cov } [ X , Y ] = E [ ( X - E [ X ] ) ( Y - E [ Y ] ) ] = E [ X Y ] - E [ X ] E [ Y ]\]

对于多个变量的问题,用协方差矩阵 \(\Sigma \in S ^ { n }\) 来表示各个变量之间的相关性,有

\[\Sigma = E \left[ ( X - \mu ) ( X - \mu ) ^ { T } \right] = E \left[ X X ^ { T } \right] - \mu \mu ^ { T }\]

对角多元高斯分布

特殊地,当 N 个随机变量 \(X = \left[ X _ { 1 } , X _ { 2 } , \ldots , X _ { n } \right] ^ { T }\) 为各自独立的高斯随机变量时,协方差矩阵为对角阵,即

\[\Sigma = \operatorname { diag } \left( \sigma _ { 1 } ^ { 2 } , \sigma _ { 2 } ^ { 2 } , \ldots , \sigma _ { n } ^ { 2 } \right)\]

对角高斯策略 Diagonal Gaussian Policies

由于标准差的公式 \(\sigma = \sqrt { \frac { 1 } { N } \sum _ { i = 1 } ^ { N } \left( x _ { i } - \mu \right) ^ { 2 } }\) 可知 \(\sigma\) 始终大于等于 0 ,对标准差取 log 对数,可以将标准差映射到 \(( - \infty , \infty )\),这样更有利于神经网络的训练。

  • 采样:假设已知动作(Action) 的均值 \(\mu _ { \theta } ( s )\) 和标准差 \(\sigma _ { \theta } ( s )\) ,引入服从 \(( z \sim \mathcal { N } ( 0 , I ) )\) 分布的噪声 \(z\) ,下一步的动作采样表示为 \[a = \mu _ { \theta } ( s ) + \sigma _ { \theta } ( s ) \odot z\] 其中 \(\odot\) 表示两个向量之间的内积。

  • 似然数:当均值为 \(\mu = \mu _ { \theta } ( s )\) ,标准差为 \(\sigma = \sigma _ { \theta } ( s )\)\(k-\)维的动作 \(a\) 的似然数表示为 \[\log \pi _ { \theta } ( a | s ) = - \frac { 1 } { 2 } \left( \sum _ { i = 1 } ^ { k } \left( \frac { \left( a _ { i } - \mu _ { i } \right) ^ { 2 } } { \sigma _ { i } ^ { 2 } } + 2 \log \sigma _ { i } \right) + k \log 2 \pi \right)\]

二、代码实现

要求 - 输入: 样本 x,对角高斯分布的均值和标准差 - 输出:样本 x 的似然数

1
2
3
import tensorflow as tf
import numpy as np
EPS = 1e-8

根据上一节,似然数公式,理解公式后就很容易写出代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# my solution
def my_gaussian_likelihood(x, mu, log_std):
"""
Args:
x: Tensor with shape [batch, dim]
mu: Tensor with shape [batch, dim]
log_std: Tensor with shape [batch, dim] or [dim]
Returns:
Tensor with shape [batch]
"""
#######################
# #
# YOUR CODE HERE #
# #
#######################
std = tf.exp(log_std)
ans = ((x - mu) / std)**2 + 2 * log_std + np.log(2 * np.pi)
ans = -0.5 * ans
# https://www.tensorflow.org/api_docs/python/tf/math/reduce_sum
sum_ans = tf.reduce_sum(ans, axis=1)
return sum_ans
1
2
3
4
5
# standard solution
# 代码来自 spinup/exercises/problem_set_1_solutions/exercise1_2_soln.py
def ans_gaussian_likelihood(x, mu, log_std):
pre_sum = -0.5 * (((x-mu)/(tf.exp(log_std)+EPS))**2 + 2*log_std + np.log(2*np.pi))
return tf.reduce_sum(pre_sum, axis=1)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
if __name__ == '__main__':
"""
Run this file to verify your solution.
"""

sess = tf.Session()

dim = 10
x = tf.placeholder(tf.float32, shape=(None, dim))
mu = tf.placeholder(tf.float32, shape=(None, dim))
log_std = tf.placeholder(tf.float32, shape=(dim,))

your_gaussian_likelihood = my_gaussian_likelihood(x, mu, log_std)
true_gaussian_likelihood = ans_gaussian_likelihood(x, mu, log_std)

batch_size = 32
feed_dict = {x: np.random.rand(batch_size, dim),
mu: np.random.rand(batch_size, dim),
log_std: np.random.rand(dim)}

your_result, true_result = sess.run([your_gaussian_likelihood, true_gaussian_likelihood],
feed_dict=feed_dict)

correct = np.allclose(your_result, true_result)

print("Your answer is", correct)
Your answer is True

参考链接