Python手写机器学习的"线性回归"算法
我们只考虑如何手写实现,不考虑效果好不好,和统计学上的使用方法,主要是培养代码算法实现思想,如果您想学习线性回归知识,请看我博客的专门有写统计分析------回归分析文章
线性回归
您将看到一个 LinearRegression 类模板。实现与上面描述的模型相对应的 .fit() 和 .predict() 方法。对于这个任务,您只能使用 numpy 库。使用任何其他库都会导致自动化系统检查任务时出现错误。我们还要求您不要更改类的名称和指定的方法,这也会导致错误。你可以将自己的方法添加到类中。
获得的模型系数应存储在.coef_ 字段中。
LinearRegression 类模板如下所示:
python
import numpy as np
np.random.seed(42)
class LinearRegression:
def __init__(self, **kwargs):
self.coef_ = None
pass
def fit(self, x: np.array, y: np.array):
# TODO:为 LinearRegression 类编写一个 .fit() 方法
pass
def predict(self, x: np.array):
# TODO:编写 LinearRegression 类的 .predict(x) 方法
pass
注意:
- 不要忘记添加单位列(这是添加偏移量所需要的)。
- 在使用各种矩阵运算时,不要忘记检查操作数矩阵维数的对应关系。不要忘记在需要的地方转调。
- 注意所提出的模板中的字段名称(self.coef_)、方法(fit、predict)及其参数的顺序(参见上文)。
代码
python
import numpy as np
np.random.seed(42)
class LinearRegression:
def __init__(self, **kwargs):
self.coef_ = None
pass
def fit(self, x: np.array, y: np.array):
# 添加一列全为1的偏置项
x = np.concatenate([np.ones((x.shape[0], 1)), x], axis=1)
# 使用最小二乘法计算系数
self.coef_ = np.linalg.inv(x.T @ x) @ x.T @ y
return self
def predict(self, x: np.array):
# 添加一列全为1的偏置项
x = np.concatenate([np.ones((x.shape[0], 1)), x], axis=1)
# 根据计算出的系数进行预测
y_pred = x @ self.coef_
return y_pred
解析
这段代码实现了一个简单的线性回归模型类 LinearRegression
,它包含了两个核心方法:fit
用于训练模型,计算模型的系数;predict
用于使用训练好的模型对新的数据进行预测。
python
import numpy as np
np.random.seed(42)
import numpy as np
:导入numpy
库,它是 Python 中用于科学计算的基础库,提供了高效的数组操作和数学函数。np.random.seed(42)
:设置随机数种子,确保代码的可重复性。无论何时运行代码,生成的随机数序列都是相同的。
python
class LinearRegression:
def __init__(self, **kwargs):
self.coef_ = None
pass
class LinearRegression:
:定义一个名为LinearRegression
的类,用于实现线性回归模型。def __init__(self, **kwargs):
:类的构造函数,**kwargs
表示可以接受任意数量的关键字参数,但在这个实现中并没有使用这些参数。self.coef_ = None
:初始化一个实例变量self.coef_
,用于存储训练得到的模型系数。初始值为None
,表示还没有进行训练。
python
def fit(self, x: np.array, y: np.array):
# 添加一列全为1的偏置项
x = np.concatenate([np.ones((x.shape[0], 1)), x], axis=1)
# 使用最小二乘法计算系数
self.coef_ = np.linalg.inv(x.T @ x) @ x.T @ y
return self
def fit(self, x: np.array, y: np.array):
:定义fit
方法,用于训练线性回归模型。x
是输入的特征矩阵,y
是对应的目标值向量。x = np.concatenate([np.ones((x.shape[0], 1)), x], axis=1)
:在特征矩阵x
的左侧添加一列全为 1 的向量。这是为了引入偏置项(截距),使得线性回归模型可以表示为 y = θ 0 + θ 1 x 1 + θ 2 x 2 + ⋯ + θ n x n y = \theta_0 + \theta_1x_1 + \theta_2x_2 + \cdots + \theta_nx_n y=θ0+θ1x1+θ2x2+⋯+θnxn 的形式,其中 θ 0 \theta_0 θ0 就是偏置项。np.ones((x.shape[0], 1))
创建了一个形状为(样本数量, 1)
的全 1 矩阵,np.concatenate
函数将其与原特征矩阵x
按列拼接。self.coef_ = np.linalg.inv(x.T @ x) @ x.T @ y
:使用最小二乘法来计算模型的系数。最小二乘法的目标是找到一组系数 θ \theta θ,使得预测值与真实值之间的误差平方和最小。具体公式为 θ = ( X T X ) − 1 X T y \theta = (X^T X)^{-1} X^T y θ=(XTX)−1XTy,其中 X X X 是添加了偏置项的特征矩阵, y y y 是目标值向量。np.linalg.inv
函数用于计算矩阵的逆,@
是numpy
中用于矩阵乘法的运算符。return self
:返回当前对象实例,这样可以实现方法的链式调用。
python
def predict(self, x: np.array):
# 添加一列全为1的偏置项
x = np.concatenate([np.ones((x.shape[0], 1)), x], axis=1)
# 根据计算出的系数进行预测
y_pred = x @ self.coef_
return y_pred
def predict(self, x: np.array):
:定义predict
方法,用于使用训练好的模型对新的数据进行预测。x
是输入的特征矩阵。x = np.concatenate([np.ones((x.shape[0], 1)), x], axis=1)
:同样在输入的特征矩阵x
左侧添加一列全为 1 的向量,以引入偏置项,保证与训练时的特征矩阵格式一致。y_pred = x @ self.coef_
:使用训练得到的系数self.coef_
对输入数据进行预测。通过矩阵乘法 y p r e d = X θ y_{pred} = X \theta ypred=Xθ 计算预测值,其中 X X X 是添加了偏置项的特征矩阵, θ \theta θ 是训练得到的系数向量。return y_pred
:返回预测结果向量。
使用示例
输入和输出数据的示例:
python
from sklearn.datasets import load_diabetes
from sklearn.model_selection import train_test_split
X, y = load_diabetes(return_X_y=True) # 此数据集已预处理
print(X[:5])
输出:
python
# 将数据集分为训练和测试部分
X_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.3, shuffle=True, random_state=42)
python
# 创建你的类的一个对象并对其进行训练
LinReg = LinearRegression()
LinReg.fit(X_train, y_train)
python
# 在测试数据集上进行预测
predictions = LinReg.predict(x_test)
predictions
输出:
python
# 预测质量评估
from sklearn.metrics import r2_score
r2_score(y_test, predictions)
输出:0.47728971643226203