赞
踩
上一篇【机器学习】粒子滤波原理推导(二),我们已经对粒子滤波的原理和实现流程进行了原理推导求解。接下来,我们就案例而言,来看看粒子滤波的实际应用。
假设,有一辆汽车,其初始位置是 x , y = ( 0 , 0 ) x,y =(0,0) x,y=(0,0),经过了50个时刻后,按照我们运动方程式,假设它能够去到点 x , y = ( 0 , 65 ) x,y=(0,65) x,y=(0,65)的位置。也就是做个半圆运动。
但是现实生活中,往往存在各种各样的噪声,也许是地面凹凸不平,亦或者是风阻较大,所以我们引入误差。结果得到的图是这样。
可以看到,每一个时刻,它并不是按照运动方程规定的那样。是存在一定的误差的,也许前一个时刻快了一点,也许下一个时刻又慢了一点。
因为存在误差,所以我们给这辆汽车搭载一个GPS定位,每一个时刻都返回汽车的位置信息。但是GPS的定位也不精准,也存在一定的误差。结果得到的图是这样的
那么如何利用粒子滤波,让其预测相对来说更加合理。
我们定义运动方程,对于x坐标我们用
z
1
z^1
z1表示,假设一个时刻为1秒。小车速度为
2
m
/
s
2m/s
2m/s,角速度
3.6
°
/
s
3.6°/s
3.6°/s,所以时刻t的横坐标位置为
z
t
1
=
z
t
−
1
1
+
v
∗
cos
(
t
∗
a
n
g
l
e
)
+
u
1
z^1_{t}=z^{1}_{t-1}+v*\cos(t*angle)+u_1
zt1=zt−11+v∗cos(t∗angle)+u1
u
1
u_1
u1为随机误差,v为速度,angle为角速度,
z
t
−
1
1
z^{1}_{t-1}
zt−11为上一时刻的横坐标位置
对于y坐标y,我们用
z
2
z^2
z2表示
z
t
2
=
z
t
−
1
2
+
v
∗
sin
(
t
∗
a
n
g
l
e
)
+
u
2
z_t^{2}=z_{t-1}^{2}+v*\sin(t*angle)+u_2
zt2=zt−12+v∗sin(t∗angle)+u2
u
2
u_2
u2为随机误差,其他都一样
而同理对于GPS的x坐标我们用
x
1
x^1
x1表示
x
t
1
=
z
t
1
+
ω
1
x^1_t=z_t^1+\omega_1
xt1=zt1+ω1
ω
1
\omega_1
ω1为随机误差,
z
t
1
z_t^1
zt1为运动方程中t时刻的横坐标,同理得y坐标,我们用
x
2
x^2
x2表示
x
t
2
=
z
t
2
+
ω
2
x_t^2=z_t^2+\omega_2
xt2=zt2+ω2
将上述表示成矩阵形式
运动方程
z
t
=
A
z
t
−
1
+
B
+
u
z_t=Az_{t-1}+B+u
zt=Azt−1+B+u
GPS观测方程
x
t
=
z
t
+
ω
x_t=z_t+\omega
xt=zt+ω
z
t
=
(
z
t
1
z
t
2
)
;
x
t
=
(
x
t
1
x
t
2
)
;
u
=
(
u
1
u
2
)
;
ω
=
(
ω
1
ω
2
)
z_t=(z1tz2t)
对于系数
A
=
(
1
0
0
1
)
;
B
=
(
v
∗
c
o
s
(
a
n
g
l
e
∗
t
)
v
∗
s
i
n
(
a
n
g
l
e
∗
t
)
)
A=(1001)
为了简单起见,我们将随机误差项
u
,
ω
u,\omega
u,ω假设服从期望为
0
0
0,协方差矩阵分别为
Q
,
R
Q,R
Q,R。
当 t = 1 t=1 t=1时
①在均匀分布中随机初始化粒子群,并且令当前时刻的权重w= 1 N \frac{1}{N} N1(N为采样次数)。
当 t ≥ 2 t\ge2 t≥2
②从 P ( z t ∣ z t − 1 ) P(z_t|z_{t-1}) P(zt∣zt−1)中抽样出粒子群记作 p i , i ∈ 1 , 2 , ⋯ , N p_{i},i\in1,2,\cdots,N pi,i∈1,2,⋯,N
③根据公式 w t = P ( x t ∣ z t ) w_t=P(x_t|z_t) wt=P(xt∣zt)当前时刻的权值。并归一化。
④重采样得到新的粒子群,求出粒子群的均值,为当前时刻的预测值。
⑤迭代②~④步骤,得到所有的均值。
①归一化权重,令所有的权重的和为1.
②计算权重的累计函数值,记作 c c c
③将(0,1)区间分为N份(N为重采样的次数)。得到n个区间,将所有临界点记作数组 d d d
④从(0, 1 N \frac{1}{N} N1)均匀分布中随机抽样出一个值。记作 a a a
⑤计算 s = a + d [ i ] s=a+d[i] s=a+d[i]( i i i为数组d的一个区间的索引),我们迭代数组d的所有区间,得到数组s。并初始化j=0
⑥for i in N:
如果s[ i ] > c [ j ]:j++
否则将索引 j 保存起来
⑦迭代完N次之后,根据所有的索引 j 取出对应位置的粒子的值。就是我们重采样之后的样本。
先看一下效果,左边为轨迹图,右边为误差图,代码中,运动方程的方差我设置的比较小,而对于GPS定位我设定的方差较大,所以对于粒子滤波的轨迹图,它更加的靠近运动方程,误差是相对于运动方程而言的,所以粒子滤波的误差比写GPS定位的要小。
import matplotlib.pyplot as plt import numpy as np from scipy import stats plt.rcParams['font.sans-serif'] = ['SimHei'] plt.rcParams['axes.unicode_minus'] = False fig,axes=plt.subplots(1,2) #绘图,一行两列的子图 np.random.seed(3) #随机数种子 class Particle_Filter(): def __init__(self): pass def train(self): #初始化权重和粒子群 P=np.random.uniform(0,40,size=(2,N)) #从[0,40]均匀分布中抽样 w=np.ones(shape=N)/N #设置权重都为 1/N centers=np.zeros(shape=(2,T)) #粒子群的中心点,用于储存每一个时刻的中心点 for t in np.arange(1,T): #从第一个时刻开始 #B B = np.array([[np.cos(angle_speed * t) * 2], [np.sin(angle_speed * t) * 2]]) #采样粒子并更新权重 for i in np.arange(w.shape[0]): #从P(z_t|z_t-1)中采样 P[:,i] =stats.multivariate_normal.rvs(mean=A@P[:,i]+B.reshape(-1), cov=Q).reshape(-1) #利用P(x_t|z_t)计算权重,其中里面的z_t就是粒子,x_t就是GPS定位所得的值 w[i]=stats.multivariate_normal.pdf(x=X[:,t],mean=P[:,i],cov=R) #归一化 w=w/np.sum(w) #重采样(系统重采样) cum=np.cumsum(w) #累计函数 s=(np.random.uniform(0,1/N)+np.arange(0,1,1/N)) #区间s P_index=np.zeros(shape=N,dtype=int) #初始化一个数组,用于储存对应索引 index=0 #从第一项开始 for i in np.arange(N): while s[i]>cum[index]: index+=1 P_index[i]=index #储存索引 P=P[:,P_index] #取出索引对应的粒子 center=P.mean(axis=1) #求出均值 centers[:,t]=center #储存结果 plot_figure(Z, X,centers) def plot_figure(x,y,centers): #绘图函数 axes[0].plot(x[0,:],x[1,:],label="运动方程",linewidth=2,marker="o") #绘制运动方程轨迹图 axes[0].plot(y[0,:],y[1,:],label="GPS",linewidth=2,marker="o") #绘制GPS轨迹图 axes[0].plot(centers[0, :], centers[1, :], label="粒子滤波", linewidth=2, marker="o")#粒子滤波轨迹图 axes[0].set_title("轨迹") axes[0].set_xlabel("位置x") axes[0].set_ylabel("位置y") axes[0].legend() err_X = np.linalg.norm(X - Z, axis=0) #观测误差 err_particle = np.linalg.norm(centers - Z, axis=0) #粒子滤波误差 axes[1].plot(np.arange(T), err_X, label="观测误差", linewidth=2, marker="o") axes[1].plot(np.arange(T), err_particle, label="滤波误差", linewidth=2, marker="o") axes[1].set_title("误差") axes[1].set_xlabel("时刻t") axes[1].set_ylabel("误差") axes[1].legend() plt.show() if __name__ == '__main__': pi=np.pi V=2 # 速度 2m/s T=50 # 记录10个时刻 angle_speed=pi/T #角速度 X=np.zeros(shape=(2,T)) # 观测变量(GPS定位) 2行10列 用于储存每个时刻数据 Z=np.zeros(shape=(2,T)) # 隐变量(运动方程) 2行10列 用于储存每个时刻数据 Q=np.array([[0.1,0], [0,0.1]]) #运动方程的过程噪声,假设服从均值为0,协方差矩阵为Q的正态分布 R=np.array([[10,0], [0,0.10]]) #GPS的过程噪声,假设服从均值为0,协方差矩阵为R的正态分布 mean = np.array([0, 0]) #随机误差(过程噪声)的均值 A=np.array([[1,0], [0,1]]) #运动方程的系数 N=1000 #每次抽样的粒子数 for t in np.arange(1,T): B=np.array([[np.cos(angle_speed*t)*2], [np.sin(angle_speed*t)*2]]) #截距项B #计算每一个时刻的运动方程,并且加上误差项 Z[:,t]=A@Z[:,t-1]+B.reshape(-1)+stats.multivariate_normal.rvs(mean=mean,cov=Q) #计算每一个时刻的GPS位置观测数据 X[:,t]=Z[:,t]+stats.multivariate_normal.rvs(mean=mean,cov=R) particle_filter=Particle_Filter() #初始化 particle_filter.train() #训练
归根究底,这个问题仍然是一个线性问题,实际上跟卡尔曼滤波没啥区别,只是用的粒子滤波去求解罢了。如有问题,还望指出。阿里嘎多。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。