2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




На страницу Пред.  1, 2
 
 Re: Как провести гладкую кривую?
Сообщение02.02.2014, 05:00 
B@R5uk в сообщении #821798 писал(а):
Обычными сплайнами воспользоваться прям так сходу не получится, потому что в классическом виде эти интерполянты проходят через определённые точки, а не дают под собой заданную площадь (если я не ошибаюсь). Так что придётся их модернизировать под вашу задачу.
Модернизация имхо проста до безобразия. Это вообще очень благодатная почва для простых методов. Например, рассмотрим гистограмму из $5$ столбцов. На ширине каждого столбца будем искать сплайн в виде полинома какой-то степени. Считаем наши условия: $4$ равенства значений кусков сплайна в соседних столбцах (сшивка по непрерывности, $4$ стыка интервалов) плюс $4$ равенства первых производных там же (сшивка по первой производной - гладкость порядка 1) плюс $5$ условий на равенство площадей под кусками сплайна на каждом интервале площади прямоугольников гистограммы. Итого имеем $13$ условий. А теперь - заказывайте: или параболы в трех средних интервалах и линейные зависимости в крайних (те же $9+4=13$ неизвестных, либо параболы везде и плюс пара дополнительных условий, например, нулевые первые производные кусков на границах внешних интервалов. В результате получаем линейную (да, т.к. площадь под многочленом по формуле Ньютона-Лейбница линейна по его коэффициентам) систему уравнений $13$ или $15$ порядка - и все. Это глобальный метод, родившийся за секунды. Можно ли придумать локальные? Можно :-) Если значения функций и производных на стыке интервалов брать какими-то определенными, посчитанными по данным исходной гистограммы. Это тоже несложно, даже проще системы будут.

 
 
 
 Re: Как провести гладкую кривую?
Сообщение02.02.2014, 15:49 
Да Боже ты мой, размахивания руками и предложения каких-либо глобальных способов, предполагающих решения более десятка уравнения - не нужно.
Нужен хоть какой-то простой алгоритм, который, например, для каждого столбца будет высчитывать несколько коэффициентов и строить интерполянту.

 
 
 
 Re: Как провести гладкую кривую?
Сообщение02.02.2014, 15:55 
hello19, я отвечал не вам, а другому участнику. А вы, раз создали тему в данном разделе - предлагайте свои попытки решения, начинайте разбираться в вопросе, вместо эмоциональных всплесков :-)

 
 
 
 Re: Как провести гладкую кривую?
Сообщение02.02.2014, 19:50 
Аватара пользователя
Утундрий в сообщении #821801 писал(а):

(Оффтоп)

Поскольку ТС сам не понимает чего он хочет, предрекаю теме более 30 страниц.

Изображение

(Оффтоп)

Вот приду домой, сяду и выведу формулы. И обсуждение сразу закончится. Изображение

 
 
 
 Re: Как провести гладкую кривую?
Сообщение03.02.2014, 02:08 
B@R5uk в сообщении #822067 писал(а):
Вот приду домой, сяду и выведу формулы. И обсуждение сразу закончится.
В теге оффтопа навскидку написанный код, неоптимально и может не совсем красиво, но рабочий. Интерполяция распределения Гаусса с мультипликативным шумом. Вполне красиво, имхо. Только хвосты гистограммы должны быть малой амплитуды, иначе кривая пляшет в них. Желающие могут сами поиграться параметрами и посмотреть на картинки.
ЗЫ почему-то при выборе языка Матлаб у меня постоянно любой код отображается некорректно, поместил под code.

(Оффтоп)

Код:
N = 15;
tl = -N/2; tr = N/2;
t = tl:(tr-tl)/N:tr;

ul = 0;%.0005;
ur = 0;%.0005;

Mean = 0;
Sigma = 3;
hiss = 0.2;
s = [];
for ii = 1:N
    ts = (t(ii+1) + t(ii))/2;
    s = [s, exp(-(Mean - ts)^2/Sigma^2)*(1 + (rand() - 0.5)*hiss)];
end

a = zeros(3*N);
b = zeros(3*N, 1);
for ii = 1:N-1
    v = [1, t(ii+1), t(ii+1)^2];
    v = [v, -v];
    d = 3*(ii-1);
    a(ii, 1+d:6+d) = v;
end
for ii = 1:N-1
    v = [0, 1, 2*t(ii+1)];
    v = [v, -v];
    d = 3*(ii-1);
    a(ii+N-1, 1+d:6+d) = v;
end
for ii = 1:N
    v = [t(ii+1) - t(ii), (t(ii+1)^2 - t(ii)^2)/2, (t(ii+1)^3 - t(ii)^3)/3];
    d = 3*(ii-1);
    a(ii+2*(N-1), 1+d:3+d) = v;
    b(ii+2*(N-1)) = s(ii);
end
a(3*N-1, 1:3) = [1, t(1), t(1)^2];
b(3*N-1) = ul;
a(3*N, 3*N-2:3*N) = [1, t(N+1), t(N+1)^2];
b(3*N) = ur;
%a
k = inv(a)*b;
%c = a*k

figure(1)
clf reset
axis on
grid on
bar(t(1:N) + diff(t)/2, s, 1, 'w');
for ii = 1:N
    tt = t(ii):(t(ii+1) - t(ii))/100:t(ii+1);
    d = 3*(ii-1);
    y = k(1+d) + k(2+d).*tt + k(3+d).*tt.^2;
    hold on
    plot(tt, y, 'r', 'LineWidth', 2)
    hold off
end

Изображение Изображение

 
 
 
 Re: Как провести гладкую кривую?
Сообщение03.02.2014, 09:27 
Аватара пользователя
hello19 в сообщении #821974 писал(а):
строить интерполянту.
У вас в задаче нет узлов интерполяции и, соответственно, не может и не должна строиться интерполянта. Речь идёт о сглаживающей аппроксимации.

Если вам оказалось не совсем понятно о чём говорит _Ivana, скачайте книжку Де Бор К. Практическое руководство по сплайнам: Пер. с англ. - М.: Радио и связь, 1985 и загляните на стр.79, пример VIII.1. Сглаживание гистограммы параболическими сплайнами. Попробуйте также поисковый запрос "метод одинаковой площади".

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

 
 
 
 Re: Как провести гладкую кривую?
Сообщение03.02.2014, 21:54 
Когда хотят гладкую непараметрическую оценку, то индикативную функцию заменяют каким-либо ядром, т.е. весовой функцией. Погуглите, например, оценку Розенблатта-Парзена.

 
 
 [ Сообщений: 22 ]  На страницу Пред.  1, 2


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group