机器学习代码实现1:线性回归和岭回归

这一专题的内容主要是我在进行统计机器学习的算法的代码实践的过程中的一些记录,包括公式的推导,算法的实现与数据集的实验结果。

这部分工作我比较早之前就已经开始做了,现在刚好趁此机会整理一下之前写过的所有小demo,汇总成一个完成的库

1.线性回归模型

  • 线性回归模型是最简单的一种线性模型,模型的形式就是:

  • 我们可以通过对原本的输入向量x扩增一个为1的维度将参数统一成一个参数,即模型变成了

  • 这里的是原本两个参数合并之后的而其损失函数的形式是残差平方损失RSS

  • 我们很容易就可以通过求导得到线性回归模型的关于的梯度

这样一来我们就可以通过梯度下降的方式来训练参数,可以用下面的公式表示[大概是这样,我也没有]:

  • 但实际上线性模型的参数可以直接求解出,即:

2.线性回归的编程实现

  • 具体代码中的参数的形式可能和上面的公式推导略有区别,我们实现了一个LinearRegression的类,包含fit,predict和loss三个主要的方法,fit方法就是求解线性模型的过程,这里我们直接使用了正规方程来解
1
2
3
4
5
6
7
8
9
class LinearRegression:
def fit(self, X: np.ndarray, y: np.ndarray) -> float:
N, D = X.shape
# 将每个样本的特征增加一个维度,用1表示,使得bias和weight可以一起计算
# 这里在输入的样本矩阵X末尾增加一列来给每个样本的特征向量增加一个维度
# 现在X变成了N*(D+1)维的矩阵了
expand_X = np.column_stack((X, np.ones((N, 1))))
self.w = np.matmul(np.matmul(np.linalg.inv(np.matmul(expand_X.T, expand_X)), expand_X.T), y)
return self.loss(X, y)
  • predict实际上就是将输入的矩阵X放到模型中进行计算得到对应的结果,loss给出了损失函数的计算方式:
1
2
3
4
5
6
7
8
9
10
def loss(self, X: np.ndarray, y: np.ndarray):
"""
线性回归模型使用的是RSS损失函数
:param X:需要预测的特征矩阵X,维度是N*D
:param y:标签label
:return:
"""
delta = y - self.predict(X)
total_loss = np.sum(delta ** 2) / X.shape[0]
return total_loss

3.岭回归Ridge Regression与代码实现

  • 岭回归实际上就是一种使用了正则项的线性回归模型,也就是在损失函数上加上了正则项来控制参数的规模,即:

  • 因此最终的模型的正规方程就变成了:

  • 这里的是待定的正则项参数,可以根据情况选定,岭回归模型训练的具体代码如下
1
2
3
4
5
6
7
8
9
class RidgeRegression:
def fit(self, X: np.ndarray, y: np.ndarray):
N, D = X.shape
I = np.identity(D + 1)
I[D][D] = 0
expand_X = np.column_stack((X, np.ones((N, 1))))
self.W = np.matmul(np.matmul(np.linalg.inv(np.matmul(expand_X.T, expand_X)
+ self.reg * I), expand_X.T), y)
return self.loss(X, y)

4.数据集实验

  • 这里使用了随机生成的二位数据点来对线性模型进行测试,测试结果如下:
线性模型测试结果
  • 岭回归也使用同样的代码进行测试。