我正在尝试将逻辑S形函数拟合到数据。 y 轴中的数据反转以显示 x 轴进展上的长度变化。 T

问题描述 投票:0回答:1

我有许多数据集,它们从较高的 y 轴值开始,然后逐渐减小。这种情况发生在传统的 S 曲线方式中,因此它实际上看起来像反向 S 形曲线。我成功地翻转了 y 数据,使得最大值位于 y 轴的底部,并且向上减小。所以,数据绘制得很好。曲线现在看起来像标准的 S 形曲线。

大问题: 我无法将 sigmoid 拟合到它。这几天我能想到的都做了。

我得到的最好的结果是在附图中。 我有很多拟合看起来不完整,与 sigmoid 拟合应该有的样子相差甚远。

绘制的最佳结果示例:(https://i.stack.imgur.com/NPVry.png)

我的代码:

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

# 1. Data set: 
x_data = np.array([130, 125, 120, 115, 110, 105, 100, 95, 90, 85, 80, 75, 70, 65, 60, 55, 50, 45, 40,     
35, 30, 25])
y_data = np.array([81, 81, 80.5, 79, 77.5, 76, 74.5, 71.5, 68.5, 67, 64, 59.5, 55, 48.5, 44, 42.5, 42,     
41.5, 41.5, 41, 41, 41])

# 2. Reverse the y-values: 
y_data_reversed = np.flip(y_data)
y_range = np.linspace(41, 61.75, 81)

# 3. Sigmoid function defined: 
def sigmoid(x, U, k, a, b): 
    b = 81 #-the maxmimum y_data value. 
    return (U / (1 + np.exp(-k * (x - 77.5))))**a + b

p0 = [np.max(y_data), np.median(x_data), 1, np.min(y_data)] #-as an initial guess for the fit     
calculation. 
popt, pcov = curve_fit(sigmoid, x_data, y_data, p0, maxfev = 10000) #method = 'lm')

# 4. Sigmoid fit to data: 
x_fit = np.linspace(25, 77.5, 130) #-min(x_data), np.median(x_data), max(x_data)). 
y_fit = sigmoid(x_fit, *popt) 

# 5. Plot data and sigmoid fit:
plt.plot(x_data, y_data_reversed, marker='o', linestyle='', color='b', label='Data')
plt.plot(x_fit, y_fit, color='r', label='Sigmoid Fit')
plt.xlabel('Temperature (°C)')
plt.ylabel('Length (mm)')
plt.title('Sigmoid Fit for Contraction Data')
plt.gca().invert_yaxis()  # ...Invert y-axis to start with highest value at the top
plt.legend()
plt.grid(True)
plt.show() 
python plot logistic-regression data-fitting sigmoid
1个回答
0
投票

一般来说,将指数作为参数(如代码中的

a
参数)是危险的,因为如果优化器为此参数选择高/低值,则很容易导致数值上溢/下溢。

您的

b
参数是多余的,因为您将
b
设置为 sigmoid 函数内的固定值。这是故意的吗?

这是我根据您的数据拟合的简化模型,没有

a
b
参数。

我没有费心翻转 y 数据,因为它会造成混乱。

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

# 1. Data set: 
x_data = np.array([130, 125, 120, 115, 110, 105, 100, 95, 90, 85, 80, 75, 70, 65, 60, 55
, 50, 45, 40,
35, 30, 25])
y_data = np.array([81, 81, 80.5, 79, 77.5, 76, 74.5, 71.5, 68.5, 67, 64, 59.5, 55, 48.5,
 44, 42.5, 42,
41.5, 41.5, 41, 41, 41])

# 3. Sigmoid function defined: 
def sigmoid(x, U, k):
    a = 1
    b = 81 
    return (U / (1 + np.exp(-k * (x - 77.5))))**a + b

p0 = [-40, -0.1]
x_fit = np.linspace(25, 130, 101)
y_init = sigmoid(x_fit, *p0)

popt, pcov = curve_fit(sigmoid, x_data, y_data, p0, maxfev = 10000)
y_est = sigmoid(x_data, *popt)
mse = np.mean((y_data - y_est) ** 2)
print(f"Mean-squared error: {mse}")

# 4. Sigmoid fit to data:
y_fit = sigmoid(x_fit, *popt)

# 5. Plot data and sigmoid fit:
plt.plot(x_data, y_data, marker='o', linestyle='', color='b', label='Data')
plt.plot(x_fit, y_init, color='r', label='Initial guess')
plt.plot(x_fit, y_fit, color='g', label='Sigmoid Fit')
plt.xlabel('Temperature (°C)')
plt.ylabel('Length (mm)')
plt.title('Sigmoid Fit for Contraction Data')
plt.gca().invert_yaxis()  # ...Invert y-axis to start with highest value at the top
plt.legend()
plt.grid(True)
plt.show()

输出:

Mean-squared error: 1.7366871891164086

© www.soinside.com 2019 - 2024. All rights reserved.