Как передать серию или массив фрейма данных в экспоненциальную функцию при расчете кривой

Я пытаюсь использовать модуль scipy.optimize.

Моя экспоненциальная функция:

a - (a - b) np.exp( -(c + Q / V) * t )

Мне нужно найти a, b, c из уравнения путем оптимизации.

V = 1200 # constant

мой фрейм данных выглядит так:

time(t)   value    score(Q)
1.0       2.347    4500
2.0       2.345    4600
3.0       2.523    4655
4.0       2.723    4500
    ...
    ...
100.0    5.6787    7000
    ...

Значения в поле значений увеличиваются линейно.

Моя подходящая функция для приведенной выше экспоненты:

def my_exp(Q, t, a, b, c): #just added Q here  
    V = 1280
    return a - (a - b) np.exp( -(c + Q / V) * t )

# Q = 5000 #mean value from column score
# getting values
c, cov = curve_fit(lambda t, a, b, c: my_exp(Q, t, a, b, c), df['time'], df['value'])

сценарий 1: когда столбец оценки не указан, при условии, что константа должна быть передана как (например: Q = 5000). Я попытался взять среднее значение из серии оценок, и это работает.

сценарий 2: когда указан столбец оценок, отправьте ряд оценок в экспоненциальную функцию Q, которая должна предоставлять значение оценки в каждый момент времени.

Как я могу отправить значения массива серии оценок в экспоненциальную функцию Q, чтобы получить оптимизированное значение?

Это правильный способ сделать curve_fit для вышеупомянутых данных или мне нужно следовать любым другим моделям подбора кривой?


person Sai Kiran    schedule 20.07.2020    source источник


Ответы (1)


Привет, поскольку грязная работа вокруг вас может сделать следующее:

  • не передавайте Q в качестве аргумента.
  • сделать Q глобальным списком
  • поскольку t в основном представляет собой целочисленный вызов внутри my_epx, значение Q через Q[ int( round( t ) ) ]

Изменить/дополнить

Это должно прояснить:

import numpy as np
from scipy.optimize import curve_fit

# setting static values
v = 2500
qlist = [ np.random.randint(4500, 4650 ) for i in range( 15 ) ]
tlist = np.arange( 1, 16 )
noiselist = np.random.normal( 0, 0.3, 15 )
a0 = 5
b0 = 2.2
c0 = -.78

# simple function checking for iterable first argument
def my_exp( t, a, b, c):
    if isinstance( t, ( list, tuple, np.ndarray ) ):
        out = np.fromiter( ( my_exp( tt, a, b, c) for tt in t ), np.float )
    else:
        localindex = int( round ( t ) ) - 1 ## -1 as t starts at 1 but index at 0
        localq = qlist[ localindex ]
        out = a - ( a - b ) * np.exp( -( c + localq / v ) * t )
    return out

# creating some test data with noise
testdata = my_exp( tlist, a0, b0, c0 )
testdatanoisy = testdata + noiselist

# fitting, does not even require start values
sol, _ = curve_fit( my_exp, tlist, testdatanoisy )
print sol
# works

который дает что-то вроде:

>> [ 4.89673111,  1.70423291, -0.72995739 ]
person mikuszefski    schedule 22.07.2020
comment
Привет, @mikuszefski, я пытался, как ты объяснил, но получаю сообщение об ошибке. ` Ошибка типа: тип RangeIndex не определяет метод round `, и я пытался напечатать t, но получаю это RangeIndex(start=0, stop=622, step=1). Правильно ли я передаю t? Если нет, не могли бы вы предложить мне другой способ - person Sai Kiran; 22.07.2020
comment
@SaiKiran извините за путаницу. Ты прав. Вы правильно передаете t, но я забыл, что он, скорее всего, будет передан как массив. Как следствие, вам нужно перебирать этот массив самостоятельно. - person mikuszefski; 23.07.2020