強化學習隨機策略之高斯似然數原理與代碼實現

強化學習隨機策略之高斯似然數原理與代碼實現

一、原理介紹

使用隨機策略有兩個關鍵點

  • 從策略當中進行採樣,獲得動作 aa (Action)
  • 計算特定動作的似然數 logπθ(as)\log \pi _ { \theta } ( a | s )

什麼是多元高斯分佈?

在多元高斯分佈中,當協方差矩陣 Σ\Sigma 只有在對角元素非零,而其餘元素爲 0 時,成爲對角高斯分佈。
多元高斯分佈(Multivariate Gaussian Distribution)是一元高斯分佈的在向量形式上的推廣,其中向量 X=[X1,X2,,Xn]TX = \left[ X _ { 1 } , X _ { 2 } , \ldots , X _ { n } \right] ^ { T } 的均值爲 μRn\mu \in \mathbf { R } ^ { n } ,協方差矩陣爲 ΣSn\Sigma \in S ^ { n } ,概率密度函數表示爲

p(x;μ,Σ)=1(2π)n/2Σ1/2exp(12(xμ)TΣ1(xμ))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)

例如二元高斯多元分佈可以如圖所示

.

對於一對隨機變量 XXYY ,它們的協方差矩陣寫作

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

對於多個變量的問題,用協方差矩陣 ΣSn\Sigma \in S ^ { n } 來表示各個變量之間的相關性,有

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

對角多元高斯分佈

特殊地,當 N 個隨機變量 X=[X1,X2,,Xn]TX = \left[ X _ { 1 } , X _ { 2 } , \ldots , X _ { n } \right] ^ { T } 爲各自獨立的高斯隨機變量時,協方差矩陣爲對角陣,即

Σ=diag(σ12,σ22,,σn2)\Sigma = \operatorname { diag } \left( \sigma _ { 1 } ^ { 2 } , \sigma _ { 2 } ^ { 2 } , \ldots , \sigma _ { n } ^ { 2 } \right)

對角高斯策略 Diagonal Gaussian Policies

由於標準差的公式 σ=1Ni=1N(xiμ)2\sigma = \sqrt { \frac { 1 } { N } \sum _ { i = 1 } ^ { N } \left( x _ { i } - \mu \right) ^ { 2 } } 可知 σ\sigma 始終大於等於 0 ,對標準差取 log 對數,可以將標準差映射到 (,)( - \infty , \infty ),這樣更有利於神經網絡的訓練。

  • 採樣:假設已知動作(Action) 的均值 μθ(s)\mu _ { \theta } ( s ) 和標準差 σθ(s)\sigma _ { \theta } ( s ) ,引入服從 (zN(0,I))( z \sim \mathcal { N } ( 0 , I ) ) 分佈的噪聲 zz ,下一步的動作採樣表示爲
    a=μθ(s)+σθ(s)za = \mu _ { \theta } ( s ) + \sigma _ { \theta } ( s ) \odot z
    其中 \odot 表示兩個向量之間的內積。

  • 似然數:當均值爲 μ=μθ(s)\mu = \mu _ { \theta } ( s ) ,標準差爲 σ=σθ(s)\sigma = \sigma _ { \theta } ( s )kk-維的動作 aa 的似然數表示爲
    logπθ(as)=12(i=1k((aiμi)2σi2+2logσi)+klog2π)\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 的似然數
import tensorflow as tf
import numpy as np
EPS = 1e-8

根據上一節,似然數公式,理解公式後就很容易寫出代碼

# 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
# 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)
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

參考鏈接

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章