Python实现Logistic Regression遇问题:梯度下降异常与scipy.opt报错
Andrew Ng机器学习课程Logistic Regression实现问题解答
一、梯度下降参数更新异常解惑
手动实现梯度下降法更新参数时,不同学习率(alpha)下成本变化表现异常:
- alpha=0.0001、迭代400000次:成本曲线缓慢下降,最终分类结果可接受
- alpha=0.01、迭代200000次:成本曲线出现震荡波动,但最终分类结果依然达标
异常原因分析
- alpha=0.0001的情况:学习率过小,参数更新步长不足,需要极多次迭代才能逐步收敛到成本函数最小值附近,因此成本曲线下降缓慢,但整体趋势正确,最终能得到合理结果。
- alpha=0.01的情况:学习率偏大,每次参数更新步长超过最优下降方向,导致在最小值区域来回震荡。不过梯度下降的特性决定了即使震荡,参数也会在最小值范围内波动,因此最终结果仍可接受。
建议:尝试学习率衰减策略(如每次迭代后alpha乘以0.99),或测试多个alpha值(比如0.001),选择既能快速收敛又无过度震荡的学习率。
二、scipy.opt函数调用维度不匹配问题解决
问题代码
import numpy as np from scipy import opt m,n=data.shape X=data[:,0:n-1] y=data[:,-1:] theta=np.array([[0] for i in range(n)],dtype=np.float64) print(X.shape,y.shape,theta.shape) # OUT:(100, 2) (100, 1) (3, 1) X=np.concatenate((np.array([[1] for i in range(m)]),X),axis=1) def sigmoid(z): return 1/(1+np.exp(-z)) def h(X,theta): return sigmoid(X@theta) def calculate_cost(X,y,theta): first=-y.T @ np.log(h(X,theta)+1e-5) second=(1-y).T@np.log(1-h(X,theta)+1e-5) return 1/m*(first-second)[0][0] def gradient(X,y,theta): return 1/m*(X.T@(h(X,theta)-y)).T result = opt.fmin_tnc(func=calculate_cost, x0=theta, fprime=gradient, args=(X, y))
报错信息
Cell In[5], line 4, in h(X, theta) 3 def h(X,theta): ----> 4 return sigmoid(X@theta) ValueError: matmul: Input operand 1 has a mismatch in its core dimension 0, with gufunc signature (n?,k),(k,m?)->(n?,m?) (size 100 is different from 3)
问题根源
scipy.optimize.fmin_tnc会将输入的x0(即theta)自动转换为一维数组,但你的代码中theta初始是(3,1)的二维数组。函数调用时theta被转为(3,)的一维数组,此时X((100,3))与theta的矩阵乘法维度不匹配,导致报错。
解决方案
修改函数以兼容一维theta,同时调整维度匹配逻辑:
修正后的代码
import numpy as np from scipy import optimize as opt m,n=data.shape X=data[:,0:n-1] y=data[:,-1:] # 初始theta设为一维数组,或在函数内转换维度 theta=np.zeros(n, dtype=np.float64) print(X.shape,y.shape,theta.shape) # OUT:(100, 2) (100, 1) (3,) X=np.concatenate((np.ones((m,1)),X),axis=1) def sigmoid(z): return 1/(1+np.exp(-z)) def h(X,theta): # 将theta转为二维列向量,确保矩阵乘法维度匹配 theta = theta.reshape(-1,1) return sigmoid(X@theta) def calculate_cost(X,y,theta): theta = theta.reshape(-1,1) h_val = h(X,theta) first=-y.T @ np.log(h_val+1e-5) second=(1-y).T@np.log(1-h_val+1e-5) return 1/m*(first-second)[0][0] def gradient(X,y,theta): theta = theta.reshape(-1,1) grad = 1/m*(X.T@(h(X,theta)-y)) # 将梯度转为一维数组,符合fmin_tnc的输出要求 return grad.flatten() result = opt.fmin_tnc(func=calculate_cost, x0=theta, fprime=gradient, args=(X, y))
关键修改点
- theta初始形状:将
theta初始化为一维数组np.zeros(n, dtype=np.float64),减少后续转换步骤; - 函数内维度兼容:在
h、calculate_cost、gradient函数中,先将theta转为二维列向量,确保X@theta的维度匹配(X(100,3) × theta(3,1) = (100,1)); - 梯度格式适配:
gradient函数返回一维数组,用grad.flatten()将二维梯度转为一维,满足fmin_tnc的输入要求。
内容的提问来源于stack exchange,提问作者Krism
相关产品推荐
相关产品推荐

