Matlab — Плохо обусловленный полином

У меня есть вопрос, в котором мне предлагается выполнить линейную, квадратичную и кубическую подгонку данных о населении, а затем оценить население в 1915 году. Линейная и квадратичная подгонка работают, однако кубическая, кажется, вызывает ошибку, говорящую мне, что полином плохо обусловлен. График довольно близок к значениям данных и, кажется, хорошо подходит. Что я могу сделать, чтобы исправить это? Код:

clear;
clc;
close all;

year = [1815,1845,1875,1905,1935,1965];
population = [8.3,19.7,44.4,83.2,127.1,190.9];

rlinear = polyfit(year,population,1);
rquadratic = polyfit(year,population,2);
rcubic = polyfit(year,population,3);

newTime = linspace(1815,1965,100);
vrlinear = polyval(rlinear,newTime);
vrquadratic = polyval(rquadratic,newTime);
vrcubic = polyval(rcubic,newTime);

subplot(2,2,1)
plot(year,population,'ob',newTime,vrlinear)
xlabel('Year')
ylabel('Population (millions)')
title('Year vs. US population')

subplot(2,2,2)
plot(year,population,'ob',newTime,vrquadratic)
xlabel('Year')
ylabel('Population (millions)')
title('Year vs. US population')

subplot(2,2,3)
plot(year,population,'ob',newTime,vrcubic)
xlabel('Year')
ylabel('Population (millions)')
title('Year vs. US population')

estimate = polyval(rquadratic,1915);
fprintf('The estimated population in the year 1915 is %d million. \r',estimate)

person Vladamir    schedule 01.05.2016    source источник


Ответы (2)


После предупреждающего сообщения:

Предупреждение: многочлен плохо обусловлен. Добавьте точки с различными значениями X, уменьшите степень полинома или попробуйте выполнить центрирование и масштабирование, как описано в HELP POLYFIT.

центрирование и масштабирование решает проблему:

[rcubic2,~,mu] = polyfit(year,population,3);
vrcubic2 = polyval(rcubic2,newTime,[],mu);

subplot(2,2,3)
plot(year,population,'ob',newTime,vrcubic1)
hold on
plot(newTime,vrcubic2,'--r')
xlabel('Year')
ylabel('Population (millions)')
title('Year vs. US population')

введите здесь описание изображения

Результаты показывают, что в этом случае два кубических соответствия практически одинаковы. Дополнительные сведения об этой проблеме см. в справке polyfit. .

person rozsasarpi    schedule 01.05.2016

В более новых версиях MATLAB в предупреждении также говорится, что вам следует прочитать справку. . В частности, вам необходимо изменить масштаб данных, чтобы избежать числовых проблем. К счастью, это то, что polyfit и polyval могут сделать для вас.

Причина, по которой вам нужно это сделать, заключается в том, что подгонка полинома довольно плохо обусловлена. За кулисами он строит матрицу, содержащую ваши годы, возведенные в каждую степень полинома. Итак, у вас есть матрица с такими элементами, как 1815 вместе с 1815^3 = 6e9, которая не идеальна для кондиционирования. Масштабирование гарантирует, что вы не получите больших чисел в матрице, и, следовательно, число обусловленности улучшится.

На практике вам придется вызывать polyfit и polyval немного по-разному:

[p,s,m] = polyfit(year, population, order)
[populationAtOtherYears] = polyval(p, otherYears, s, m)

Таким образом, ваш скрипт будет выглядеть примерно так:

clear;
clc;
close all;

year       = [1815,1845,1875,1905,1935,1965];
population = [8.3,19.7,44.4,83.2,127.1,190.9];

[linear.poly, linear.sigma, linear.mu] = polyfit(year,population,1);
[quadratic.poly, quadratic.sigma, quadratic.mu] = polyfit(year,population,2);
[cubic.poly, cubic.sigma, cubic.mu] = polyfit(year,population,3);

newTime = linspace(1815,1965,100);
% next line is to make a function for easier calling
evaluatePolynomial = @(fit, t) polyval(fit.poly, t, fit.sigma, fit.mu);
linear.evaluated    = evaluatePolynomial(linear, newTime);
quadratic.evaluated = evaluatePolynomial(quadratic, newTime);
cubic.evaluated     = evaluatePolynomial(cubic, newTime);

subplot(2,2,1)
plot(year,population,'ob',newTime,linear.evaluated)
xlabel('Year')
ylabel('Population (millions)')
title('Year vs. US population')

subplot(2,2,2)
plot(year,population,'ob',newTime,quadratic.evaluated)
xlabel('Year')
ylabel('Population (millions)')
title('Year vs. US population')

subplot(2,2,3)
plot(year,population,'ob',newTime,cubic.evaluated)
xlabel('Year')
ylabel('Population (millions)')
title('Year vs. US population')

estimate = evaluatePolynomial(quadratic,1915);
fprintf('The estimated population in the year 1915 is %d million. \r',estimate)
person Egon    schedule 01.05.2016