2010-04-06 3 views
3

Я занимаюсь анализом конкретных сигналов, и мне нужен метод, который сглаживает определенную колоколообразную кривую распределения. Подход среднего уровня не дает желаемых результатов. Я хочу сохранить минимальную/максимальную и общую форму моей встроенной кривой неповрежденной, но разрешить несоответствия в выборке.Сглаживание небольших наборов данных с квадратичной кривой второго порядка

Вкратце: если задан набор данных, который моделирует простую квадратичную кривую, какой статистический метод сглаживания вы бы порекомендовали?

Если возможно, обратитесь к реализации, библиотеке или структуре.

Спасибо!

Редактировать: Некоторые полезные данные

(Возможный график сигнала)

alt text http://i40.tinypic.com/b49942.png

Темный цветной квадратичный мой «установлен» кривая светлого цвета соединенные точки данных.

Образец @ -44 (приблизительно) - проблема на моем графике (т. Е. Несогласованность потенциального образца). Мне нужна эта кривая, чтобы лучше «подгонять» распределение, и преодолевать значения, которые не соответствуют тенденции. Надеюсь это поможет!

+0

Под «несоответствиями в выборке», вы имеете в виду, что частота дискретизации была переменной или вы имеете в виду шум сигнала? –

+0

@Judge Maygarden - я добавил возможный график того, где значение резко отклоняется от кривой. – Rev316

+0

Вам нужно лучше описать свои данные. Это распределение, временные ряды или что? Вы хотите поместить квадратичную функцию или что-то более гибкое? Лучшая модель будет зависеть от того, как генерируются ваши данные. Учитывая модельный класс, существуют различные подходы к оценке. – Tristan

ответ

3

А «квадратичной» кривая одно; «колоколообразная» обычно означает нормальное распределение Гаусса. Получение наилучшей оценки Гаусса не может быть проще: вычислить выборочное среднее и дисперсия и ваша гладкая аппроксимация

y = exp(-squared(x-mean)/variance) 

Если, с другой стороны, вы хотите, чтобы приблизить гладкую кривую с quadradatic, я Рекомендуем вычислить квадратичный многочлен с минимальной квадратичной ошибкой. Я не могу вспомнить формулы для этого, но если у вас было дифференциальное исчисление, напишите формулу для полной квадратной ошибки (поточечно) и дифференцируйте по коэффициентам вашей квадратичной. Задайте первые производные до нуля и решите для наилучшего приближения. Или ты мог бы это посмотреть.

И, наконец, если вы хотите, чтобы гладкая кривая приближалась к набору точек, cubic splines - ваш лучший выбор. Кривые не обязательно означают ничего, но вы получите приятное плавное приближение.

0

Возможно, параметры для вашего среднего значения установлены неправильно (примерное окно слишком маленькое или большое)?

Это просто шум, наложенный на кривую колокола? Насколько близко частота шума к частоте сигнала, который вы пытаетесь получить? Изображение того, что вы пытаетесь извлечь, может помочь нам определить решение.

Вы можете попробовать какой-то алгоритм подгонки, используя least squares fit, если вы можете разумно догадаться о параметрах функции. Эти методы часто имеют некоторый иммунитет к шуму.

0

Как насчет простого цифрового low-pass filter?

y[0] = x[0]; 
for (i = 1; i < len; ++i) 
    y[i] = a * x[i] + (1.0 - a) * y[i - 1]; 

В этом случае х [] ваши входные данные и у [] отображает отфильтрованный выходной сигнал. Коэффициент a - это значение от 0 до 1, которое вы должны настроить. значение 1 воспроизводит входной и cut-off frequency, уменьшается по мере приближается к 0.

+0

Спасибо за код, но проблема с этим подходом к тому моменту, когда коэффициент достаточно мал, чтобы «исправить» несоответствия, форма сильно меняется, а макс/макс становится неточным. – Rev316

+0

Если это так, то вам нужно будет увеличить частоту дискретизации, чтобы этот подход работал. Это вариант? –

+0

К сожалению, это не так. В моем случае средний образец кластера будет от 3 до 10. – Rev316

2
#include <iostream> 
#include <math.h> 

struct WeightedData 
{ 
double x; 
double y; 
double weight; 
}; 

void findQuadraticFactors(WeightedData *data, double &a, double &b, double &c, unsigned int const datasize) 
{ 
double w1 = 0.0; 
double wx = 0.0, wx2 = 0.0, wx3 = 0.0, wx4 = 0.0; 
double wy = 0.0, wyx = 0.0, wyx2 = 0.0; 
double tmpx, tmpy; 
double den; 

for (unsigned int i = 0; i < datasize; ++i) 
    { 
    double x = data[i].x; 
    double y = data[i].y; 
    double w = data[i].weight; 

    w1 += w; 
    tmpx = w * x; 
    wx += tmpx; 
    tmpx *= x; 
    wx2 += tmpx; 
    tmpx *= x; 
    wx3 += tmpx; 
    tmpx *= x; 
    wx4 += tmpx; 
    tmpy = w * y; 
    wy += tmpy; 
    tmpy *= x; 
    wyx += tmpy; 
    tmpy *= x; 
    wyx2 += tmpy; 
    } 

den = wx2 * wx2 * wx2 - 2.0 * wx3 * wx2 * wx + wx4 * wx * wx + wx3 * wx3 * w1 - wx4 * wx2 * w1; 
if (den == 0.0) 
    { 
    a = 0.0; 
    b = 0.0; 
    c = 0.0; 
    } 
else  
    { 
    a = (wx * wx * wyx2 - wx2 * w1 * wyx2 - wx2 * wx * wyx + wx3 * w1 * wyx + wx2 * wx2 * wy - wx3 * wx * wy)/den; 
    b = (-wx2 * wx * wyx2 + wx3 * w1 * wyx2 + wx2 * wx2 * wyx - wx4 * w1 * wyx - wx3 * wx2 * wy + wx4 * wx * wy)/den; 
    c = (wx2 * wx2 * wyx2 - wx3 * wx * wyx2 - wx3 * wx2 * wyx + wx4 * wx * wyx + wx3 * wx3 * wy - wx4 * wx2 * wy)/den; 
    } 

} 

double findY(double const a, double const b, double const c, double const x) 
{  
return a * x * x + b * x + c; 
}; 




int main(int argc, char* argv[]) 
{ 
WeightedData data[9]; 
data[0].weight=1; data[0].x=1; data[0].y=-52.0; 
data[1].weight=1; data[1].x=2; data[1].y=-48.0; 
data[2].weight=1; data[2].x=3; data[2].y=-43.0; 
data[3].weight=1; data[3].x=4; data[3].y=-44.0; 
data[4].weight=1; data[4].x=5; data[4].y=-35.0; 
data[5].weight=1; data[5].x=6; data[5].y=-31.0; 
data[6].weight=1; data[6].x=7; data[6].y=-32.0; 
data[7].weight=1; data[7].x=8; data[7].y=-43.0; 
data[8].weight=1; data[8].x=9; data[8].y=-52.0; 

double a=0.0, b=0.0, c=0.0; 
findQuadraticFactors(data, a, b, c, 9); 
std::cout << " x \t y" << std::endl; 
for (int i=0; i<9; ++i) 
    { 
    std::cout << " " << data[i].x << ", " << findY(a,b,c,data[i].x) << std::endl; 
    } 
}