【问题标题】:Factoring out noise in an algorithm在算法中排除噪声
【发布时间】:2012-02-29 05:06:56
【问题描述】:

我基本上有一堆数据对象,它们以毫秒为单位将时间戳映射到浮点值。我正在寻找基本上找到给定范围内数据的峰值/最大值。我基本上一直在使用这样的东西:

float previousValue = 0;
for (int i = 0; i < data.size(); i++) {
    MyData value = data.get(i);
    if (value.getData() < previousValue) {
        // found the peak!
        break;
    } else {
        previousValue = value.getData();
    }
}

这个算法的唯一问题是它没有考虑噪声。本质上,我可以有这样的价值观:

[0.1025, 0.3000, 0.3025, 0.3500, 0.3475, 0.3525, 0.1025]

实际峰值为 0.3525,但我上面的算法将其视为 0.3500,因为它首先出现。由于我计算的性质,我不能只对数组执行max() 并找出最大值,我需要在它下降之前找到最先出现的最大值。

如何在考虑噪声差异的同时找到峰值?

【问题讨论】:

  • 如何定义峰值? .3500 之后的值和 .3525 之后的值下降。有什么区别?
  • 分离关注点:首先,使用滑动窗口并对数据进行平均——这将消除噪音。之后,您可以使用您的方法或任何其他方法轻松找到峰值。

标签: java math noise


【解决方案1】:

有两个问题:

  1. 过滤掉噪音;
  2. 寻找高峰。

看来您已经有了 2 的解决方案,需要解决 1。

要过滤掉噪音,您需要某种low-pass filtermoving average 就是这样一种过滤器。例如,exponential moving average 很容易实现,应该可以很好地工作。

总而言之:将您的系列通过过滤器,然后应用寻峰算法。

【讨论】:

  • 所以低通滤波器将摆脱跳跃值并带回更多线性结果?我怎样才能写出过滤器?我对数学一窍不通。
【解决方案2】:

在数组(任何数值数组:int、double)中查找单个峰值(或最大值)的更简单方法是遍历数组并将变量设置为最大值...

示例:(所有示例都使用名为“data”的浮点数组)

float highest = 0; //use a number equal to or below the lowest possible value
for (int i = 0; i < data.length; i++){
    if (data[i] > highest){
        highest = data[i];
    }
}

为了在噪声数据中找到多个峰值,过滤掉一些噪声,我使用了这种方法:

boolean[] isPeak = new boolean[20]; // I am looking for 20 highest peaks
float[] filter = new float[9]; // the range to which I want to define a peak is 9
float[] peaks = new float[20]; // again the 20 peaks I want to find
float lowpeak = 100; // use a value higher than the highest possible value
// first we start the filter cycling through the data
for (int i = 0; i < data.length; i++){
    for (int a = filter.length-1; a > 0; a--){
        filter[a] = filter[a-1];
    }
    filter[0] = data[1]
    // now we check to see if the filter detects a peak
    if (filter[4]>filter[0] && filter[4]>filter[1] && filter[4]>filter[2] &&
            filter[4]>filter[3] && filter[4]>filter[5] && filter[4]>filter[6] &&
            filter[4]>filter[7] && filter[4]>filter[8]){
        // now we find the lowest peak
        for (int x = 0; x < peaks.lengt-1; x++){
            if (peaks[x] < lowpeak){
                lowpeak = peaks[x];
            }
        }
        // now we check to see if the peak is above the lowest peak 
        for (int x = 0; x < peaks.length; x++){
            if (peaks[x] > lowpeak && peaks[x] != peaks[x+1]){
                for (int y = peaks.length-1; y > 0 && !isPeak[y]; y--){
                peaks[y] = peaks[y-1];
                }
                peaks[0] = filter[4];
            }
        }
    }
}

这可能不是最有效的方法,但它可以完成工作!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-02-15
    • 2011-03-19
    • 1970-01-01
    • 1970-01-01
    • 2015-10-14
    • 1970-01-01
    • 1970-01-01
    • 2023-04-05
    相关资源
    最近更新 更多