首页 > 解决方案 > 简化巨大的条件语句

问题描述

抽象的

生活中有些时候你的信号很嘈杂,你想摆脱这个

在此处输入图像描述

对此

在此处输入图像描述

有许多现有的方法可以让您平滑数据:局部线性和多项式回归,不同类型的移动平均线:

https://en.wikipedia.org/wiki/Kernel_smoother

https://homepages.inf.ed.ac.uk/rbf/HIPR2/gsmooth.htm

https://www.stat.wisc.edu/~mchung/softwares/hk/hk.html

https://matthew-brett.github.io/teaching/smoothing_intro.html

如何在numpy中有效地计算高斯核矩阵?

如何平滑 3D 体素世界的块?

但是我发现对于我的情况,最适合的方法是高斯内核平滑。它在台式机上对我来说就像是一种魅力,但是当切换到移动设备时,由于计算要求高,算法会停止设备。

原因之一是在平滑之前,我必须使采样率与其他信号相等,这大大增加了采样率,从而增加了处理所需的数据量。

这也产生了这样一个事实,即高斯核的大小必须是数以万计的分量,这直接影响了我的幼稚方法的算法的复杂性,它需要滤波器中的数万个元素与数十个元素相乘并求和来自信号的数千个分量只接收一个平滑数据的分量。

有一种方法可以有效地进行高斯核平滑,这需要使用傅里叶变换,这很难有效地实现。

因此,与其走这条路,我认为您实际上可以更有效地进行平滑处理,而无需深入研究傅立叶变换的复杂性。

基本上任何信号都只是[time, value]按时间排序的对的集合。当使用线性插值进行插值时,它总是可以用多边形链表示,您实际上可以分析地平滑多边形链的一个组件(即线段)。我不会深入探讨如何实际计算解析定义的内核在解析定义的线段上的卷积积分。这里值得一提的是,结果是一个巨大的分段函数:

在此处输入图像描述

这产生了许多if陈述:

public static Double Solution(Double x, Double w, Double x1, Double y1, Double x2, Double y2)
{
    Double result;

    if (x + w < x2 && w + x1 <= x)
    {
        result = (x * y1 - x2 * y1 - x * y2 + x1 * y2) / (x1 - x2);
    }
    else if (x1 < x + w && x < x1 && x + w < x2)
    {
        result = Math.Pow(w + x - x1, 2) * ((w + x + 2 * x1 - (3 * x2)) * y1 - (w + x - x1) * y2) * Math.Pow(w, -2) / (x1 - x2) / 6;
    }
    else if (x == x1 && x + w < x2)
    {
        result = y1 / 2 + w * (y1 - y2) / (x1 - x2) / 6;
    }
    else if (x + w < x2 && x1 < x && x < w + x1)
    {
        result = Math.Pow(w, -2) / (x1 - x2) * (Math.Pow(w, 3) * (y1 - y2) + 3 * w * w * (-x2 * y1 + x * (y1 - y2) + x1 * y2) - Math.Pow(x - x1, 2) * ((x + 2 * x1 - (3 * x2)) * y1 + (-x + x1) * y2) + 3 * w * (x - x1) * ((x + x1 - (2 * x2)) * y1 + (-x + x1) * y2)) / 6;
    }
    else if (x2 <= x + w && x < x1)
    {
        result = (x1 - x2) * (2 * y1 * x1 + x2 * y1 + x1 * y2 + 2 * x2 * y2 - 3 * w * (y1 + y2) - 3 * x * (y1 + y2)) * Math.Pow(w, -2) / 6;
    }
    else if (x2 <= x && w + x1 <= x && x < w + x2)
    {
        result = -Math.Pow(w - x + x2, 2) * ((w - x + x2) * y1 + (-w + x - 3 * x1 + (2 * x2)) * y2) * Math.Pow(w, -2) / (x1 - x2) / 6;
    }
    else if (x2 <= x && x < w + x1)
    {
        result = -(x1 - x2) * (2 * y1 * x1 + x2 * y1 + x1 * y2 + 2 * x2 * y2 + 3 * w * (y1 + y2) - 3 * x * (y1 + y2)) * Math.Pow(w, -2) / 6;
    }
    else if (x == x1 && (x + w == x2 && (x2 <= x && x + w < x1 && w + x2 <= x || x < w + x1) || x < w + x1 && x2 <= x + w && x < x2))
    {
        result = (-x1 + x2) * (3 * w * (y1 + y2) + (x1 - x2) * (y1 + 2 * y2)) * Math.Pow(w, -2) / 6;
    }
    else if (x < x2 && x2 <= x + w && w + x1 <= x)
    {
        result = Math.Pow(w, -2) / (x1 - x2) * (Math.Pow(w, 3) * (-y1 + y2) + 3 * w * w * (-x2 * y1 + x * (y1 - y2) + x1 * y2) + Math.Pow(x - x2, 2) * ((-x + x2) * y1 + (x - 3 * x1 + (2 * x2)) * y2) + 3 * w * (x - x2) * (-2 * x1 * y2 + x * (-y1 + y2) + x2 * (y1 + y2))) / 6;
    }
    else if (x < x2 && x2 <= x + w && x1 < x && x < w + x1)
    {
        result = Math.Pow(w, -2) / (x1 - x2) * (-2 * Math.Pow(x1, 3) * y1 + 3 * x1 * x1 * x2 * y1 + Math.Pow(x2, 3) * y1 - Math.Pow(x1, 3) * y2 - 3 * x1 * (x2 * x2) * y2 + 2 * Math.Pow(x2, 3) * y2 + 2 * Math.Pow(x, 3) * (-y1 + y2) - 3 * w * Math.Pow(x1 - x2, 2) * (y1 + y2) + 6 * x * x * (x2 * y1 - x1 * y2) + 3 * x * (2 * x1 * x2 * (-y1 + y2) + x1 * x1 * (y1 + y2) - (x2 * x2) * (y1 + y2))) / 6;
    }
    else
    {
        result = 0.0e0;
    }

    return result;
}

以下是它的视觉外观: 在此处输入图像描述

您还可以通过对这些线段的平滑函数求和来组合多个线段

在此处输入图像描述

从而将计算复杂性降低到您拥有的点数:

问题

如果上面的语句看起来效率低下,并且存在数值稳定性问题。当由 定义的线段x1,y1,x2,y2得到大数字时,结果会爆炸。我正在尝试处理这些问题,但它比我预期的要难。即使是对方程的仔细展开也会在计算中引入一些奇怪的错误。所以我认为咨询 StackOverflow 以获得更多关于如何优化此语句并使其在数值上更稳定的想法是一个好主意。

先感谢您,

标签: c#optimizationboolean-logicboolean-expression

解决方案


推荐阅读