Abstract: 概率滤波算法,自己写的,觉得挺好用

原理

通过分析数据点的分布情况,取出设计数据最可能的分布区间,对区间左侧和区间右侧的值加权平均后得到估计值

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import numpy as np
import matplotlib.pyplot as plt


class ProbabilityFilterClass:
def __init__(self, probable_max_val, probable_min_val, scale):
"""
:param probable_max_val: 预计最大值
:param probable_min_val: 预计最小值
:param scale: 最大值到最小值区间的分度值
"""
self.probable_max_val = probable_max_val
self.probable_min_val = probable_min_val
self.scale = scale
self.range_num = int((probable_max_val - probable_min_val) / scale) # 区间数量

self.range_list = [[probable_min_val + i * scale, probable_min_val + (i + 1) * scale] for i in
range(self.range_num)] # 数值区间表,左小右大,左闭右开
self.range_element_count = [0 for _ in range(self.range_num)] # 落入区间内的数值数,小标与数值区间表对应
self.real_val_probability_preference_list = [0.5 for _ in range(self.range_num)] # 实际值值概率偏向(偏向左边)

def calculate(self, _val):
"""根据输入数值计算估计值"""
for i in range(self.range_num):
tmp_range = self.range_list[i]
if _val in np.arange(tmp_range[0], tmp_range[1]): # 在区间范围内
self.range_element_count[i] += 1 # 区间元素个数加一
self.real_val_probability_preference_list[i] = 1 - (_val - tmp_range[0]) / self.scale # 概率偏向更新

max_count_index_list = [i for i, x in enumerate(self.range_element_count) if x == max(self.range_element_count)]
probable_real_val_list = []
for i in range(len(max_count_index_list)):
val_range = self.range_list[max_count_index_list[i]]
probability_preference = self.real_val_probability_preference_list[max_count_index_list[i]]
probable_real_val_list.append(
val_range[0] * probability_preference + val_range[1] * (1 - probability_preference))

if probable_real_val_list:
return sum(probable_real_val_list) / len(probable_real_val_list)
else:
return 0


if __name__ == "__main__":
real_value = 1
num = 100

sample_value = [real_value + np.random.standard_normal() for _ in range(num)]
probability_filter = ProbabilityFilterClass(1.5, 0.5, 0.02)

filter_value = []
for j in range(len(sample_value)):
result = probability_filter.calculate(sample_value[j])
filter_value.append(result)

plt.axhline(real_value, color="red", label="real_value")
plt.plot(np.arange(num), sample_value, color="dodgerblue", label="sample_value")
plt.plot(np.arange(num), filter_value, color="green", label="filter_value")
plt.legend(loc='upper left')
plt.show()