無跡卡爾曼濾波-2


對於上一篇中的問題:X ∼ N(µ, σ^2 ) , Y = sin(X)要求隨機變量Y的期望和方差。還有一種思路是對X進行采樣,比如取500個采樣點(這些采樣點可以稱為sigma點),然后求取這些采樣點的期望和方差。當采樣值足夠大時,結果與理論值接近。這種思路的問題顯而易見,當隨機變量維數增大時采樣點的數量會急劇增加,比如一維需要500個采樣點,二維就需要500^=250,000個采樣點,三維情況下需要500^3=125,000,000個采樣點,顯然這樣會造成嚴重的計算負擔。無跡卡爾曼濾法中采用一種方法來選取2n+1個sigma點,n為隨機變量維數。

如上圖所示,考慮正態分布曲線的對稱性,選取3個sigma點來計算(sigma點的選取方法不唯一),其中一個是均值,另外兩個sigma點關於均值對稱分布。比如三個點可選為:

χ= μ;

χ= μ + σ;

χ= μ - σ;

然后選取合適的權值Wi滿足如下關系

使用同樣的公式近似計算Y=sin(X)分布的數字特征:

類比推廣到多維隨機變量X ∼ N(μ ,Σ),Σ為協方差矩陣,采用Cholesky分解計算出矩陣L(Σ = LLT)  ,矩陣L可以類比一維情況下的標准差σ。則sigma點可以寫成下面的形式:

χ0 = μ;

χi = μ + cL;

χn+i = μ - cL; c為一個正的常數

則對於非線性變換Y=g(X),可以計算出變換后的期望和方差:

關鍵問題是如何選取sigma點和權值。常見的一種方法是第一個sigma點選為χ0=μ,n是隨機變量X的維數,α,κ,λ均為常數,並有如下關系

 

其余2n個sigma點的計算公式如下,其中下標i表示矩陣L的第i列

接下來要計算權值。對求期望來說,第一個sigma點的權值為:

對求方差來說,第一個sigma點的權值為如下,式子中的β也為一個常數

對於剩下的2n個sigma點來說求期望的權值和求方差的權值都相同:

因此,一共有三個常數(α,β,κ)需要我們來設定。根據其它參考資料,選擇參數的經驗為:β=is a good choice for Gaussian problems, κ=3is a good choice for κ , and 0αis an appropriate choice for α

α越大,第一個sigma點(平均值處)占的權重越大,並且其它sigma點越遠離均值。如下圖所示,對2維隨機變量選取5個sigma點,點的大小代表權重,由感性認識可知sigma點離均值越遠其權重應該越小。

 

根據上述計算步驟和公式我們可以編程實現sigma點的選擇,權值的計算。在Python中我們可以采用現成的工具FilterPy安裝pip工具后可以直接輸入命令:pip install filterpy進行安裝。

 1 # -*- coding: utf-8 -*-
 2 from filterpy.kalman import MerweScaledSigmaPoints as SigmaPoints
 3 
 4 mean = 0    # 均值
 5 cov =  1    # 方差
 6 
 7 points = SigmaPoints(n=1, alpha=0.1, beta=2.0, kappa=1.0)  
 8 Wm, Wc = points.weights()
 9 sigmas = points.sigma_points(mean, cov)
10 
11 print Wm, Wc    # 計算均值和方差的權值
12 print sigmas    # sigma點的坐標

對於標准正態分,輸出結果如下:

 

下面舉一個2維正態分布的例子。從一個服從二維正態分布的隨機變量中隨機選取1000個點,該二維隨機變量的期望和協方差矩陣為:

接下來將這1000個點進行如下非線性變換:

下面使用unscented transform方法近似計算非線性變換后隨機變量的期望,並與直接從1000個點計算出的期望值對比

 1 # -*- coding: utf-8 -*-
 2 import numpy as np
 3 from scipy import stats
 4 import matplotlib.pyplot as plt
 5 from numpy.random import multivariate_normal
 6 from filterpy.kalman import unscented_transform
 7 from filterpy.kalman import MerweScaledSigmaPoints as SigmaPoints
 8 
 9 # 非線性變換函數
10 def f_nonlinear_xy(x, y):
11     return np.array([x + y, 0.1*x**2 + y**2])
12 
13 def plot1(xs, ys):
14     xs = np.asarray(xs) 
15     ys = np.asarray(ys)
16     xmin = xs.min()
17     xmax = xs.max()
18     ymin = ys.min()
19     ymax = ys.max()
20     values = np.vstack([xs, ys])  
21     kernel = stats.gaussian_kde(values)   
22     X, Y = np.mgrid[xmin:xmax:100j, ymin:ymax:100j]
23     positions = np.vstack([X.ravel(), Y.ravel()])
24     Z = np.reshape(kernel.evaluate(positions).T, X.shape)  
25     plt.imshow(np.rot90(Z),cmap=plt.cm.Greys,extent=[xmin, xmax, ymin, ymax])
26     plt.plot(xs, ys, 'k.', markersize=2)
27     plt.xlim(-20, 20)
28     plt.ylim(-20, 20)
29    
30 def plot2(xs, ys, f, mean_fx):
31     fxs, fys = f(xs, ys)    # 將采樣點進行非線性變換
32     computed_mean_x = np.average(fxs)   
33     computed_mean_y = np.average(fys)
34     plt.subplot(121)
35     plt.grid(False)
36     plot1(xs, ys)
37     plt.subplot(122)
38     plt.grid(False)
39     plot1(fxs, fys)
40     plt.scatter(fxs, fys, marker='.', alpha=0.01, color='k')
41     plt.scatter(mean_fx[0], mean_fx[1], marker='o', s=100, c='r', label='UT_mean')
42     plt.scatter(computed_mean_x, computed_mean_y, marker='*',s=120, c='b', label='mean')
43     plt.ylim([-10, 200])
44     plt.xlim([-100, 100])
45     plt.legend(loc='best', scatterpoints=1)
46     print ('Difference in mean x={:.3f}, y={:.3f}'.format(
47            computed_mean_x-mean_fx[0], computed_mean_y-mean_fx[1]))
48     
49 # -------------------------------------------------------------------------------------------
50 mean = [0, 0]               # Mean of the N-dimensional distribution.
51 cov = [[32, 15], [15, 40]]  # Covariance matrix of the distribution.
52 
53 # create sigma points(2n+1個sigma點)
54 # uses 3 parameters to control how the sigma points are distributed and weighted
55 points = SigmaPoints(n=2, alpha=.1, beta=2., kappa=1.)  
56 Wm, Wc = points.weights()
57 sigmas = points.sigma_points(mean, cov)
58 
59 # pass through nonlinear function
60 sigmas_f = np.empty((5, 2))
61 for i in range(5):  
62     sigmas_f[i] = f_nonlinear_xy(sigmas[i, 0], sigmas[i ,1]) 
63 
64 # use unscented transform to get new mean and covariance
65 ukf_mean, ukf_cov = unscented_transform(sigmas_f, Wm, Wc)
66 
67 # generate random points
68 xs, ys = multivariate_normal(mean, cov, size=1000).T  # 從二維隨機變量的正態分布中產生1000個數據點
69 plot2(xs, ys, f_nonlinear_xy, ukf_mean)
70 
71 # 畫sigma點
72 plt.xlim(-30, 30); plt.ylim(0, 90)
73 plt.subplot(121)
74 plt.scatter(sigmas[:,0], sigmas[:,1], c='r', s=30) 
75 plt.show()

結果如下圖所示,左圖中黑點為1000個采樣點,5個紅色的點為sigma點,圖中陰影表示概率密度的大小,顏色越深的地方概率密度越大。右圖中的紅點為用5個sigma點經UT變換計算出的近似期望,藍色星號標記點為將1000個采樣點非線性變換后直接計算出的期望。可以看出和直接產生1000個點經非線性變換計算期望相比,使用unscented transform的計算量要小的多,並且誤差也不大。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM