LOADING

加载过慢请开启缓存 浏览器默认开启

概率滤波

2023/10/15 算法

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

原理

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

代码

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()