g-h滤波--卡尔曼滤波(一)

本文是对Kalman-and-Bayesian-Filters-in-Python书里内容的概括总结,原文请参考:
Kalman-and-Bayesian-Filters-in-Python

一. 数据的取值

我们现在有两台体重秤A和B,但体重秤每次的测量都是不准确的,假设两次测量的体重分别为160和170斤,我该怎么选取体重值呢?

  • 相信第一次的值160
  • 相信第二次的值170
  • 选一个值比两个值都大
  • 选一个值比两个都小
  • 选一个值在两者之间

前两个选择是可以的,但我们没有理由偏向于一个。为什么我们选择相信A而不是B?我们没有理由相信这一点。第三和第四选择是不合理的,体重秤当然不是很准确,但是根本没有理由选择超出两者均测量范围的数字。最后的选择是唯一合理的选择。如果两个刻度都不正确,并且结果可能超过我的实际体重,也可能低于我的实际体重,那么答案通常是在A和B之间。

假设我们的两台体重秤有它各自的误差范围,A的误差范围是3,B的误差范围是9,如下图所示:


图1

我们的直觉告诉我们,选择两者重叠的部分是更合理的。两台传感器,即使其中的一台精确度不如另一台,两台也能提供更可靠的数据。我们不应该丢弃任何数据!!!

如果我只有一个体重秤,但可以多次称重自己该怎么办? 我们得出的结论是,如果我们有两个精度相等的量表,则应平均其测量结果。 如果我用一个秤称量自己10,000次会怎样? 我们会得到一个既不会太大也不会太小的数据。 不难证明大量权重的平均值将非常接近实际权重。就像下图这样:


图2

我们取得的值看起来不错,使用均值是合理的。

二. g-h模型

假设我们每隔一天使用这台体重秤测试一次自己的体重,如果得到的数据是158.0, 164.2, 160.3, 159.9, 162.1, 164.6, 169.6, 167.4, 166.4, 171.0 。这些数据参差不齐,是测量的误差吗?但这些数字看起来又好像在增加,我们先采用平均值的方式,如下图


图3

使用平均值不合理,实际上我们不能画一条水平线在所有测量的误差内。
现在我们假设体重一直在增加,通过工具,采用最小二乘法画一条线,如图:


图4

这条线看起来好多了,覆盖了所有测量,更合理。但事实一定是这样吗?我就不能一周增加13斤(最小值158,最大值171)?这可能吗?

假设我们就认为我每天增加1斤的体重(滤波器模型),第一次测量158,那么第二天我的体重就是159,让我们看看体重秤的第二次读数164.2。我们遇到了一个问题,我们的预测和我们的测量不一致。 但是,这就是我们所期望的, 如果预测始终与测量完全相同,则它将无法向过滤器添加任何信息。 同样,由于我们的预测是完美的,因此没有理由进行测量。我们需要将预测和测量以某种方式混合。

混合两个值-听起来很像前面的两个体重秤的问题。我们不要丢弃任何信息,预测值和测量值都不能丢弃。使用与以前相同的推理,我们可以看到,唯一有意义的是在预测和测量之间选择一个数字。估计值要介于测量和预测之间吗?也许可以,总的来说,我们的预测值比测量值或多或少是准确的(因为整体趋势上是上升的)。我们假设估计值是这样取得的:

estimate = prediction + 4/10 x (measurement - prediction)

我们使预测模型的初始值为160,编码如下:

from kf_book.book_plots import figsize
import matplotlib.pyplot as plt

weights = [158.0, 164.2, 160.3, 159.9, 162.1, 164.6, 
           169.6, 167.4, 166.4, 171.0, 171.2, 172.6]

time_step = 1.0  # day
scale_factor = 4.0/10

def predict_using_gain_guess(estimated_weight, gain_rate, do_print=False):     
    # storage for the filtered results
    estimates, predictions = [estimated_weight], []

    # most filter literature uses 'z' for measurements
    for z in weights: 
        # predict new position
        predicted_weight = estimated_weight + gain_rate * time_step

        # update filter 
        estimated_weight = predicted_weight + scale_factor * (z - predicted_weight)

        # save and log
        estimates.append(estimated_weight)
        predictions.append(predicted_weight)
        if do_print:
            gh.print_results(estimates, predicted_weight, estimated_weight)

    return estimates, predictions

initial_estimate = 160.
estimates, predictions = predict_using_gain_guess(
    estimated_weight=initial_estimate, gain_rate=1, do_print=True)

执行输出得到

previous estimate: 160.00, prediction: 161.00, estimate 159.80
previous estimate: 159.80, prediction: 160.80, estimate 162.16
previous estimate: 162.16, prediction: 163.16, estimate 162.02
previous estimate: 162.02, prediction: 163.02, estimate 161.77
previous estimate: 161.77, prediction: 162.77, estimate 162.50
previous estimate: 162.50, prediction: 163.50, estimate 163.94
previous estimate: 163.94, prediction: 164.94, estimate 166.80
previous estimate: 166.80, prediction: 167.80, estimate 167.64
previous estimate: 167.64, prediction: 168.64, estimate 167.75
previous estimate: 167.75, prediction: 168.75, estimate 169.65
previous estimate: 169.65, prediction: 170.65, estimate 170.87
previous estimate: 170.87, prediction: 171.87, estimate 172.16

每次用估计的值进行预测,然后将预测的值与测量值按比例混合,得到新的估计值,不断的迭代。请仔细查看代码,确保清楚每一个值的计算过程。

我们将数据打印到图表中,如下:


图5

我们蓝色曲线模拟的效果非常好,它比单一的测量和预测值都更符合实际。也许我们的预测模型刚好符合实际,那如果我们的预测模型是每天减少1斤呢?

e, p = predict_using_gain_guess(initial_estimate, -1.)
#打印
gh.plot_gh_results(weights, estimates, predictions, [160, 172]) 

如下图所示:

图6

滤波器没有上次好,但是!滤波器在调整自己,只不过调整的速度有点慢。如果体重的增加或者减少也是从预测和测量中计算出来呢?我么现在第二天的预测值是
(160+1)+4 /10*(158-161) = 159.8
我们的测量值是164.2,增加了4.4(164.2-159.8=4.4)而不是1,我么是否可以利用这个信息呢? 我们不要丢弃任何信息,我们得预测的增量是1,而测量增量是4.4,我们是否可以混合这两个值?这和前面的问题是一样的。我们假设增加值是这样的:

new gain = old gain + 1/3 (measurement - predicted) / day

重新编码如下:

weight = 160.  # initial guess
gain_rate = -1.0  # initial guess

time_step = 1.
weight_scale = 4./10
gain_scale = 1./3
estimates = [weight]
predictions = []

for z in weights:
    # prediction step
    weight = weight + gain_rate*time_step
    gain_rate = gain_rate
    predictions.append(weight)
    
    # update step    
    residual = z - weight
    
    gain_rate = gain_rate + gain_scale   * (residual/time_step)
    weight    = weight    + weight_scale * residual
  
    estimates.append(weight)
gh.plot_gh_results(weights, estimates, predictions, [160, 172])

打印数据如下:

图7

Great! 这就是g-h滤波器 (这里4/10就是g, 3/10就是h)

该滤波器是包括Kalman滤波器在内的众多滤波器的基础。换句话说,卡尔曼滤波器是g-h滤波器的一种形式。总结一下该算法(这里采用原文):

Initialization

  1. Initialize the state of the filter
  2. Initialize our belief in the state

Predict

  1. Use system behavior to predict state at the next time step
  2. Adjust belief to account for the uncertainty in prediction

Update

  1. Get a measurement and associated belief about its accuracy
  2. Compute residual between estimated state and measurement
  3. New estimate is somewhere on the residual line
图8

三. g,h的选择

g的取值代表我们对预测和测量的信任程度。


图9

g越大滤波器更靠近测量值,越小越靠近预测值。

h反应的是滤波器的变化速度,这里不详细讲述,请参考原文。


图10

实际应用中对g和h的选择具体分析,这里不做讨论,相关请查看原文,重在理解g-h滤波模型的思想。

本节讲述了g-h滤波,是大部分滤波的核心思想,通过不断的在模型基础上预测和测量而得到估计值,笔者认为,滤波器的本质是得到可能的值,某一时刻的真实值是不知道的,但我们对滤波器的估计值有很高的信任度,就像文章开头我们使用两次测量的中间值一样。

实际的应用中单点的真实值意义不大,估计值很多情况能满足我们的需求。最后,不要丢弃任何数据。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343