无迹卡尔曼滤波
无迹卡尔曼滤波(unscented Kalman filter,UKF)利用一组确定性的sigma点,通过非线性模型传播均值、协方差和交叉协方差,再进行高斯形式的观测更新。它通常不需要模型的雅可比;“不用导数”并不意味着不需要模型,或能精确处理任意非线性后验。
sigma点代表哪些量
给定 维近似均值 和协方差 ,令 ,要求 。取矩阵平方根 ,sigma点为 、、,其中 为第 列。均值权重为 协方差权重除中心点外相同,中心点另加 。这些点不声称是从真实状态独立抽取的随机样本,而是构造出来的数值积分规则。[1]
平方变换中均值的移动
令 ,取 ,于是 。三点为 ,均值权重 ,协方差权重 。经平方变换得到 ,近似均值为 ,不是均值直接平方所得的四。
变换后方差为 本例可独立精确复核:写 ,利用 ,得到 、,恰好相同。这个匹配是本例的结果,不是所有非线性变换的保证。
用交叉协方差校正状态
若观测 , 独立,观测方差为 。sigma点还给出状态与观测交叉协方差 。读数六时, 即便变换矩在这里精确,高斯校正仍只是后验近似,因为平方似然与高斯先验相乘后一般不是高斯分布。
一维实例代码与边界
下例固定上述sigma点参数,只复核平方观测的一次更新。时间和额外空间为常数,返回新均值、新方差、预测观测均值与创新方差;不改写输入。
Python 3
import math
def ukf_square_update(mean, variance, observation, noise_variance):
if not all(math.isfinite(v) for v in (mean, variance, observation, noise_variance)):
raise ValueError("finite data required")
if variance < 0 or noise_variance <= 0:
raise ValueError("invalid variances")
d = math.sqrt(variance)
points = (mean, mean + d, mean - d)
transformed = tuple(x * x for x in points)
wm, wc = (0.0, 0.5, 0.5), (2.0, 0.5, 0.5)
predicted = sum(w * y for w, y in zip(wm, transformed))
S = noise_variance + sum(w * (y - predicted) ** 2 for w, y in zip(wc, transformed))
cross = sum(w * (x - mean) * (y - predicted)
for w, x, y in zip(wc, points, transformed))
K = cross / S
return mean + K * (observation - predicted), variance - K * cross, predicted, S
print(ukf_square_update(2, 1, 6, 1))
输出约为 。变式。 预测均值为零、方差一时,三个点为 ,平方后观测均值为一、交叉协方差为零。UKF仍无法用一次对称平方观测确定状态的正负,真实后验可能有两峰;需要表达多峰时可考虑更丰富的分布表示。
一般UKF还要先传播状态sigma点、加入过程噪声,再重新生成或增广点集以传播观测;本文为突出原理只计算一次校正。高维实现需要处理矩阵平方根、舍入误差和可能为负的权重。UKF不是对EKF在所有模型下都更精确的排序结论。
参考资料
- ↑ Simo Särkkä,Bayesian Filtering and Smoothing (2013),§5.5 Unscented Transform,式5.74—5.77;§5.6 Unscented Kalman Filter,式5.84—5.90。