搜索
bottom↓
回复: 58

算法学习分享,格鲁布斯算法在stm32的代码实现

  [复制链接]

出100入976汤圆

发表于 2017-12-20 11:27:51 | 显示全部楼层 |阅读模式
本帖最后由 linccfzu 于 2017-12-20 11:29 编辑

格拉布斯法—异常值判断
▲概述:一组测量数据中,如果个别数据偏离平均值很远,那么这个(这些)数据称作“可疑值”。如果用统计方法—例如格拉布斯(Grubbs)法判断,能将“可疑值”从此组测量数据中剔除而不参与平均值的计算,那么该“可疑值”就称作“异常值(粗大误差)”。本文就是介绍如何用格拉布斯法判断“可疑值”是否为“异常值”。
▲测量数据:例如测量10次(n=10),获得以下数据:8.2、5.4、14.0、7.3、4.7、9.0、6.5、10.1、7.7、6.0。
▲排列数据:将上述测量数据按从小到大的顺序排列,得到4.7、5.4、6.0、6.5、7.3、7.7、8.2、9.0、10.1、14.0。可以肯定,可疑值不是最小值就是最大值。
▲计算平均值x-和标准差s:x-=7.89;标准差s=2.704。计算时,必须将所有10个数据全部包含在内。
▲计算偏离值:平均值与最小值之差为7.89-4.7=3.19;最大值与平均值之差为14.0-7.89=6.11。
▲确定一个可疑值:比较起来,最大值与平均值之差6.11大于平均值与最小值之差3.19,因此认为最大值14.0是可疑值。
▲计算Gi值:Gi=(xi-x- )/s;其中i是可疑值的排列序号
——10号;因此G10=( x10-x- )/s=(14.0-7.89)/2.704=2.260。由于 x10-x-是残差,而s是标准差,因而可认为G10是残差与标准差的比值。下面要把计算值Gi与格拉布斯表给出的临界值GP(n)比较,如果计算的Gi值大于表中的临界值GP(n),则能判断该测量数据是异常值,可以剔除。但是要提醒,临界值GP(n)与两个参数有关:检出水平α (与置信概率P有关)和测量次数n (与自由度f有关)。
▲定检出水平α:如果要求严格,检出水平α可以定得小一些,例如定α=0.01,那么置信概率P=1-α=0.99;如果要求不严格,α可以定得大一些,例如定α=0.10,即P=0.90;通常定α=0.05,P=0.95。
▲查格拉布斯表获得临界值:根据选定的P值(此处为0.95)和测量次数n(此处为10),查格拉布斯表,横竖相交得临界值G95(10)=2.176。
▲比较计算值Gi和临界值G95(10):Gi=2.260,G95(10)=2.176,Gi>G95(10)。
▲判断是否为异常值:因为Gi>G95(10),可以判断测量值14.0为异常值,将它从10个测量数据中剔除。
▲余下数据考虑:剩余的9个数据再按以上步骤计算,如果计算的Gi>G95(9),仍然是异常值,剔除;如果Gi<G95(9),不是异常值,则不剔除。本例余下的9个数据中没有异常值。
 
格拉布斯表——临界值GP(n)
P
n        0.95                0.99        P
n        0.95                0.99
3        1.135        1.155        17        2.475        2.785
4        1.463        1.492        18        2.504        2.821
5        1.672        1.749        19        2.532        2.854
6        1.822        1.944        20        2.557        2.884
7        1.938        2.097        21        2.580        2.912
8        2.032        2.231        22        2.603        2.939
9        2.110        2.323        23        2.624        2.963
10        2.176        2.410        24        2.644        2.987
11        2.234        2.485        25        2.663        3.009
12        2.285        2.550        30        2.745        3.103
13        2.331        2.607        35        2.811        3.178
14        2.371        2.659        40        2.866        3.240
15        2.409        2.705        45        2.914        3.292
16        2.443        2.747        50        2.956        3.336
 
对异常值及统计检验法的解释
■测量过程是对一个无限大总体的抽样:对固定条件下的一种测量,理论上可以无限次测量下去,可以得到无穷多的测量数据,这些测量数据构成一个容量为无限大的总体;或者换一个角度看,本来就存在一个包含无穷多测量数据的总体。实际的测量只不过是从该无限大总体中随机抽取一个容量为n(例如n=10)的样本。这种样本也可以有无数个,每个样本相当于总体所含测量数据的不同随机组合。样本中的正常值应当来自该总体。通常的目的是用样本的统计量来估计总体参量。总体一般假设为正态分布。
■异常值区分:样本中的正常值应当属于同一总体;而异常值有两种情况:第一种情况异常值不属于该总体,抽样抽错了,从另外一个总体抽出一个(一些)数据,其值与总体平均值相差较大;第二种情况异常值虽属于该总体,但可能是该总体固有随机变异性的极端表现,比如说超过3σ的数据,出现的概率很小。用统计判断方法就是将异常值找出来,舍去。
■犯错误1:将本来不属于该总体的、第一种情况的异常值判断出来舍去,不会犯错误;将本来属于该总体的、出现的概率小的、第二种情况的异常值判断出来舍去,就会犯错误。
■犯错误2:还有一种情况,不属于该总体但数值又和该总体平均值接近的数据被抽样抽出来,统计检验方法判断不出它是异常值,就会犯另外一种错误。
■异常值检验法:判断异常值的统计检验法有很多种,例如格拉布斯法、狄克逊法、偏度-峰度法、拉依达法、奈尔法等等。每种方法都有其适用范围和优缺点。
■格拉布斯法最佳:每种统计检验法都会犯犯错误1和错误2。但是有人做过统计,在所有方法中,格拉布斯法犯这两种错误的概率最小,所以推荐使用格拉布斯法。
■多种方法结合使用:为了减少犯错误的概率,可以将3种以上统计检验法结合使用,根据多数方法的判断结果,确定可疑值是否为异常值。
■异常值来源:测量仪器不正常,测量环境偏离正常值较大,计算机出错,看错,读错,抄错,算错,转移错误。

代码实现:
#include "math_flash.h"
#define MIN_SMOOTHING_SAMPLE_AMOUNT                5        //最小平滑样本量
typedef enum                                                                 //数据有效标志定义
{
        VALID_FLAG_VALID = 0x00,                                        //数据有效
        VALID_FLAG_VALID_LESS = 0x01,                        //有效数据不足
        VALID_FLAG_MORE_ERROR_DATA = 0x02                //粗大误差太多
}ValidFlagDef;
const float f32GrubbsTable[SMOOTHING_SAMPLE_SIZE] = {        //格鲁布斯临界值
        0.0f,   0.0f,   0.0f,   0.0f,   1.672f,
        1.822f, 1.938f, 2.032f, 2.11f,  2.176f,
        2.234f, 2.285f, 2.331f, 2.371f, 2.409f,
        2.443f, 2.475f, 2.504f, 2.532f, 2.557f
};

/*******************************************************************
功能:格鲁布斯法求平均值和标准差
*******************************************************************/
uint8_t calc_grubbs_value(float32_t * pSrc, uint32_t blockSize,  float32_t * mean,  float32_t * stdErr)
{
        volatile float32_t f32Min = 0.0f, f32Max = 0.0f, f32StdError = 0.0f, f32GMin = 0.0f, f32GMax = 0.0f, f32Mean = 0.0f;
        uint32_t u32MinIndex = 0, u32MaxIndex = 0;
        uint8_t result = VALID_FLAG_VALID;
        uint8_t u8Exit = 0;
        //剔除粗大误差
        while(!u8Exit)
        {
                arm_min_f32(pSrc, blockSize, (float32_t*)&f32Min, &u32MinIndex);        //最小值
                arm_max_f32(pSrc, blockSize, (float32_t*)&f32Max, &u32MaxIndex);        //最大值
                arm_std_f32(pSrc, blockSize, (float32_t*)&f32StdError);                                //标准差
                arm_mean_f32(pSrc, blockSize, (float32_t*)&f32Mean);                                //平均值
                if(f32StdError <= 0.001f)
                {
                        break;
                }
                f32GMin = (f32Mean - f32Min) / f32StdError;
                f32GMax = (f32Max - f32Mean) / f32StdError;
                if(f32GMin <= f32GMax && f32GMax > f32GrubbsTable[blockSize-1])
                {
                        arm_copy_f32(&(pSrc[u32MaxIndex+1]), &(pSrc[u32MaxIndex]), blockSize-u32MaxIndex-1);
                }
                else if(f32GMin > f32GMax && f32GMin > f32GrubbsTable[blockSize-1])
                {
                        arm_copy_f32(&(pSrc[u32MinIndex+1]), &(pSrc[u32MinIndex]), blockSize-u32MinIndex-1);
                }
                else
                {
                        u8Exit = 1;
                }
                blockSize--;
                if(blockSize < MIN_SMOOTHING_SAMPLE_AMOUNT)
                {
                        result = VALID_FLAG_MORE_ERROR_DATA;
                        u8Exit = 1;
                }
        }
        *mean = f32Mean;
        *stdErr = f32StdError;

        return result;
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入12汤圆

发表于 2017-12-20 11:35:47 | 显示全部楼层
收藏,学习

出0入147汤圆

发表于 2017-12-20 11:55:55 来自手机 | 显示全部楼层
不错,长见识了

出0入0汤圆

发表于 2017-12-20 12:05:23 | 显示全部楼层
学习了,收藏已经

出0入0汤圆

发表于 2017-12-20 13:42:50 | 显示全部楼层
学习                              

出0入0汤圆

发表于 2017-12-20 13:48:52 | 显示全部楼层
学习                                

出0入0汤圆

发表于 2017-12-20 14:00:58 来自手机 | 显示全部楼层
收藏。。。

出0入0汤圆

发表于 2017-12-20 14:34:18 | 显示全部楼层
请问检测超过1000个数据样本,格拉布斯表——临界值GP(n)如何写

出0入0汤圆

发表于 2017-12-20 14:51:58 | 显示全部楼层
非常不错的分享,谢谢楼主,收藏了。

出0入0汤圆

发表于 2017-12-20 14:57:08 | 显示全部楼层
可以做各种传感器异常数值处理了

出0入0汤圆

发表于 2017-12-20 14:59:10 | 显示全部楼层
涨见识了,收藏先

出0入0汤圆

发表于 2017-12-20 15:17:25 | 显示全部楼层
学习了,谢谢分享。

出0入0汤圆

发表于 2017-12-20 15:31:36 | 显示全部楼层
野蛮方法,数据排序后,取中间的1/3做平均

出0入0汤圆

发表于 2017-12-20 15:36:48 | 显示全部楼层
收藏学习。。。

出0入0汤圆

发表于 2017-12-20 16:24:04 | 显示全部楼层
不知道实际用起来实时性怎样?

出0入0汤圆

发表于 2017-12-20 23:32:33 | 显示全部楼层

收藏学习。。。

出0入0汤圆

发表于 2017-12-21 08:27:53 | 显示全部楼层
学习了,好厉害的样子也

出0入0汤圆

发表于 2017-12-21 09:35:15 | 显示全部楼层
本帖最后由 surken 于 2017-12-21 09:37 编辑

请教一下,标准差s=2.704 这个是怎么算出来的?

百度到公式了。

出0入0汤圆

发表于 2017-12-21 09:39:21 | 显示全部楼层
应该给酷  :0

出0入0汤圆

发表于 2017-12-21 09:52:06 | 显示全部楼层
有人试过了么,效果怎么样?

出0入0汤圆

发表于 2017-12-21 10:12:25 | 显示全部楼层
谢谢, 学习了

出0入0汤圆

发表于 2017-12-21 10:30:46 | 显示全部楼层
好东西 收藏先

出0入0汤圆

发表于 2017-12-21 11:54:03 | 显示全部楼层
谢谢楼主共享

出0入0汤圆

发表于 2017-12-21 22:31:24 来自手机 | 显示全部楼层
感谢分享,谢谢楼主提供的数据处理方法

出0入0汤圆

发表于 2017-12-21 23:26:51 | 显示全部楼层
算法是好的,可是标准差比较耗资源啊。。

出0入0汤圆

发表于 2017-12-21 23:53:20 | 显示全部楼层
赞,感谢分享。。。。

出0入0汤圆

发表于 2017-12-22 13:31:08 | 显示全部楼层
mark

出0入0汤圆

发表于 2017-12-22 13:48:41 来自手机 | 显示全部楼层
异常值处理,有应用场景吗

出0入0汤圆

发表于 2017-12-23 17:25:02 | 显示全部楼层
谢谢分享,收藏备用

出0入50汤圆

发表于 2017-12-23 18:32:37 | 显示全部楼层
其实从某种意义上说,不管是否存在异常,只要是偏离目标最大的那个数据,不管你是否异常,都要当作异常值被剔除,这个很像某些电影里的情节啊

出0入0汤圆

发表于 2017-12-23 18:36:28 来自手机 | 显示全部楼层
听起来就牛逼的样子

出0入0汤圆

发表于 2017-12-23 19:47:20 | 显示全部楼层
简单的采用中值滤波是不是更好,如果信号本来是波动的,不可能取太多的数据,如果类似温度的数据这种比较靠谱

出0入0汤圆

发表于 2017-12-23 19:51:08 | 显示全部楼层
收藏了,感谢

出0入76汤圆

发表于 2017-12-23 19:54:34 | 显示全部楼层
先赞一个, 以后可能会用到

出50入0汤圆

发表于 2017-12-23 22:47:05 来自手机 | 显示全部楼层
格拉布斯算法,赞!!

出0入0汤圆

发表于 2017-12-24 19:44:30 来自手机 | 显示全部楼层
和中值滤波的,复杂度(假设最优的,有限可能性,桶排,N-排序 + N-展开 + N-求和平均)相比谁更优?

出0入0汤圆

发表于 2017-12-27 19:38:55 | 显示全部楼层
收藏,学习了,以后可能会用到!

出0入0汤圆

发表于 2017-12-28 09:34:47 | 显示全部楼层
挺不错的,收藏了。

出0入0汤圆

发表于 2017-12-28 11:31:42 | 显示全部楼层
格鲁布斯算法stm32实现

出0入0汤圆

发表于 2017-12-28 17:36:14 | 显示全部楼层
刚好可以用到  谢谢分享

出0入0汤圆

发表于 2017-12-29 12:04:18 | 显示全部楼层
谢谢分享收藏备用

出0入0汤圆

发表于 2017-12-29 12:57:49 | 显示全部楼层
算法复杂度高,中间函数没有了不全,还是谢谢楼主分享

出0入0汤圆

发表于 2018-1-2 11:15:34 | 显示全部楼层
不错,就是复杂了点,但是对工程应用还是比较有用的

出0入0汤圆

发表于 2018-1-2 11:45:21 | 显示全部楼层
收藏,学习了

出0入0汤圆

发表于 2018-1-2 11:51:02 | 显示全部楼层
对于变化缓慢的测量值有效,要看使用环境

出0入12汤圆

发表于 2018-1-2 12:27:49 | 显示全部楼层
简单测试了8个数据{1707058.0,1570487.0,1538024.0,1079866.0,1354633.0,102039.0,1619591.0,1436633.0},木有异常值,

出0入0汤圆

发表于 2018-1-4 13:22:53 | 显示全部楼层
我都只是简单的取五个值,再取中间值为标准值,看来还有更实用的算法

出0入0汤圆

发表于 2018-1-4 13:47:20 来自手机 | 显示全部楼层
RAMILE 发表于 2017-12-20 15:31
野蛮方法,数据排序后,取中间的1/3做平均

方便实用

出0入0汤圆

发表于 2018-12-29 15:20:15 | 显示全部楼层
楼主衣服用了 格鲁布斯算法

出0入0汤圆

发表于 2019-1-2 09:11:10 | 显示全部楼层
mark一下:格鲁布斯算法

出0入0汤圆

发表于 2019-1-2 13:01:42 | 显示全部楼层
格鲁布斯算法  采样滤波 比较复杂

出0入0汤圆

发表于 2019-3-9 17:33:01 | 显示全部楼层
格鲁布斯算法实现

出0入0汤圆

发表于 2019-3-9 18:46:51 | 显示全部楼层
学习了,收藏已经

出0入0汤圆

发表于 2019-3-9 19:15:49 来自手机 | 显示全部楼层
收藏学习

出0入0汤圆

发表于 2019-3-10 11:03:19 | 显示全部楼层

格鲁布斯算法stm32实现

出250入8汤圆

发表于 2019-3-10 12:32:02 | 显示全部楼层
格鲁布斯算法,采样,stm32算法

出0入0汤圆

发表于 2019-3-12 11:06:42 | 显示全部楼层
长见识了··· 牛···

出0入17汤圆

发表于 2019-8-5 14:55:05 来自手机 | 显示全部楼层
这算法实用

出0入0汤圆

发表于 2019-9-9 19:12:23 | 显示全部楼层
格鲁布斯算法实现
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-6 22:28

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表