自定义LinearModel类predict方法报错:矩阵广播不匹配求助
解决自定义LinearModel线性回归类的predict方法广播错误
我手动实现了一个不依赖Sklearn的线性回归类LinearModel,但在调用predict方法时出现矩阵广播错误,报错信息如下:
ValueError: operands could not be broadcast together with shapes (4,3) (2,)
初始代码
import numpy as np class LinearModel: def __init__(self, X, y): self.X = X self.y = y # X columns of 1s appended on its left, X = np.vstack((np.ones((X.shape[0], )), X.T)).T if len(self.X)!=len(y): raise ("they are not similar") def fit(self): # stores this coefficient vector in the object. Xt = np.transpose(X) XtX = np.dot(Xt,X) Xty = np.dot(Xt,y) beta = np.linalg.solve(XtX,Xty) self.fit = beta def coef(self): # raise an error if called before the model has been fitted if not self.fit: raise ValueError("Need to call the fit function first") #returns βˆ. return self.fit def predict(self,X0=None): # Takes an optional argument X0 if not self.fit: raise ValueError("Need to call the fit function first") if X0==None: X0 = X X0 = np.vstack((np.ones((X0.shape[0], )), X0.T)).T # where X0 is X0 with column of 1s added on its left. prediction = self.fit * X0 # method should return X0 * βˆ return prediction X = np.array([[-1.34164079, -1.25675744], [-0.4472136, -0.48336824], [0.4472136, 0.29002095], [1.34164079, 1.45010473]]) y = np.array([1, 3, 4, 6]) model = LinearModel(X, y) model.fit() print(model.coef()) print(model.predict())
修改后的代码
import numpy as np class LinearModel: def __init__(self, X, y): self.X = X self.y = y #X columns of 1s appended on its left, X = np.vstack((np.ones((X.shape[0], )), X.T)).T if len(self.X)!=len(y): raise ("they are not similar") self._is_fitted : bool = False def fit(self): Xt = np.transpose(X) XtX = np.dot(Xt,X) Xty = np.dot(Xt,y) beta = np.linalg.solve(XtX,Xty) beta_array = np.array(beta) self.fit = beta_array self._is_fitted = True def coef(self): # raise an error if called before the model has been fitted if not self._is_fitted: raise ValueError("Need to call the fit function first") #returns βˆ return self.fit def predict(self,X0=None): # Takes an optional argument X0 if not self._is_fitted: raise ValueError("Need to call the fit function first") if X0==None: X0 = X X0 = np.vstack((np.ones((X0.shape[0], )), X0.T)).T # where X0 is X0 with column of 1s added on its left. prediction = np.multiply(X0, self.fit) # method should return X0 * βˆ return prediction X = np.array([[-1.34164079, -1.25675744], [-0.4472136, -0.48336824], [0.4472136, 0.29002095], [1.34164079, 1.45010473]]) y = np.array([1, 3, 4, 6]) model = LinearModel(X, y) model.fit() print(model.coef()) print(model.predict())
错误原因分析
- 变量作用域错误:
__init__中处理后的带截距的X是局部变量,fit方法中直接使用的X实际是全局的原始特征数组(未加截距),导致计算出的beta维度为(2,),而predict中生成的X0是加了截距的(4,3)数组,两者形状不匹配,触发广播错误。 - 矩阵乘法方式错误:
predict中使用np.multiply(元素级相乘)而非矩阵点乘,线性回归的预测应该是带截距的特征矩阵与系数向量做矩阵乘法,得到每个样本的预测值。 - 属性命名冲突:将系数赋值给
self.fit,覆盖了类的fit方法,属于不合理命名。
修复方案
修改后的完整代码如下:
import numpy as np class LinearModel: def __init__(self, X, y): self.X = X self.y = y # 保存带截距的特征矩阵为实例变量 self.X_with_intercept = np.vstack((np.ones((X.shape[0], )), X.T)).T if len(self.X) != len(y): raise ValueError("Feature and target lengths do not match") self._is_fitted = False self.beta = None # 用beta存储系数,避免覆盖fit方法 def fit(self): # 使用实例中的带截距特征矩阵计算系数 Xt = self.X_with_intercept.T XtX = np.dot(Xt, self.X_with_intercept) Xty = np.dot(Xt, self.y) self.beta = np.linalg.solve(XtX, Xty) self._is_fitted = True def coef(self): if not self._is_fitted: raise ValueError("Need to call the fit function first") return self.beta def predict(self, X0=None): if not self._is_fitted: raise ValueError("Need to call the fit function first") if X0 is None: X0 = self.X # 对输入的X0添加截距列 X0_with_intercept = np.vstack((np.ones((X0.shape[0], )), X0.T)).T # 使用矩阵点乘计算预测值,X0_with_intercept (n,3) @ beta (3,) -> (n,) prediction = np.dot(X0_with_intercept, self.beta) return prediction X = np.array([[-1.34164079, -1.25675744], [-0.4472136, -0.48336824], [0.4472136, 0.29002095], [1.34164079, 1.45010473]]) y = np.array([1, 3, 4, 6]) model = LinearModel(X, y) model.fit() print(model.coef()) print(model.predict())
修复要点说明
- 将带截距的特征矩阵保存为实例变量
self.X_with_intercept,确保fit方法使用正确的特征矩阵计算系数,得到维度为(3,)的系数向量(截距+两个特征系数)。 - 使用
self.beta存储系数,避免与fit方法名冲突。 predict方法中使用np.dot(或@运算符)进行矩阵点乘,确保形状匹配,得到正确的预测值数组(形状为(4,))。- 修正异常抛出方式,使用
ValueError而非直接抛出字符串。
内容的提问来源于stack exchange,提问作者Dome
相关产品推荐
相关产品推荐

