Python多变量曲线拟合(线性/非线性)触发IndexError求助
多变量曲线拟合(多元线性+Sigmoid)的IndexError解决
问题背景
需要用Python实现多变量函数拟合,包含多元线性拟合和非线性Sigmoid拟合,数据处理后得到包含Area、Room、Parking、Warehouse、Elevator、Address、Price的数值型DataFrame,拟合公式如下:
- 多元线性拟合:
Y = aX1 + bX2 +cX3 + dX4 + gX5 + hX6 - 非线性Sigmoid拟合:
Y = 1 / (1 + e^beta1(X - beta2)),其中X为aX1 + bX2 +cX3 + dX4 + gX5 + hX6
当前调用curve_fit(Multiple_Sigmoid_f, X_train, Y_real_train)时触发IndexError: invalid index to scalar variable,错误栈指向拟合函数中对Numeric_HDS的索引操作。
错误原因
- 函数参数顺序不符合
curve_fit要求:curve_fit要求拟合函数的第一个参数是输入数据xdata,后续是待拟合参数,原函数把待拟合参数放在最前面、输入数据放在最后,导致参数传递混乱。 - 数据维度处理错误:
X_train被转置为(6, N)形状,但函数内按行索引提取特征,与实际数据维度不匹配;同时curve_fit会将xdata作为单个参数传入,导致函数内对其索引时出现标量索引错误。
修正方案
1. 重构拟合函数的参数顺序与数据处理逻辑
curve_fit要求函数签名为func(xdata, *params),其中xdata是(N,6)形状的特征矩阵(N为样本数),*params是所有待拟合参数。
多元线性拟合函数
def Multiple_f(xdata, theta1, theta2, theta3, theta4, theta5, theta6): # xdata为(N,6)数组,每行对应一个样本的6个特征 Area = xdata[:, 0] Room = xdata[:, 1] Parking = xdata[:, 2] Warehouse = xdata[:, 3] Elevator = xdata[:, 4] Address = xdata[:, 5] Y = theta1*Area + theta2*Room + theta3*Parking + theta4*Warehouse + theta5*Elevator + theta6*Address return Y
Sigmoid拟合函数
import numpy as np def Multiple_Sigmoid_f(xdata, beta1, beta2, theta1, theta2, theta3, theta4, theta5, theta6): Area = xdata[:, 0] Room = xdata[:, 1] Parking = xdata[:, 2] Warehouse = xdata[:, 3] Elevator = xdata[:, 4] Address = xdata[:, 5] X = theta1*Area + theta2*Room + theta3*Parking + theta4*Warehouse + theta5*Elevator + theta6*Address Y = 1 / (1 + np.exp(beta1*(X - beta2))) return Y
2. 修正训练集特征维度
取消对特征矩阵的转置操作,保持(N,6)的样本-特征结构:
# 提取训练集特征,保持(N,6)形状 X_train = np.asanyarray(train[["Area","Room","Parking","Warehouse","Elevator","Address"]]) Y_real_train = np.asanyarray(train["Price"])
3. 正确调用curve_fit
必须提供初始参数p0帮助拟合算法收敛,尤其是Sigmoid拟合,初始值对结果影响较大:
多元线性拟合调用
from scipy.optimize import curve_fit # 线性拟合初始参数设为全1 p0_linear = [1, 1, 1, 1, 1, 1] popt_linear, pcov_linear = curve_fit(Multiple_f, X_train, Y_real_train, p0=p0_linear) print("线性拟合参数:", popt_linear)
Sigmoid拟合调用
# 基于线性拟合结果生成Sigmoid初始参数,提升收敛性 X_linear = (popt_linear[0]*X_train[:,0] + popt_linear[1]*X_train[:,1] + popt_linear[2]*X_train[:,2] + popt_linear[3]*X_train[:,3] + popt_linear[4]*X_train[:,4] + popt_linear[5]*X_train[:,5]) p0_sigmoid = [0.0001, np.mean(X_linear)] + list(popt_linear) popt_sigmoid, pcov_sigmoid = curve_fit(Multiple_Sigmoid_f, X_train, Y_real_train, p0=p0_sigmoid) print("Sigmoid拟合参数:", popt_sigmoid)
4. 测试拟合效果
用测试集验证拟合结果:
X_test = np.asanyarray(test[["Area","Room","Parking","Warehouse","Elevator","Address"]]) Y_real_test = np.asanyarray(test["Price"]) # 线性拟合预测 Y_pred_linear = Multiple_f(X_test, *popt_linear) # Sigmoid拟合预测 Y_pred_sigmoid = Multiple_Sigmoid_f(X_test, *popt_sigmoid) # 打印前5组对比结果 print("真实值 | 线性预测值 | Sigmoid预测值") for y_true, y_lin, y_sig in zip(Y_real_test[:5], Y_pred_linear[:5], Y_pred_sigmoid[:5]): print(f"{y_true:.2f} | {y_lin:.2f} | {y_sig:.2f}")
关键优化说明
- Sigmoid函数的值域是(0,1),但原始Price为较大数值(20000-79000),直接拟合会导致效果极差。建议先对Price做归一化处理(如除以最大值缩放到(0,1)区间),拟合后再反归一化得到实际价格:
# 归一化训练集标签 Y_max = Y_real_train.max() Y_train_norm = Y_real_train / Y_max # 用归一化数据拟合Sigmoid popt_sigmoid, pcov_sigmoid = curve_fit(Multiple_Sigmoid_f, X_train, Y_train_norm, p0=p0_sigmoid) # 预测后反归一化得到实际价格 Y_pred_sigmoid = Multiple_Sigmoid_f(X_test, *popt_sigmoid) * Y_max
内容的提问来源于stack exchange,提问作者Alireza Rahimi
相关产品推荐
相关产品推荐

