Pers.narod.ru. Алгоритмы. Метод наименьших квадратов (МНК) |
Если набор экспериментальных данных получен со значительной погрешностью, то не имеет смысла использовать интерполяцию Лагранжа полиномами и сплайнами для обработки результатов. В этом случае необходимо провести аппроксимирующую кривую, которая не проходит через экспериментальные точки, но в то же время отражает исследуемую зависимость и сглаживает "выбросы", возможные за счет погрешности эксперимента.
Обозначим узлы исходной таблицы данных через хi, где 0<= i<= n - номер узла. Считаем известными значения экспериментальных данных в узловых точках f(xi) = fi. Введем непрерывную функцию φ(х) для аппроксимации дискретной зависимости f(xi). В узлах функции φ(х) и f(x) будут отличаться на величину еi = φ(хi)-f(xi). Отклонения еi могут принимать положительные и отрицательные значения. Чтобы не учитывать знаки, возведем каждое отклонение в квадрат и просуммируем квадраты отклонений по всем узлам:
(1)
Метод построения аппроксимирующей функции φ(х) из условия минимума величины Q называется методом наименьших квадратов (МНК).
Наиболее распространен способ выбора функции φ(х) в виде линейной комбинации:
(2)
φ0(х), φ1(х),…, φm(х) - базисные функции; m <= n; c0, c1,...,cm - коэффициенты, определяемые при минимизации величины Q.
Математически условия минимума суммы квадратов отклонений Q запишем, приравнивая нулю частные производные от Q по коэффициентам сk, 0<=k<=n:
(3)
Из системы линейных алгебраических уравнений (3) определяются все коэффициенты сk. Система (3) называется системой нормальных уравнений. Матрица этой системы имеет следующий вид:
(4)
и называется матрицей Грама. Элементы матрицы Грама являются скалярными произведениями базисных функций
(5)
Расширенная матрица системы уравнений (3) получится добавлением справа к матрице Грама столбца свободных членов
(6)
где скалярные произведения, являющиеся элементами столбца, определяются аналогично (5):
(7)
Отметим основные свойства матрицы Грама, полезные при программной реализации алгоритмов МНК:
1) матрица симметрична, т.е. аi,j = аj,i, что позволяет сократить объем вычислений при заполнении матрицы;
2) матрица является положительно определенной, следовательно, при решении системы нормальных уравнений методом исключения Гаусса можно отказаться от процедуры выбора главного элемента;
3) определитель матрицы будет отличен от нуля, если в качестве базиса выбраны линейно независимые функции φk(х), при этом система (3) имеет единственное решение.
При обработке экспериментальных данных, определенных с погрешностью e в каждой узловой точке, обычно начинают с аппроксимации функцией φ(x), представимой одной-двумя базисными функциями. После определения коэффициентов ck вычисляют величину Q по формуле (1). Если получится, что корень(Q) > e , то необходимо расширить базис добавлением новых функций φk(х). Расширение базиса необходимо осуществлять до тех пор, пока не выполнится условие корень(Q)~=е.
Выбор конкретных базисных функций зависит от свойств аппроксимируемой функции f(x), таких, как периодичность, экспоненциальный или логарифмический характер, свойства симметрии, наличие асимптотики и т.д. На практике чаще всего используется решение, показанное далее.
Степенной базис
Выберем базисные функции φk(х) в виде последовательности степеней аргумента х, которые линейно независимы,
(8)
В этом случае мы будем аппроксимировать экспериментальную зависимость полиномом. Степень полинома m выбираем m<<n (при лагранжевой интерполяции m=n). Аппроксимирующая кривая в МНК не проходит через значения исходной функции в узлах, но проведена из условия наименьшего суммарного квадратичного отклонения. Экспериментальные данные "сглаживаются" с помощью функции φ(х). Если же выбрать m=n, то на основании единственности интерполяционного полинома получим функцию φ(х), совпадающую с каноническим интерполяционным полиномом степени n, аппроксимирующая кривая пройдет через все экспериментальные точки и величина Q будет равна нулю. Последнее обстоятельство используется для отладки и тестирования программ, реализующих алгоритмы МНК.
Запишем расширенную матрицу системы нормальных уравнений для базиса (8):
(9)
Нетрудно видеть, что для формирования расширенной матрицы (9) достаточно вычислить только элементы первой строки и двух последних столбцов, остальные элементы не являются "оригинальными" и заполняются с помощью циклического присваивания.
Для решения систем уравнений с матрицей Грама разработаны методы сингулярного разложения. Если же m <= 4..5, то такие системы можно решать и более простым методом исключения Гаусса.
Ниже приводится консольная программа на Паскале, реализующая метод МНК со степенным базисом. С клавиатуры вводятся число узлов n, степень полинома m, затем n пар точек (xi, fi). После вычисления коээфициентов полинома МНК степени m можно ввести границы по оси X и шаг по X для построения значений полинома.
{Метод наименьших квадратов}
program Mnk;
uses crt; {модуль управления экраном}
type matrix=array[0..100,0..100] of real;
vector=array [0..100] of real; {Нумеруем точки с нуля}
var n,m,k,i:integer;
x,f,c:vector;
a:matrix;
x0,x9,h,x1:real;
procedure InputData (n:integer; var x,f:vector); {Ввод исходных данных}
begin
for i:=0 to n do begin
write ('Введите пару значений X(',i,'),F(',i,'):');
readln (x[i],f[i]);
end;
end;
function ex (a:real; n:integer):real;
{Показательная функция для формирования матрицы Грама}
var i:integer;
e:real;
begin
e:=1;
for i:=1 to n do e:=e*a;
ex:=e;
end;
procedure Gram (n,m:integer; var x,f:vector; var a:matrix);
{Формирование матрицы Грама A по векторам данных X,F}
var i,j:integer;
p,q,r,s:real;
begin
for j:=0 to m do begin
s:=0; r:=0; q:=0;
for i:=0 to n do begin
p:=ex(x[i],j);
s:=s+p;
r:=r+p*f[i];
q:=q+p*ex(x[i],m);
end;
a[0,j]:=s;
a[j,m]:=q;
a[j,m+1]:=r;
end;
{Надо формировать только 1-ю строку и 2 последних столбца матрицы Грама,
остальные элементы легко получить циклическим копированием:}
for i:=1 to m do
for j:=0 to m-1 do a[i,j]:=a[i-1,j+1];
end;
procedure Gauss(n:integer; var a:matrix; var x:vector);
{Решение СЛАУ методом Гаусса}
{a - расширенная матрица системы, x - вектор результата}
var i,j,k,l,k1,n1:integer;
r,s:real;
begin
{Прямой ход:}
n1:=n+1;
for k:=0 to n do begin
k1:=k+1;
s:=a[k,k];
for j:=k1 to n1 do a[k,j]:=a[k,j]/s;
for i:=k1 to n do begin
r:=a[i,k];
for j:=k1 to n1 do a[i,j]:=a[i,j]-a[k,j]*r;
end;
end;
{Обратный ход:}
for i:=n downto 0 do begin
s:=a[i,n1];
for j:=i+1 to n do s:=s-a[i,j]*x[j];
x[i]:=s;
end;
end;
function fi (m:integer; var c:vector; x1:real):real;
{Аппроксимирующая функция по найденным коэффициентам МНК}
{m - степень полинома, c - вектор коэффициентов,
x1 - точка, в которой ищем значение}
var i:integer; p:real;
begin
p:=c[m];
for i:=m-1 downto 0 do p:=c[i]+x1*p;
fi:=p;
end;
begin
clrscr; {очистить экран}
writeln ('Подбор зависимости методом наименьших квадратов');
write ('Введите число узлов (1<n<100):');
read (n);
n:=n-1; {нумерация будет с нуля!}
write ('Введите степень полинома (1<=m<=',n,'):');
read (m);
InputData (n,x,f); {вводим данные}
Gram (n,m,x,f,a); {считаем матрицу Грама}
Gauss (m,a,c); {решаем систему линейных уравнений}
writeln ('Коэффициенты полинома МНК ',m,' степени:');
for i:=0 to m do write (c[i]:10:4);
writeln;
writeln ('Введите границы по оси X для построения полинома:');
read (x0,x9);
writeln ('Введите шаг по X для построения значений полинома:');
read (h);
k:=round((x9-x0)/h+1);
x1:=x0;
for i:=1 to k do begin
{строим и выводим полином по найденным коэффициентам}
writeln (x1:10:4,fi(m,c,x1):10:4);
x1:=x1+h;
end;
reset (input); readln;
end.
Пример вывода программы:
Подбор зависимости методом наименьших квадратов
Введите число узлов (1<n<100):4
Введите степень полинома (1<=m<=3):2
Введите пару значений X(0),F(0):0 0
Введите пару значений X(1),F(1):1 1
Введите пару значений X(2),F(2):2 4
Введите пару значений X(3),F(3):3 9
Коэффициенты полинома МНК 2 степени:
0.0000 0.0000 1.0000
Введите границы по оси X для построения полинома:
-1 4
Введите шаг по X для построения значений полинома:
1
-1.0000 1.0000
0.0000 0.0000
1.0000 1.0000
2.0000 4.0000
3.0000 9.0000
4.0000 16.0000
|
|