Численные методы. Учебное пособие для СПО
.pdf4. АППРОКСИМАЦИЯ ФУНКЦИЙ
Аппроксимация — это замена сложной или неизвестной функции более простой (аппроксимирующей) функцией, близкой к исходной в определенном смысле. Она применяется, когда: точное выражение функции неизвестно (есть только данные), функция слишком сложна для анализа, необходимо упростить вычисления [6].
Рассматривается два типа аппроксимации: точечная — это когда функция задана таблично (имеется некоторый набор точек) и нужно подобрать аналитическую зависимость.
Функциональная аппроксимация — это когда исходная функция известна, но ее необходимо приблизить более простой функцией (например, заменить сложный интеграл полиномом).
4.1. ИНТЕРПОЛЯЦИЯ
Интерполяция — это метод нахождения неизвестной функции по заданному набору ее значений в дискретных точках. Иными словами, если известны значения функции ( ) в точках0, 1, … , (узлы интерполяции), интерполяция позволяет построить функцию ( ) (интерполянт), которая точно проходит через эти точки и может использоваться для предсказания значений в промежуточных точках.
Интерполяционный полином в форме Лагранжа.
Необходимо построить полином ( ), проходящий через заданные точки, т.е.
( ) =
41
Интерполяционный полином Лагранжа имеет следующую формулу:
( ) = −1( ) = ∑ =1 ( ),
где
( − 1) … ( − −1)( − +1) … ( − )( ) = ( − ) … ( − −1)( − +1) ( − )
Реализация на языке Python
import numpy as np
import matplotlib.pyplot as plt
def lagrange(x, y, x_interp): n = len(x)
result = 0.0
for i in range(n): term = y[i]
for j in range(n): if j != i:
term *= (x_interp - x[j]) / (x[i] - x[j]) result += term
return result
# Данные
x_data = np.array([1, 2, 3]) y_data = np.array([2, 3, 5])
# Интерполяция
x_new = np.linspace(1, 3, 100)
42
y_new = [lagrange(x_data, y_data, xi) for xi in x_new]
# График
plt.scatter(x_data, y_data, color='red', label='Узлы') plt.plot(x_new, y_new, label='Полином Лагранжа') plt.legend()
plt.show()
Интерполяционный полином Ньютона (разделенные разности) имеет вид:
( ) = [ 0] + [ 0, 0]( − 0) + + [ 0, … , ]( − 0) ( − −1)
Реализация на языке Python
function yy = newton(x, y, xx) N = length(x);
DIFF = y;
for k = 1 : N-1 for i = 1: N - k
DIFF(i) = (DIFF(i+1) - DIFF(i)) / (x(i+k) - x(i)); end
end
yy = DIFF(1) * ones(size(xx)); for k = 2 : N
yy = DIFF(k) + (xx - x(k)) .* yy; end
%Интерполируем с ее помощью следующий набор данных: % точки данных
x = [0.1 2.2 3.1 4.9 6.5];
43
y = [0.8 0.9 0.1 -0.7 -0.9];
xx= linspace(x(1), x(end), 100);
yy= newton(x, y, xx);
plot(x,y,'o',xx,yy)
Реализация на языке Matlab
function yy = newton(x, y, xx) N = length(x);
DIFF = y;
for k = 1 : N-1 for i = 1: N - k
DIFF(i) = (DIFF(i+1) - DIFF(i)) / (x(i+k) - x(i)); end
end
yy = DIFF(1) * ones(size(xx)); for k = 2 : N
yy = DIFF(k) + (xx - x(k)) .* yy; end
Интерполируем с ее помощью следующий набор данных: % точки данных
x = [0.1 2.2 3.1 4.9 6.5];
y = [0.8 0.9 0.1 -0.7 -0.9];
xx= linspace(x(1), x(end), 100);
yy= newton(x, y, xx);
plot(x,y,'o',xx,yy)
44
4.2. СПЛАЙН-ИНТЕРПОЛЯЦИЯ
Сплайн-интерполяция — это метод построения гладкой функции, проходящей через заданные точки (узлы), с помощью кусочно-полиномиальных функций. В отличие от глобальной полиномиальной интерполяции (например, полинома Лагранжа), сплайны обеспечивают лучшую устойчивость и избегают осцилляций (проблема Рунге).
Сплайн — это функция, состоящая из нескольких полиномов, каждый из которых определен на своем отрезке между узлами.
Степень сплайна — максимальная степень полиномов (чаще всего используют кубические сплайны — 3-й степени).
Условия гладкости: непрерывность функции и ее производных (обычно до 2-й производной включительно).
Типы сплайнов делят по степеням:
1.Линейный сплайн (сплайн 1-ой степени) состоит из прямых линий, соединяющих соседние точки.
2.Квадратичный сплайн (2-ой степени) использует параболы для каждого отрезка.
3.Кубический сплайн (3-й степени) состоит из суммы вида:
( ) = + ( − ) + ( − )2 + ( − )3.
Сплайны применяются для построения гладких кривых и поверхностей в компьютерной графике; при расчете траекторий движения объектов в анимации; для восстановления непрерывных сигналов из дискретных данных в обработке сигналов; при аппроксимации экспериментальных данных в инженерии.
45
Реализация на языке Python
import numpy as np
import matplotlib.pyplot as plt
def cubic_spline(x, y): n = len(x) - 1
h = np.diff(x)
#Матрица для коэффициентов (вторая производная)
A = np.zeros((n+1, n+1)) B = np.zeros(n+1)
#Заполнение матрицы (условия непрерывности второй производной)
A[0, 0] = 1 # Естественный сплайн: c0 = 0 A[-1, -1] = 1 # cn = 0
for i in range(1, n): A[i, i-1] = h[i-1]
A[i, i] = 2*(h[i-1] + h[i]) A[i, i+1] = h[i]
B[i] = 3*((y[i+1] - y[i])/h[i] - (y[i] - y[i-1])/h[i-1])
#Решение системы (метод прогонки или np.linalg.solve) c = np.linalg.solve(A, B)
#Вычисление коэффициентов b и d
b = np.zeros(n) d = np.zeros(n) for i in range(n):
b[i] = (y[i+1] - y[i])/h[i] - h[i]*(2*c[i] + c[i+1])/3 d[i] = (c[i+1] - c[i])/(3*h[i])
# Коэффициенты a (значения y)
46
a = y[:-1]
return a, b, c[:-1], d, x[:-1]
# Исходные данные
x = np.array([0, 1, 2, 3, 4]) y = np.array([0, 2, 1, 3, 2])
# Получение коэффициентов
a, b, c, d, x_knots = cubic_spline(x, y)
# Функция для вычисления значения сплайна в точке x_val def eval_spline(a, b, c, d, x_knots, x_val):
i = np.searchsorted(x_knots, x_val) - 1 if i < 0:
i = 0
dx = x_val - x_knots[i]
return a[i] + b[i]*dx + c[i]*dx**2 + d[i]*dx**3
# Визуализация
x_new = np.linspace(0, 4, 100)
y_new = [eval_spline(a, b, c, d, x_knots, xi) for xi in x_new]
plt.figure(figsize=(8, 5))
plt.plot(x, y, 'o', label='Исходные точки')
plt.plot(x_new, y_new, '-', label='Кубический сплайн (ручная реализация)')
plt.legend()
plt.grid()
plt.title('Ручная реализация кубического сплайна') plt.show()
47
Реализация на языке Matlab
function [a, b, c, d] = cubic_spline(x, y) n = length(x) - 1;
h = diff(x);
% Матрица для вторых производных
A = zeros(n+1, n+1);
A(1,1) = 1; A(n+1,n+1) = 1; % Естественные условия
rhs = zeros(n+1, 1);
for i = 2:n
A(i,i-1) = h(i-1);
A(i,i) = 2*(h(i-1) + h(i)); A(i,i+1) = h(i);
rhs(i) = 3*((y(i+1)-y(i))/h(i) - (y(i)-y(i-1))/h(i-1)); end
%Решение системы c = A \ rhs;
%Вычисление остальных коэффициентов b = zeros(n,1);
d = zeros(n,1); a = y(1:n)';
for i = 1:n
b(i) = (y(i+1)-y(i))/h(i) - h(i)*(2*c(i)+c(i+1))/3; d(i) = (c(i+1)-c(i))/(3*h(i));
end
c = c(1:n); end
% Использование:
48
x = [0 1 2 3]; y = [1 0 1 0];
[a, b, c, d] = cubic_spline(x, y);
% Вычисление значения в точке x_star x_star = 1.5;
for i = 1:length(x)-1
if x_star >= x(i) && x_star <= x(i+1)
S = a(i) + b(i)*(x_star-x(i)) + c(i)*(x_star-x(i))^2 + d(i)*(x_star-x(i))^3;
break; end
end
disp(['S(', num2str(x_star), ') = ', num2str(S)]);
4.3. СГЛАЖИВАНИЕ. МЕТОД НАИМЕНЬШИХ КВАДРАТОВ
Метод наименьших квадратов — это статистический ме-
тод оптимизации, который минимизирует сумму квадратов отклонений между наблюдаемыми значениями ( ) и значениями, предсказанными моделью (( )), что математически выражается формулой:
∑ =1( − ( , ))2,
где — количество наблюдений, а параметры модели.
Реализация на языке Python
import numpy as np
import matplotlib.pyplot as plt
N = 100 # число экспериментов
sigma = 3 # стандартное отклонение наблюдаемых значений
49
k = 0.5 # теоретическое значение параметра k b = 2 # теоретическое значение параметра b x = np.array(range(N))
f = np.array([k*z+b for z in range(N)]) y = f + np.random.normal(0, sigma, N) plt.scatter(x, y, s=2, c='red') plt.grid(True)
plt.show()
# вычисляем коэффициенты mx = x.sum()/N
my = y.sum()/N
a2 = np.dot(x.T, x)/N
a11 = np.dot(x.T, y)/N
kk = (a11 - mx*my)/(a2 - mx**2) bb = my - kk*mx
ff = np.array([kk*z+bb for z in range(N)]) plt.plot(f)
plt.plot(ff, c='red')
Реализация на языке Matlab
% Данные
x = [1, 2, 3, 4, 5]';
y = [1.1, 1.9, 3.2, 4.1, 5.0]';
% Линейная модель y = β + β x X = [ones(size(x)), x];
beta = X \ y; % Решение МНК
%Альтернатива beta = lscov(X, y);
%Аппроксимация полиномом 2-й степени p = polyfit(x, y, 2);
50
