scipy.optimize функция мощности ошибки

У меня возникли проблемы с подбором набора значений с заданной функцией: f (x) = const * (1- (x / a) ** b) ** c

Я использую python 3.6.3 со следующим кодом:

import numpy as np
import scipy.optimize as opt
from scipy.optimize import curve_fit

x=[0.,0.4,0.8,1.6,2.,2.4]
y=[0.09882902,0.07298427,0.05111438,0.01679405,0.00517385,0.00065633]

def func(x,a,b,c):
    return y[0] * ( 1 - (x/a)**b )**c

x0=np.array([2.0,0.9,1.5])
opt.curve_fit(func,x,y,p0=x0)

У меня появляется следующее сообщение об ошибке:

RuntimeWarning: invalid value encountered in power
  return y[0] * ( 1 - (x/a)**b )**c
///: OptimizeWarning: Covariance of the parameters could not be estimated
  category=OptimizeWarning)

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

def func(x,a,b,c):
    return y[0] * ( 1 - (x/a)**b )*c

person ant.kr    schedule 22.11.2017    source источник


Ответы (2)


Просто выполните классические шаги отладки: распечатайте свои компоненты, чтобы проверить, правильно ли определены математические операции.

Измените свою функцию на:

def func(x,a,b,c):
    print(x/a)
    print((x/a)**b)
    print((1-(x/a)**b))

    result = y[0] * ( 1 - (x/a)**b )**c
    print(result)

    if not np.isfinite(result):
        assert False
    else:
        return result

и вы увидите:

[ 0.   0.2  0.4  0.8  1.   1.2]
[ 0.          0.23492379  0.43838329  0.81805215  1.          1.17831965]
[ 1.          0.76507621  0.56161671  0.18194785  0.         -0.17831965]
...-py:13: RuntimeWarning: invalid value encountered in power
  result = y[0] * ( 1 - (x/a)**b )**c
[ 0.09882902  0.06613655  0.04159532  0.00767017  0.                 nan]

где возведение в степень не работает для этого отрицательного значения и вводится nan (который, вероятно, представит гораздо больше на более поздних этапах).

Примечание: начальная точка по умолчанию должна быть однозначной (тоже легко распечатать).

Исправление этого зависит от того, что вы на самом деле пытаетесь сделать (изменение модели; использование границ, ...).

person sascha    schedule 22.11.2017
comment
Спасибо. На самом деле эта функция отлично работала с подгонкой gnuplot, и я должен ее использовать, хотя она становится бесконечно маленькой для x - ›a. Если я не ошибаюсь, NaN кажется числом ниже 1e-13. Есть ли способ преодолеть это ограничение? - person ant.kr; 22.11.2017
comment
NaN - это не число :-) Опять же: все зависит от множества решений, к которым у вас есть доступ. Если gnuplot сработал, то есть различия в предположениях или данных, поскольку математическая проблема не исчезнет (в общем случае). - person sascha; 22.11.2017
comment
Возможно, это актуально для вас (и, возможно, разница в gnuplot). - person sascha; 22.11.2017
comment
Что ж, я знаю, что означает нан. Если я запускаю подгонку кривой, начиная с [a = 2,4, b = 0,9, c = 1,5], значение func (x) становится не числом сразу после шага, на котором оно было равно 1e-13. Так, может быть, количество цифр станет слишком важным? - person ant.kr; 22.11.2017
comment
Стать там нанимателем не имеет ничего общего с порогом. - person sascha; 22.11.2017
comment
Что ж, моя ошибка. Я постараюсь с некоторыми ограничениями - person ant.kr; 22.11.2017

Я нашел решение, спасибо Саша. Функция действительно не определена, когда x> a. Чтобы решить эту проблему, я ограничил значение a, чтобы оно всегда превышало максимальное значение x:

fit = opt.curve_fit (func, x, y, p0 = x0, bounds = ([x [-1] +0.001,0.0,1.00], [5.0,1.0,2.0]))

Однако в gnuplot подгонка, возможно, находила x> a. Не знаю почему. Возможно, он берет реальную часть func (x> a), но я не знаю, действительно ли это просто сделать.

person ant.kr    schedule 23.11.2017