粒子过滤器,重采样步骤实现

信息处理 计算机视觉 粒子过滤器
2022-02-20 09:17:58

我在统计和概率论方面都不是很好,我也不完全了解蒙特卡罗模拟或 SIR 采样的数学背景,但我喜欢计算机视觉,我正在尝试它,希望能得到一些不错的结果已知技术(我不想重新发明轮子也不想找到一些新方法)。

我已经用 Bhattacharyya 距离作为似然得分函数完成了粒子滤波器的近似实现。我所说的近似是指重采样部分。

现在,我的粗略算法在 python 伪代码中做了类似的事情:

for each particles:
    p.position = move with a random walk motion model

    p_histogram = calculate histogram that is under the particle
    p.weight = bhattacharyya_distance( p_histogram, model_histogram )

sort(particles, less_weight_comparator)
# now particles[0] has less weight --> less distance
# and particles[nParticles-1] has more weight --> more distance

# find best k particles
# i.e., the particles that has weight less then a threshold 0.25
k = -1
for each particles:
    if p.weight < 0.25: 
         k++;
    else:
         break

# resample all the other particles near those k best ones
if k!= -1:
    for i in range(k, nParticles):
        # choose a random number between 0 and k
        new_index = rand(0,k) 
        # resample the particle near the k_th 
        # with a gaussian random with 0 mean and 0.6 variance
        particles[i].position = particles[k].position * random_gauss(0, 0.6)
else:
    print "target is lost"

predicted_position = particles[0].position

这项工作非常好,但并非每次都如此,所以我正在尝试按照一些著名的实现来改进它,比如Arulampalam_etal_2002 论文中的那个。

但是..我很困惑,我不明白重采样阶段发生了什么。

使用我粗略而肤浅的算法,我总是知道发生了什么:重量小于我的阈值的粒子离直方图模型太远,以及k == -1目标是否丢失。很清楚,在我心里。

在提到的论文(以及所有其他粒子过滤论文)中,我正在阅读关于将权重归一化,因为所有权重总和为 1,并计算退化值Neff(方程式 51)和.. 我迷路了。n_eff的值从 249.444(在粒子过滤器初始化后的第一帧,以便某些粒子必须靠近目标)到 245.452(稍后更多帧,当目标丢失时),在这里,我再次找不到阈值。如果我对权重进行归一化,在排序之后,我的粒子权重从 0.00418279 到 0.00240669 之类的值,并且我无法轻易找到一个阈值来帮助我了解哪些靠近目标,这取决于如何我有很多粒子,所以如果我添加更多粒子,我会迷失更多。

此外,在像Nummiaro_2002这样的论文中,Bhattacharyya 是在高斯(方程 10)内计算的,我不确定这意味着什么,而且我失去了一种简单的方法来理解哪个粒子在模型附近有直方图。

我完全迷失了将 Bhattacharyya 纳入高斯意味着什么,以及为什么归一化以及如何找到阈值以了解必须重新采样多少粒子以及哪些粒子在其中。

我希望有人能用简单易懂的话给我解释一下。

1个回答

您的问题是关于重采样步骤,让我们专注于这一点。

重采样用于粒子过滤以抵消“样本贫乏”,即某些粒子的权重可能非常低。这是对资源的浪费,因为您想描述您的概率分布吃得最好。您应该注意,它不应(先验地)干扰预测步骤的测量。

最佳情况是让所有粒子具有大致均匀的权重,这是大多数重采样算法设定的目标。我建议你使用这个函数,它使用类似于直方图均衡的东西来计算resample粒子的比率(一个 nd 数组是最后一行代表权重):

def resampling(particles, resample):
    """
    Resample weighted particles.

    The particles are grouped in N_pop batches to represent multiple velocities.
    The probability is given for all particles but corresponds to the proba-
    bility of one batch.

    Input
    -----
    N particles as a particles.shape array

    Output
    ------
    N particles as a particles.shape array

    Parameters
    ----------
    resample : gives the ratio of particles that get resampled at every frame (between 0 and 1)

    """
    particles_out = particles.copy()
    N = particles.shape[1]  # number of particles


    # resample a percentage of the particles (the total number keeps to N)
    if resample > 0:
        # draw resample (in %) random addresses of particles that we will reassign
        N_resample = int(N*resample)
        address_resample = np.random.permutation(np.arange(N))[0:N_resample]

        # draw from this subset some addresses uniformly over their pdf using histogram equalization
        proba_resample = particles_out[-1, address_resample]
        proba_resample /= proba_resample.sum()
        address = np.interp(np.linspace(0, 1, N_resample, endpoint=False)+1/2./N_resample,#np.random.rand(N_resample),
                            np.concatenate(([0.], np.cumsum(proba_resample))),
                            np.arange(N_resample+1))
        address = [int(k) for k in address]

        # reassign these particles and set their weight to a uniform value
        particles_out[:, address_resample] = particles_out[:, address_resample[address]]
        subset_weight = proba_resample[address].sum() # should be \approx N_resample / N, that is, resample
        particles_out[4, address_resample] = subset_weight / N_resample #1/N_resample #particles_out[4, address_resample].sum()

        # ultimately, normalize weights
        particles_out[4, :] /= particles_out[4, :].sum()

    return particles_out