Еще один вопрос об уравнении сигмоидальной регрессии - PullRequest
2 голосов
/ 02 декабря 2010

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

У меня есть сценарий ниже, который выполняет следующие действия:
1.) строит кривую наилучшего соответствия сигмоидальным данным.
2.) изменяет размеры данных, основываясь на новых максимумах и мин.координаты для x и y.
3.) рассчитать и построить новую кривую наилучшего соответствия для измененных размеров данных.

Кажется, что шаги 1 и 2 работают нормально, а шаг 3 - нет.Если вы запустите скрипт, вы увидите, что он строит абсолютно недопустимую кривую для данных с измененным размером.

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

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

New_p, New_cov, New_infodict, New_mesg, New_ier = scipy.optimize.leastsq( 
    residuals,New_p_guess,args=(NewX,NewY),full_output=1,warning=True)   

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

Вот текущий черновик моего полного кода:

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

def GetMinRR(age):
    MaxHR = 208-(0.7*age)
    MinRR = (60/MaxHR)*1000
    return MinRR

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) 

def resize(x,y,xmin=0.0,xmax=1.0,ymin=0.0,ymax=1.0):
    # Create local variables
    NewX = [t for t in x]
    NewY = [t for t in y]
    # If the mins are greater than the maxs, then flip them.
    if xmin>xmax: xmin,xmax=xmax,xmin 
    if ymin>ymax: ymin,ymax=ymax,ymin
    #----------------------------------------------------------------------------------------------    
    # The rest of the code below re-calculates all the values in x and then in y with these steps:
    #       1.) Subtract the actual minimum of the input x-vector from each value of x
    #       2.) Multiply each resulting value of x by the result of dividing the difference
    #           between the new xmin and xmax by the actual maximum of the input x-vector
    #       3.) Add the new minimum to each value of x
    # Note: I wrote in x-notation, but the identical process is also repeated for y
    #----------------------------------------------------------------------------------------------    
    # Subtracts right operand from the left operand and assigns the result to the left operand.
    # Note: c -= a is equivalent to c = c - a
    NewX -= x.min()

    # Multiplies right operand with the left operand and assigns the result to the left operand.
    # Note: c *= a is equivalent to c = c * a
    NewX *= (xmax-xmin)/NewX.max()

    # Adds right operand to the left operand and assigns the result to the left operand.
    # Note: c += a is equivalent to c = c + a
    NewX += xmin

    # Subtracts right operand from the left operand and assigns the result to the left operand.
    # Note: c -= a is equivalent to c = c - a
    NewY -= y.min()

    # Multiplies right operand with the left operand and assigns the result to the left operand.
    # Note: c *= a is equivalent to c = c * a
    NewY *= (ymax-ymin)/NewY.max()

    # Adds right operand to the left operand and assigns the result to the left operand.
    # Note: c += a is equivalent to c = c + a
    NewY += ymin

    return (NewX,NewY)

# Declare raw data for use in creating logistic regression equation
x = np.array([821,576,473,377,326],dtype='float') 
y = np.array([255,235,208,166,157],dtype='float') 

# Call resize() function to re-calculate coordinates that will be used for equation
MinRR=GetMinRR(50)
MaxRR=1200
minLVET=(y[4]/x[4])*MinRR
maxLVET=(y[0]/x[0])*MaxRR

#x,y=resize(x,y,xmin=0.3, ymin=0.3) 
NewX,NewY=resize(x,y,xmin=MinRR,xmax=MaxRR,ymin=minLVET,ymax=maxLVET) 
print 'x is:  ',x 
print 'y is:  ',y
print 'NewX is:  ',NewX
print 'NewY is:  ',NewY

# p_guess is the starting estimate for the minimization
p_guess=(np.median(x),np.median(y),1.0,1.0) 
New_p_guess=(np.median(NewX),np.median(NewY),1.0,1.0) 

# Calls the leastsq() function, which calls the residuals function with an initial
# guess for the parameters and with the x and y vectors.  The full_output means that
# the function returns all optional outputs.  Note that the residuals function also
# calls the sigmoid function.  This will return the parameters p that minimize the
# least squares error of the sigmoid function with respect to the original x and y
# coordinate vectors that are sent to it.
p, cov, infodict, mesg, ier = scipy.optimize.leastsq( 
    residuals,p_guess,args=(x,y),full_output=1,warning=True)   

New_p, New_cov, New_infodict, New_mesg, New_ier = scipy.optimize.leastsq( 
    residuals,New_p_guess,args=(NewX,NewY),full_output=1,warning=True)   

# Define the optimal values for each element of p that were returned by the leastsq() function.
x0,y0,c,k=p 
print('''Reference data:\ 
x0 = {x0} 
y0 = {y0} 
c = {c} 
k = {k} 
'''.format(x0=x0,y0=y0,c=c,k=k)) 

New_x0,New_y0,New_c,New_k=New_p 
print('''New data:\ 
New_x0 = {New_x0} 
New_y0 = {New_y0} 
New_c = {New_c} 
New_k = {New_k} 
'''.format(New_x0=New_x0,New_y0=New_y0,New_c=New_c,New_k=New_k))

# Create a numpy array of x-values
xp = np.linspace(x.min(), x.max(), x.max()-x.min())
New_xp = np.linspace(NewX.min(), NewX.max(), NewX.max()-NewX.min())
# Return a vector pxp containing all the y values corresponding with the x-values in xp
pxp=sigmoid(p,xp)
New_pxp=sigmoid(New_p,New_xp)

# Plot the results 
plt.plot(x, y, '>', xp, pxp, 'g-')
plt.plot(NewX, NewY, '^',New_xp, New_pxp, 'r-')
plt.xlabel('x')
plt.ylabel('y',rotation='horizontal')
plt.grid(True)
plt.show()

1 Ответ

2 голосов
/ 02 декабря 2010

Попробуйте это:

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

def GetMinRR(age):
    MaxHR = 208-(0.7*age)
    MinRR = (60/MaxHR)*1000
    return MinRR

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) 

def resize(arr,lower=0.0,upper=1.0):
    # Create local copy
    result=arr.copy()
    # If the mins are greater than the maxs, then flip them.
    if lower>upper: lower,upper=upper,lower
    #----------------------------------------------------------------------------------------------    
    # The rest of the code below re-calculates all the values in x and then in y with these steps:
    #       1.) Subtract the actual minimum of the input x-vector from each value of x
    #       2.) Multiply each resulting value of x by the result of dividing the difference
    #           between the new xmin and xmax by the actual maximum of the input x-vector
    #       3.) Add the new minimum to each value of x
    #----------------------------------------------------------------------------------------------    
    # Subtracts right operand from the left operand and assigns the result to the left operand.
    # Note: c -= a is equivalent to c = c - a
    result -= result.min()

    # Multiplies right operand with the left operand and assigns the result to the left operand.
    # Note: c *= a is equivalent to c = c * a
    result *= (upper-lower)/result.max()

    # Adds right operand to the left operand and assigns the result to the left operand.
    # Note: c += a is equivalent to c = c + a
    result += lower
    return result


# Declare raw data for use in creating logistic regression equation
x = np.array([821,576,473,377,326],dtype='float') 
y = np.array([255,235,208,166,157],dtype='float') 

# Call resize() function to re-calculate coordinates that will be used for equation
MinRR=GetMinRR(50)
MaxRR=1200
# x[-1] returns the last value in x
minLVET=(y[-1]/x[-1])*MinRR
maxLVET=(y[0]/x[0])*MaxRR

print(MinRR, MaxRR)
#x,y=resize(x,y,xmin=0.3, ymin=0.3) 
NewX=resize(x,lower=MinRR,upper=MaxRR)
NewY=resize(y,lower=minLVET,upper=maxLVET) 
print 'x is:  ',x 
print 'y is:  ',y
print 'NewX is:  ',NewX
print 'NewY is:  ',NewY

# p_guess is the starting estimate for the minimization
p_guess=(np.median(x),np.min(y),np.max(y),0.01) 
New_p_guess=(np.median(NewX),np.min(NewY),np.max(NewY),0.01) 

# Calls the leastsq() function, which calls the residuals function with an initial
# guess for the parameters and with the x and y vectors.  The full_output means that
# the function returns all optional outputs.  Note that the residuals function also
# calls the sigmoid function.  This will return the parameters p that minimize the
# least squares error of the sigmoid function with respect to the original x and y
# coordinate vectors that are sent to it.
p, cov, infodict, mesg, ier = scipy.optimize.leastsq( 
    residuals,p_guess,args=(x,y),full_output=1,warning=True)   

New_p, New_cov, New_infodict, New_mesg, New_ier = scipy.optimize.leastsq( 
    residuals,New_p_guess,args=(NewX,NewY),full_output=1,warning=True)   

# Define the optimal values for each element of p that were returned by the leastsq() function.
x0,y0,c,k=p 
print('''Reference data:\ 
x0 = {x0} 
y0 = {y0} 
c = {c} 
k = {k} 
'''.format(x0=x0,y0=y0,c=c,k=k)) 

New_x0,New_y0,New_c,New_k=New_p 
print('''New data:\ 
New_x0 = {New_x0} 
New_y0 = {New_y0} 
New_c = {New_c} 
New_k = {New_k} 
'''.format(New_x0=New_x0,New_y0=New_y0,New_c=New_c,New_k=New_k))

# Create a numpy array of x-values
xp = np.linspace(x.min(), x.max(), x.max()-x.min())
New_xp = np.linspace(NewX.min(), NewX.max(), NewX.max()-NewX.min())
# Return a vector pxp containing all the y values corresponding with the x-values in xp
pxp=sigmoid(p,xp)
New_pxp=sigmoid(New_p,New_xp)

# Plot the results 
plt.plot(x, y, '>', xp, pxp, 'g-')
plt.plot(NewX, NewY, '^',New_xp, New_pxp, 'r-')
plt.xlabel('x')
plt.ylabel('y',rotation='horizontal')
plt.grid(True)
plt.show()

alt text

Ваш другой связанный вопрос не закрыт, кажется, что вы зарегистрировались дважды, и stackoverflow не позволяет вам редактировать другой вопрос, потому что он не распознает этого пользователя таким же, как этот пользователь .

В основном все, что я сделал в приведенном выше коде, - это изменение New_p_guess. Поиск правильных значений для первоначального предположения является своего рода искусством. Если бы это можно было сделать алгоритмически, Сципи не стал бы просить вас сделать это. Небольшой анализ может помочь, а также «почувствовать» ваши данные. Знание заранее, как примерно должно выглядеть решение, и, следовательно, какие значения являются разумными в контексте проблемы, также помогает. (Это всего лишь долгий способ сказать, что я угадал свой путь к выбору k = 0,01.)

...