Как поместить функцию Cos в список целых чисел, не сжимая ось X или Y в Python? - PullRequest
1 голос
/ 16 апреля 2020

У меня есть список чисел с именем img, в котором 400 номеров. Как только я нарисую его, я могу ясно увидеть шаблон cos в нем. Как только я пытаюсь соответствовать с помощью optimize.curve_fit, функция не может соответствовать правильно, если я не разделю img на большое число, а также уменьшу диапазон оси X. Например, в приведенном ниже коде rangeY и rangeX - это факторы, которые я использую для сокращения списка в измерениях Y и X соответственно. В первом примере вы можете видеть, что фитинг работает отлично:

import numpy as np
from scipy import optimize
import matplotlib.pyplot as plt

rangeY = 8000
rangeX = 3

def test_func(x, a, b, c, d):
    return a + b * np.cos(c * x + d)

def fitCurve (img):
    x_data = np.linspace(0,rangeX,num=400)
    y_data = []
    for i in range(0,len(img)):
        y_data += [img[i] / rangeY]
    y_data = np.array(y_data)

    param_bounds = ([-np.inf, 0, 0, -np.inf], [np.inf, np.inf, np.inf, np.inf])
    params, params_covariance = optimize.curve_fit(test_func, x_data, y_data,      bounds=param_bounds,maxfev=100000)
    y_curve = test_func(x_data, params[0], params[1], params[2], params[3])
    MSE = round(np.square(np.subtract(y_data, y_curve)).mean(), 5)
    return (params,y_curve,MSE,x_data,y_data)


img = [8452, 8421, 8498, 8521, 8427, 8523, 8667, 8196, 8515, 8110, 8551, 8732, 8189, 8429, 8539, 8360, 8622, 8726, 8529, 8412, 8465, 8497, 8724, 8201, 8804, 8990, 8732, 8985, 8671, 8675, 8450, 8959, 8865, 8665, 8776, 8822, 9230, 8749, 8758, 8849, 8753, 9108, 9100, 8964, 8808, 9352, 8786, 9070, 9359, 8895, 9131, 9117, 8994, 9087, 9352, 9163, 9073, 9190, 9277, 9073, 9276, 9413, 9395, 9223, 9353, 9420, 9462, 9512, 9512, 9571, 9580, 9595, 9593, 9639, 9622, 9647, 9710, 9710, 9725, 9758, 9785, 9814, 9831, 9862, 9889, 9902, 9921, 9941, 9964, 9992, 10050, 10091, 10131, 10131, 10133, 10179, 10177, 10164, 10241, 10291, 10332, 10332, 10316, 10332, 10332, 10333, 10340, 10333, 10333, 10368, 10385, 10391, 10391, 10403, 10439, 10454, 10428, 10407, 10428, 10459, 10480, 10523, 10530, 10539, 10556, 10562, 10586, 10606, 10592, 10612, 10621, 10621, 10587, 10587, 10574, 10574, 10574, 10574, 10587, 10594, 10584, 10597, 10598, 10599, 10606, 10677, 10620, 10620, 10677, 10677, 10633, 10633, 10620, 10633, 10619, 10619, 10619, 10619, 10599, 10599, 10599, 10621, 10616, 10621, 10621, 10616, 10593, 10635, 10582, 10521, 10514, 10484, 10474, 10468, 10456, 10475, 10481, 10481, 10426, 10413, 10386, 10380, 10370, 10370, 10365, 10363, 10336, 10336, 10322, 10318, 10275, 10299, 10275, 10299, 10299, 10275, 10275, 10272, 10264, 10250, 10201, 10184, 10182, 10178, 10176, 10176, 10136, 10178, 10163, 10163, 10170, 10170, 10111, 10147, 10081, 10081, 10074, 10055, 10055, 10063, 10063, 10055, 10030, 10013, 10013, 9958, 9905, 9872, 9864, 9855, 9855, 9864, 9896, 9899, 9899, 9900, 9901, 9923, 9901, 9843, 9836, 9830, 9830, 9810, 9802, 9801, 9783, 9760, 9761, 9739, 9760, 9739, 9712, 9771, 9771, 9734, 9722, 9675, 9632, 9632, 9610, 9624, 9610, 9579, 9597, 9570, 9579, 9555, 9519, 9519, 9517, 9517, 9516, 9516, 9495, 9480, 9428, 9426, 9408, 9408, 9379, 9379, 9391, 9379, 9358, 9327, 9319, 9304, 9297, 9280, 9280, 9288, 9271, 9288, 9297, 9295, 9246, 9246, 9240, 9267, 9246, 9222, 9187, 9169, 9154, 9139, 9100, 9074, 9101, 9101, 9100, 9076, 9074, 9101, 9104, 9116, 9140, 9143, 9133, 9106, 9081, 9090, 9081, 9077, 9067, 9079, 9093, 9093, 9082, 9082, 9079, 9076, 9025, 9017, 9006, 9006, 8991, 9015, 9015, 9006, 9039, 9063, 9096, 9106, 9120, 9120, 9120, 9096, 9113, 9078, 9071, 9078, 9102, 9102, 9117, 9117, 9117, 9117, 9125, 9126, 9145, 9164, 9170, 9178, 9190, 9237, 9265, 9265, 9245, 9251, 9245, 9245, 9251, 9239, 9260, 9267, 9267, 9267, 9259, 9277, 9277, 9261, 9261, 9261, 9286, 9272, 9266, 9266, 9313, 9329, 9313, 9313, 9331, 9328, 9335, 9335, 9385, 9406, 9406, 9403]

params, y_curve, MSE, x_data, y_data = fitCurve(img)
plt.figure(figsize=(6, 4))
plt.scatter(x_data, y_data, label='Data')
plt.plot(x_data, y_curve, color="red", label='Fitted function')
plt.legend(loc='best')
plt.show()

enter image description here

Теперь, если я изменю диапазон Y на меньшее число, например 100, фитинг не работает должным образом, поэтому для того же кода:

rangeY = 100
rangeX = 3

enter image description here

Или, если я не сжимаю ось X (rangeX = 400) он все еще не подходит должным образом:

rangeY = 8000
rangeX = 400

enter image description here

Теперь мой вопрос: есть ли способ правильно подогнать красную кривую на синем точки без уменьшения диапазона осей Y и X или, по крайней мере, без уменьшения оси X? Если нет, как мне найти правильные значения для rangeX и rangeY? Спасибо

1 Ответ

0 голосов
/ 16 апреля 2020

После изучения руководства optimize.curve_fit, я понял, что для "c" в графе c необходим граничный предел. Потому что этот параметр зависит от T кривой, поэтому он определенно нуждается в ограничении. Итак, вот мы с новым набором ограничений и хорошей кривой подгонки, спасибо мне :-)

rangeX = 400
rangeY = 8000
param_bounds = ([-np.inf, 0, 0, -np.inf], [np.inf, np.inf, 0.02, np.inf])

enter image description here

...