Подбор кривой сплайну к тестовым данным титана

Этот пример показывает, как использовать команды от Curve Fitting Toolbox™, чтобы соответствовать сплайну к тестовым данным титана с ручным и автоматическим выбором узлов.

Ручной выбор узла для интерполяции сплайна

Вот некоторые данные, которые записывают определенное свойство титана, измеренного как функция температуры. Мы будем использовать его, чтобы проиллюстрировать некоторые проблемы с интерполяцией сплайна.

[xx,yy] = titanium;

График данных показывает довольно резкий пик.

plot(xx,yy,'bx');
frame = [-10 10 -.1 .3]+[min(xx),max(xx),min(yy),max(yy)];
axis(frame);

Мы выбираем несколько точек данных от этих несколько грубых данных, поскольку мы хотим интерполировать. Вот изображение данных с выбранными отмеченными точками данных.

pick = [1 5 11 21 27 29 31 33 35 40 45 49];
tau = xx(pick);
y = yy(pick);
hold on
plot(tau,y,'ro');
hold off

Поскольку сплайн порядка k с узлами n+k имеет n степени свободы, и у нас есть 12 точек данных, подгонка с четвертым сплайном порядка требует 12+4 = 16 узлов. Кроме того, эта последовательность узла t должна быть такова, что i-th сайт данных находится в поддержку i-th B-сплайна. Мы достигаем этого при помощи сайтов данных как узлы, но добавляем два простых узла с обоих концов.

dl = tau(2) - tau(1);
dr = tau(end) - tau(end-1);
t = [tau(1)-dl*[2 1] tau tau(end)+dr*[1 2]];  % construct the knot sequence
plot(tau,y,'ro');
hold on
axis(frame+[-2*dl 2*dr 0 0])
plot(t,repmat(frame(3)+.03,size(t)),'kx')
hold off
legend({'Data Values' 'Knots'},'location','NW')

Мы используем эту последовательность узла, чтобы создать интерполирующий кубический сплайн.

sp = spapi(t,tau,y);

Теперь, для графика. Поскольку мы не заботимся о части сплайна вне интервала данных, мы ограничиваем график тем интервалом.

plot(tau,y,'ro')
axis(frame)
hold on
fnplt(sp,[tau(1) tau(end)], 'k')
hold off

Более внимательное рассмотрение в левой части подгонки сплайна показывает некоторые волнистости.

xxx = linspace(tau(1),tau(5),41);
plot(xxx, fnval(sp, xxx), 'k', tau, y, 'ro');
axis([tau(1) tau(5) 0.6 1.2]);

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

fnplt(sp,'k');
hold on
plot(tau,y,'ro', t,repmat(.1,size(t)),'kx');
hold off
legend({'Spline Interpolant' 'Data Values' 'Knots'},'location','NW')

Вот простой способ осуществить более разумное поведение на границе. Мы добавляем еще две точки данных вне интервала определенных данных и выбираем в качестве наших данных там значения прямой линии через первые две точки данных.

tt = [tau(1)-[4 3 2 1]*dl tau tau(end)+[1 2 3 4]*dr];
xx = [tau(1)-[2 1]*dl tau tau(end)+[1 2]*dr];
yy = [y(1)-[2 1]*(y(2)-y(1)) y y(end)+[1 2]*(y(end)-y(end-1))];
sp2 = spapi(tt,xx,yy);
plot(tau,y,'ro', xx([1 2 end-1 end]),yy([1 2 end-1 end]),'bo');
axis(frame+[-2*dl 2*dr 0 0]);
hold on
fnplt(sp2,'b',tau([1 end]))
hold off
legend({'Original Data' 'Data Added for End Conditions' ...
        'Fit with Added Data'},'location','NW')

Вот сравнение двух подгонок сплайна, чтобы показать сокращение волнистости в первом и последнем интервале.

hold on
fnplt(sp,'k',tau([1 end]))
hold off
legend({'Original Data' 'Data Added for End Conditions' ...
        'Fit with Added Data' 'Original Fit'},'location','NW')

Наконец, вот более внимательное рассмотрение в первых четырех интервалах данных, которое показывает более ясно сокращение волнистости около левого конца.

plot(tau,y,'ro',xxx,fnval(sp2,xxx),'b',xxx,fnval(sp,xxx),'k');
axis([tau(1) tau(5) .6 1.2]);
legend({'Original Data' 'Fit with Added Data' ...
        'Original Fit'},'location','NW')

Автоматический выбор узла для интерполяции

Если вся эта деталь выключает вас, позвольте Curve Fitting Toolbox выбрать узлы для вас. Задайте желаемый порядок interpolant как первый входной параметр к команде интерполяции сплайна spapi, а не последовательность узла.

autosp = spapi(4, tau, y);
knots = fnbrk(autosp,'knots');
plot(tau, y, 'ro')
hold on
fnplt(autosp,'g')
plot(knots, repmat(.5,size(knots)),'gx')
hold off
legend({'Data Values' 'Fit With Knots Chosen by SPAPI' ...
        'Knots Chosen by SPAPI'}, 'location','NW')

Ниже результат намного лучшего выбора узла, полученного путем сдвига узла в 842 немного направо и узла в 985 немного налево.

knots([7 12]) = [851, 971];
adjsp = spapi(knots, tau, y);
hold on
fnplt(adjsp,'r',2)
plot(knots, repmat(.54,size(knots)),'rx')
hold off
legend({'Data Values' 'Fit With Knots Chosen by SPAPI' ...
        'Knots Chosen by SPAPI' 'Fit With Knots Adjusted' ...
        'Adjusted Knots'}, 'location','NW')

Или иначе, просто попробуйте стандартный кубический сплайн interpolant, предоставленный csapi. Это составляет немного отличающийся выбор узлов.

autocs = csapi(tau, y);
plot(tau, y, 'ro')
hold on
fnplt(autocs,'c')
hold off

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

plot(tau, y, 'ro')
hold on
fnplt(sp,'k',tau([1 end]))  % black: original
fnplt(sp2,'b',tau([1 end])) % blue:  with special end conditions
fnplt(autosp,'g')           % green: automatic knot choice by SPAPI
fnplt(autocs,'c')           % cyan:  automatic knot choice by CSAPI
fnplt(adjsp,'r',2)          % red:   knot choice by SPAPI slightly changed
hold off
legend({'Data Values' 'Original Fit' 'Special End Conditions' ...
        'With Knots Chosen by SPAPI' 'With Knots Chosen by CSAPI' ...
        'With Adjusted Knots'},'location','NW')

Для просмотра документации необходимо авторизоваться на сайте