Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
Можно поинтересоваться, с какой целью вы вставляете не прямую ссылку, а через yandex.kz с учётом переходов?
Еще не маловажным моментом является, тот факт что практически все программы при осуществлении фиттинга работают лишь с данным сигналом Y и автоматически не осуществляют фиттинг производной этого сигнала, что может привести к малозначимым результатам.

Ориджин спрашивает про начальные параметры. Во многих случаях это правильно, потому что положения максимумов известны (в XPS, например). И если вам не удалось что-то подогнать в ориджине, это значит что вы не умеете им пользоваться (и настраивать). Ваш пример прекрасно это иллюстрирует.
А причиной тому, по моему, является тот факт, что Ориджин автоматически не учитывает в алгоритме мультифитинга требование к совпадению производных оригинального сигнала и глобальной расчетной функции.
Получается, что вроде, отличие расчетного сигнала (красная кривая на графике) от экспериментального не очень большие (Ориджин, как мог провел оптимизацию), но результат не тот, что надо.
Ошибка — она же метрика качества аппроксимации исходного сигнала и его производной определяется по стандартной формуле:
def Two_Signals_error(self, data_exp_x, data_exp_y, data_th_x, data_th_y): # Intended be to called with any two signals which have to be compared
try:
error_y = np.zeros(data_th_x.size, dtype='f2')
for i in range(0, data_th_x.size):
error_y[i] = math.sqrt( (data_exp_y[i] - data_th_y[i])**2 )
return 1000*np.sum(error_y)/math.sqrt((data_th_x.size-1)*data_th_x.size)
except AttributeError:
pass
Если же в метрику добавить условие на минимизацию ошибки производной, то можно получить от расчетной функции нечто большее.
К примеру из общефизических представлений, она будет лучше повторять контур оригинального сигнала, ценность (полезность) ее значений за пределами ранее заданного интервала может также возрасти.
Замечу, что никто не пытается минимизировать суммуошибок «огурцов» и «бананов», они минимизируются отдельно друг от друга,



Если не ошибаюсь, был взят Пример4 от туда. Завтра проверю.
А я пока предскажу, что сумма квадратов отклонений экспериментальных данных от предсказания у Вас будет больше по сравнению с классическим нелинейным методом наименьших квадратов.
import csv
import datetime
from typing import Tuple
import numpy
import matplotlib.pyplot as plt
import scipy.optimize
def get_data(file_name: str) -> Tuple[numpy.ndarray, numpy.ndarray]:
with open(file_name) as csvfile:
rdr = csv.reader(csvfile, delimiter=';')
next(rdr)
tt, yy = [], []
for row in rdr:
tt.append(datetime.datetime.strptime(row[0], '%d.%m.%Y %H:%M:%S'))
yy.append(float(row[1]))
return numpy.array([(dt-tt[0]).total_seconds() for dt in tt])/60, numpy.array(yy)
class Residuals:
def __init__(self, ttt: numpy.array, yyy: numpy.array):
self._ttt = ttt
self._yyy = yyy
def _sigmoid(self, args: numpy.ndarray) -> numpy.ndarray:
xc, a, w1, w2, w3 = args
return a*(1-1/(1+numpy.exp(-(self._ttt-xc-0.5*w1)/w3)))/(1+numpy.exp(-(self._ttt-xc+0.5*w1)/w2))
def _prediction(self, args):
return self._sigmoid(args[0:5])+self._sigmoid(args[5:10])+self._sigmoid(args[10:15])
def __call__(self, args: numpy.ndarray) -> numpy.ndarray:
return self._yyy-self._prediction(args)
def plot_curves(self, args: numpy.array) -> None:
err = numpy.sqrt(numpy.sum(self(args)**2/(len(self._ttt)*(len(self._ttt)-1))))
print()
fmt = 'xc = {:11.8F} a = {:11.8F} w1 = {:11.8F} w2 = {:11.8F} w3 = {:11.8F}'
print(fmt.format(*args[0:5]))
print(fmt.format(*args[5:10]))
print(fmt.format(*args[10:15]))
print()
print('Error =', err)
print()
plt.plot(self._ttt, self._yyy)
plt.plot(self._ttt, self._prediction(args))
plt.plot(self._ttt, self._sigmoid(args[0:5]))
plt.plot(self._ttt, self._sigmoid(args[5:10]))
plt.plot(self._ttt, self._sigmoid(args[10:15]))
plt.grid()
plt.xlim(right=15.0)
plt.show()
def main() -> None:
ttt, yyy = get_data('Import_Exp_6.csv')
res = Residuals(ttt, yyy)
x0 = numpy.array([2, 10, 1, 1, 1,
4, 10, 1, 1, 1,
6, 10, 1, 1, 1])
scale = numpy.array([1, 1, 1, 1, 1,
1, 1, 1, 1, 1,
1, 1, 1, 1, 1])
bounds = numpy.array([[1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0],
[100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100]])
# noinspection PyTypeChecker
x: scipy.optimize.OptimizeResult = scipy.optimize.least_squares(res, x0, jac='3-point', diff_step=1e-8*scale,
x_scale=scale, bounds=bounds, xtol=1e-14,
ftol=3e-16, gtol=1e-14, max_nfev=1000, verbose=1)
res.plot_curves(x.x)
if __name__ == '__main__':
main()
xc = 7.94800396 a = 14.63107180 w1 = 5.29503234 w2 = 0.60003813 w3 = 0.27181285
xc = 3.57356967 a = 11.17972998 w1 = 3.39283920 w2 = 0.16275070 w3 = 0.46028389
xc = 6.11336115 a = 5.88055569 w1 = 7.34512284 w2 = 0.28137491 w3 = 0.54191075
Error = 0.0032602356426855014
Необходимость 2
Допустим мы находимся на правой границе интервала и пытаем фиттингом найти «истинную» функцию. Если мы будем учитывать как изменялся не только сам экспериментальный сигнал (к примеру координату движения частицы), но и его производная (скорость или энергия), мы сможем лучше подобрать физически осмысленную функцию(и) и ее параметры для экстраполяции кривой за границу интервала,
т.е. предсказать ее дальнейшую скорость и траекторию. Здесь, позвольте без доказательств и конкретных примеров. Уверен, что студент первого курса по естественным наукам поймет о чем речь.
Только смысл в нем какой, показать, что «автомобиль» (МНК, который применили на всем готовом, т.е. дали ему подходящие аналитические функции)) быстрее «пешехода» — ручного подбора параметров (и всего в 2 раза).
Про учет производной сигнала при ручном подборе параметров я уже писал,
В процессе самого фиттинга хотелось иметь возможность самому контролировать процесс подбора параметров,
а не доверять в слепую алгоритмам оптимизации,
в первую очередь из-за того, что они не учитывают совпадение производных экспериментального и расчетного сигналов
В замечательной программе OriginPro 8 мультифиттинг ограничен функциями Лоренца и Гаусса, что уже не плохо, но не достаточно.
Для сглаживания можно использовать Savitzky-Golay filter, он есть в scipy библиотеке.
У Fityk есть одна «киллер фича», за которую я его особенно люблю, в моей работе часто приходится фитовать набор похожих спектров (например, температурную зависимость спектров для образца) и в Fityk можно взять результат фита для одного спектра и использовать его как начального приближение для фита другого спектра, это очень ускоряет работу и повышает качество фита большого массива данных.
Мультифункциональный фиттинг экспериментальных данных