сигмоидальная регрессия с scipy, numpy, python и т. Д.

У меня есть две переменные (x и y ), которые имеют несколько сигмоидальные отношения друг с другом, и мне нужно найти какое-то уравнение прогнозирования, которое позволит мне предсказать значение y при любом значении x. Мое уравнение прогноза должно показать несколько сигмоидальную связь между двумя переменными. Поэтому я не могу согласиться на уравнение линейной регрессии, которое дает линию. Мне нужно увидеть постепенное криволинейное изменение наклона, которое происходит как справа, так и слева от графика двух переменных.

Я начал использовать numpy.polyfit после поиска в Google криволинейной регрессии и python, но это дало мне ужасные результаты вы можете увидеть, запустили ли вы приведенный ниже код. Может ли кто-нибудь показать мне, как переписать приведенный ниже код, чтобы получить нужный мне тип уравнения сигмоидальной регрессии?

Если вы запустите приведенный ниже код, вы увидите, что он дает параболу, направленную вниз, это не то, как должны выглядеть отношения между моими переменными. Вместо этого между двумя моими переменными должно быть больше сигмоидального отношения, но с точным соответствием данным, которые я использую в приведенном ниже коде. Данные в приведенном ниже коде являются средними из исследования с большой выборкой, поэтому они обладают большей статистической мощностью, чем можно предположить по их пяти точкам данных. У меня нет фактических данных исследования с большой выборкой, но у меня есть приведенные ниже средства и их стандартные отклонения (которые я не показываю). Я бы предпочел просто построить простую функцию со средними данными, перечисленными ниже, но код мог бы стать более сложным, если бы сложность предлагала существенные улучшения.

Как я могу изменить свой код, чтобы показать наилучшее соответствие сигмоидальной функции, предпочтительно используя scipy, numpy, и python? Вот текущая версия моего кода, которую необходимо исправить:

import numpy as np
import matplotlib.pyplot as plt

# Create numpy data arrays
x = np.array([821,576,473,377,326])
y = np.array([255,235,208,166,157])

# Use polyfit and poly1d to create the regression equation
z = np.polyfit(x, y, 3)
p = np.poly1d(z)
xp = np.linspace(100, 1600, 1500)
pxp=p(xp)

# Plot the results
plt.plot(x, y, '.', xp, pxp, '-')
plt.ylim(140,310)
plt.xlabel('x')
plt.ylabel('y')
plt.grid(True)
plt.show()

РЕДАКТИРОВАТЬ НИЖЕ: (переформулировал вопрос)

Ваш ответ и его скорость очень впечатляют. Спасибо, unutbu. Но, чтобы получить более достоверные результаты, мне нужно переформатировать значения данных. Это означает повторное преобразование значений x в процентах от максимального значения x и повторное преобразование значений y в процентах от значений x в исходных данных. Я попытался сделать это с вашим кодом и пришел к следующему:

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

# Create numpy data arrays 
'''
# Comment out original data
#x = np.array([821,576,473,377,326]) 
#y = np.array([255,235,208,166,157]) 
'''

# Re-calculate x values as a percentage of the first (maximum)
# original x value above
x = np.array([1.000,0.702,0.576,0.459,0.397])

# Recalculate y values as a percentage of their respective x values
# from original data above
y = np.array([0.311,0.408,0.440,0.440,0.482])

def sigmoid(p,x): 
    x0,y0,c,k=p 
    y = c / (1 + np.exp(-k*(x-x0))) + y0 
    return y 

def residuals(p,x,y): 
    return y - sigmoid(p,x) 

p_guess=(600,200,100,0.01) 
(p,  
 cov,  
 infodict,  
 mesg,  
 ier)=scipy.optimize.leastsq(residuals,p_guess,args=(x,y),full_output=1,warning=True)  

'''
# comment out original xp to allow for better scaling of
# new values
#xp = np.linspace(100, 1600, 1500) 
'''

xp = np.linspace(0, 1.1, 1100) 
pxp=sigmoid(p,xp) 

x0,y0,c,k=p 
print('''\ 
x0 = {x0}
y0 = {y0}
c = {c}
k = {k}
'''.format(x0=x0,y0=y0,c=c,k=k)) 

# Plot the results 
plt.plot(x, y, '.', xp, pxp, '-') 
plt.ylim(0,1) 
plt.xlabel('x') 
plt.ylabel('y') 
plt.grid(True) 
plt.show()

Вы можете показать мне, как исправить этот измененный код?
ПРИМЕЧАНИЕ. При повторном преобразовании данных я по существу повернул 2d (x , y) сигмоид вокруг оси z на 180 градусов. Кроме того, 1.000 на самом деле не является максимумом значений x. Вместо этого 1.000 - это среднее значение диапазона значений от разных участников теста в максимальных условиях тестирования.


ВТОРОЙ РЕДАКТИРОВАНИЕ НИЖЕ:

Спасибо, ubuntu. Я внимательно прочитал ваш код и рассмотрел его аспекты в scipy документации. Поскольку ваше имя, кажется, появляется как автор scipy документации, Я надеюсь, что вы сможете ответить на следующие вопросы:

1.) Вызывает ли leastsq () остатки (), которые затем возвращают разницу между входным y-вектором и y-вектором, возвращаемым функцией sigmoid ()? Если да, то как он учитывает разницу в длине входного y-вектора и y-вектора, возвращаемого функцией sigmoid ()?

2.) Похоже, я могу вызвать leastsq () для любой математики уравнение, если я обращаюсь к этому математическому уравнению через функцию остатков, которая, в свою очередь, вызывает математическую функцию. Это правда?

3.) Также я заметил, что p_guess имеет то же количество элементов, что и p. Означает ли это, что четыре элемента p_guess по порядку соответствуют значениям, возвращаемым x0, y0, c и k?

4. ) Является ли p, который передается в качестве аргумента функциям Остаточные () и sigmoid (), тот же самый p, который будет выводиться функцией leastsq (), и функция leastsq () использует этот p внутри перед его возвратом?

5.) Могут ли p и p_guess иметь любое количество элементов, в зависимости от сложности уравнения, используемого в качестве модели, если количество элементов в p равно количеству элементов в p_guess?

27
задан MedicalMath 1 December 2010 в 00:56
поделиться