Как получить надежную нелинейную регрессию, используя scipy.optimize.least_squares?

Моя конкретная проблема заключается в том, что я не могу преобразовать свои данные в числа с плавающей запятой. У меня есть данные, и я просто хочу подобрать надежную кривую, используя уравнение моей модели:

y = a * e^(-b*z)

Эта поваренная книга является моей ссылкой: нажмите

Ниже моя попытка. Я получаю это:

TypeError: «тип данных не понят»

я считаю, что мои столбцы являются строками, поэтому я попробовал pd.Series.astype().

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import least_squares

for i in range(1):

    def model(z, a, b):
        y = a * np.exp(-b * z)
        return y
    data = pd.read_excel('{}.xlsx'.format(600+i), names = ['EdGnd','380','395','412','443','465','490','510','520','532','555','560','565','589','625','665','670','683','694','710','Temp','z','EdZTemp','Tilt','Roll','EdZVin'])
    data.dropna(axis = 0, how = 'any')
    data.astype('float')
    np.dtype(data)
    data.plot.scatter('z','380') 
    def fun(x, z, y):
        return x[0] * np.exp(-x[1] * z) - y
    x0 = np.ones(3)
    rbst1 = least_squares(fun, x0, loss='soft_l1', f_scale=0.1, args=('z', 'ed380'))
    y_robust = model('z', *rbst1.x)
    plt.plot('z', y_robust, label='robust lsq')
    plt.xlabel('$z$')
    plt.ylabel('$Ed$')
    plt.legend();

person Jacob Cooper    schedule 22.10.2018    source источник
comment
Что должен делать args=('z', '380')? Должно ли значение z иметь значение 380? Оба являются строками, поэтому вы не можете использовать их для умножения. Не могли бы вы предоставить небольшой набор данных для целей отладки?!   -  person Cleb    schedule 22.10.2018
comment
Большое спасибо за ваш ответ! Аргументы в наименьших_квадратах — это мои значения x и y, для которых я хочу получить соответствие. Не знаю почему, но глядя на поваренную книгу, кажется, что автор так и сделал. z — глубина, а 380 — длина волны света. Я попытаюсь получить строки в массив.   -  person Jacob Cooper    schedule 23.10.2018
comment
Длина моих данных варьируется между разными файлами и составляет около 100-200 строк. Он имеет ширину 26 столбцов. К сожалению, я не могу загрузить файл.   -  person Jacob Cooper    schedule 23.10.2018
comment
Хм, я пытаюсь использовать pd.Series.astype() для получения данных в виде с плавающей запятой. np.dtype() говорит: тип данных не понят. Это мой первый опыт использования панд.   -  person Jacob Cooper    schedule 23.10.2018


Ответы (1)


Я думаю, проблема в том, что вы передаете 'z' в args, которая является строкой и поэтому не может использоваться при умножении.

Ниже приведен код, использующий curve_fit который использует least_squares, но может быть немного проще в использовании:

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


# your model definition
def model(z, a, b):
    return a * np.exp(-b * z)

# your input data
x = np.array([20, 30, 40, 50, 60])
y = np.array([5.4, 4.0, 3.0, 2.2, 1.6])

# do the fit with some initial values
popt, pcov = curve_fit(model, x, y, p0=(5, 0.1))

# prepare some data for a plot
xx = np.linspace(20, 60, 1000)
yy = model(xx, *popt)

plt.plot(x, y, 'o', xx, yy)
plt.title('Exponential Fit')

plt.show()

Это будет сюжет

введите здесь описание изображения

Вы можете попытаться адаптировать этот код для своих нужд.

Если вы хотите использовать f_scale, вы можете использовать:

popt, pcov = curve_fit(model, x, y, p0=(5, 0.1), method='trf', f_scale=0.1)

См. документацию:

варги

Аргументы ключевого слова передаются наименьшему квадрату для метода = 'lm' или наименьшему квадрату в противном случае.

Если у вас есть несвязанная проблема, по умолчанию используется method='lm', который использует leastsq, который не принимает f_scale в качестве ключевого слова. Следовательно, мы можем использовать method='trf', который затем использует least_squares, который принимает f_scale.

person Cleb    schedule 23.10.2018
comment
Спасибо! Это работает, но я стремился к надежной подгонке с наименьшими квадратами из-за аргумента f_scale, который не допускает влияния данных с выбросами. Любой способ устранить выбросы данных с помощью curve_fit? - person Jacob Cooper; 25.10.2018
comment
@JacobCooper: можно использовать f_scale в curve_fit; Я отредактировал свой пост соответственно. - person Cleb; 25.10.2018
comment
@JacobCooper: вы также можете передать sigma в curve_fit (подробности см. в связанной документации). - person Cleb; 25.10.2018
comment
Великолепно! Большое спасибо! - person Jacob Cooper; 25.10.2018