Вернуться на страницу brain2net: https://brain2net.ru/post/approksimacziya-eksperimentalnyh-tochek-nelinejnoj-funkcziej/#more-230
import numpy as np
import pandas as pd
import random
from scipy.optimize import basinhopping
from scipy.optimize import minimize
import matplotlib.pyplot as plt
# Независимая переменная
t = np.linspace(0.0, 100.0, num=101, endpoint=True)
# Амплитуда, период и фаза для трех синусоид
a1 = 10.9
T1 = 20.1
phi1 = 5.4
a2 = 10.2
T2 = 10.5
phi2 = 4.3
a3 = 9.3
T3 = 5.8
phi3 = -3.9
# Сумма 3-х синусоид. Требуется, что-бы аппроксимация была близка к этой функции
y = a1 * np.sin(2 * np.pi * t / T1 + phi1) \
+ a2 * np.sin(2 * np.pi * t / T2 + phi2) \
+ a3 * np.sin(2 * np.pi * t / T3 + phi3)
# График исходной функции
plt.plot(t, y, 'b.')
plt.plot(t, y, 'b')
plt.grid()
# Добавляется шум и формируется выборка "экспериментальных" точек
nois = [random.gauss(0, 5) for _ in range(101)]
z = [y[i] + nois[i] for i in range(101)]
data = pd.DataFrame({'t': t, 'y': y, 'z': z,})
# График "экспериментальных" точек
plt.plot(data.t, data.z, 'm.')
plt.grid()
Формирование функции для оценки ошибки минимизации
def function_test(b):
# Идентификаторы для 3-х амплитуд, перидов и фаз
a1 = b[0]
T1 = b[1]
phi1 = b[2]
a2 = b[3]
T2 = b[4]
phi2 = b[5]
a3 = b[6]
T3 = b[7]
phi3 = b[8]
# Расчет значения функции
data['h'] = a1 * np.sin(2 * np.pi * data['t'] / T1 + phi1) \
+ a2 * np.sin(2 * np.pi * data['t'] / T2 + phi2) \
+ a3 * np.sin(2 * np.pi * data['t'] / T3 + phi3)
# Оценка коэффициента детерминации
data['dres2'] = (data.h - data.z) ** 2
SSres = data.dres2.sum()
z_mean = data.z.mean()
data['dtot2'] = (z_mean - data.z) ** 2
SStot = data['dtot2'].sum()
R2 = 1. - SSres / SStot
# При необходимости можно распечатать изменение коэффициента детерминации - приближении его к единице
# print(R2)
criterion = abs(SSres / SStot)
return criterion
Начальные значения (далекие от значений исходной функции)
b0 = [
20.,
30.,
0.,
20.,
15.,
0.,
20.,
8.,
0.]
Применение функции basinhopping
minimizer_kwargs = {"method": "BFGS"}
res = basinhopping(function_test, b0, minimizer_kwargs=minimizer_kwargs, niter=100)
res
res.x
Полученные параметры искомой функции
a1 = res.x[0]
T1 = res.x[1]
phi1 = res.x[2]
a2 = res.x[3]
T2 = res.x[4]
phi2 = res.x[5]
a3 = res.x[6]
T3 = res.x[7]
phi3 = res.x[8]
# Расчет аппроксимации
y_calc = a1 * np.sin(2 * np.pi * t / T1 + phi1) \
+ a2 * np.sin(2 * np.pi * t / T2 + phi2) \
+ a3 * np.sin(2 * np.pi * t / T3 + phi3)
# График аппроксимации на фоне "экспериментальных" точек
plt.plot(data.t, data.z, 'mo')
plt.plot(t, y_calc, 'g')
plt.grid()
# График аппроксимации (зеленая кривая) на фоне исходной функции (синяя кривая)
plt.plot(data.t, data.y, 'b')
plt.plot(t, y_calc, 'g')
plt.grid()
Применение функции minimize
res = minimize(function_test, b0, method='BFGS')
res
Полученные параметры искомой функции
a1 = res.x[0]
T1 = res.x[1]
phi1 = res.x[2]
a2 = res.x[3]
T2 = res.x[4]
phi2 = res.x[5]
a3 = res.x[6]
T3 = res.x[7]
phi3 = res.x[8]
# Расчет аппроксимации
y_calc = a1 * np.sin(2 * np.pi * t / T1 + phi1) \
+ a2 * np.sin(2 * np.pi * t / T2 + phi2) \
+ a3 * np.sin(2 * np.pi * t / T3 + phi3)
# График аппроксимации на фоне "экспериментальных" точек
plt.plot(data.t, data.z, 'mo')
plt.plot(t, y_calc, 'g')
plt.grid()
# График аппроксимации (зеленая кривая) на фоне исходной функции (синяя кривая)
plt.plot(data.t, data.y, 'b')
plt.plot(t, y_calc, 'g')
plt.grid()
Вернуться на страницу brain2net: https://brain2net.ru/post/approksimacziya-eksperimentalnyh-tochek-nelinejnoj-funkcziej/#more-230