简单线性回归(一个特征)的思路
思路:
假设 , 基本符合 线性的关系,所以找到一条直线 y = ax+b 最大程度的拟合 , ;
这样当给出新的 时,就可以预测出 = a +b ;
目标: x 和 y 都是已知的 , 需要求出 a:斜率 、b:截距。
方法:
最小二乘法(最小二乘法(又称最小平方法)是一种数学优化技术。它通过最小化误差的平方和寻找数据的最佳函数匹配。)
误差的平方 : ; 考虑所有的样本 : 使 尽可能小;
将 = a +b 带进 上面的式子 , 目标:找到 a 和 b 使得 尽可能小 ; 这个函数称为损失函数。
最小二乘法:
称这个损失函数为 ,目标是使这个函数 最小 ;
对 求导, 根据导数的定义,当
就是极值的地方。
根据推到得到,当处于极值时:
编写一个简单线性回归的函数算法
通过传入 x_train ,y_train ,求出 a 和 b ; 并且可以当给定新的 x (向量)时候,预测出新的 y。
import numpy as np
class SimpleLinearRegression1:
def __init__(self):
'''初始化 Simple Linear Regression 模型'''
self.a_ = None
self.b_ = None
def fit(self , x_train , y_train):
assert x_train.ndim ==1
assert x_train.shape[0] == y_train.shape[0]
num = 0
d = 0
for x_i ,y_i in zip(x_train,y_train):
num += (x_i -np.mean(x_train)) *(y_i -np.mean(y_train))
d += (x_i - np.mean(x_train))**2
self.a_ = num/d
self.b_ = np.mean(y_train) - self.a_ *np.mean(x_train)
return self
def predict(self ,x_predict ):
assert x_predict.ndim == 1
assert self.a_ is not None and self.b_ is not None
return np.array([self._predict(x) for x in x_predict])
def _predict(self,x_single):
return self.a_ *x_single +self.b_
def __repr__(self):
return "SimpleLinearRegression1()"
向量化算法
在上面的算法中,求 a 的方法是使用 for 循环;可以改进为使用 向量的点乘 来加快算法的运算速度。
点乘:两个向量的点乘 ,每个对应的元素 相乘 再 相加。
观察a 的分子分母 ,可以发现分子分母实际都是 两个向量 点乘 的结果 ;
只需要改动 原代码中 fit 部分即可,其余代码保持不变:
def fit(self , x_train , y_train):
assert x_train.ndim ==1
assert x_train.shape[0] == y_train.shape[0]
x_mean = np.mean(x_train)
y_mean = np.mean(y_train)
num = (x_train-x_mean).dot(y_train-y_mean)
d = (x_train-x_mean).dot(x_train-x_mean)
self.a_ = num/d
self.b_ = y_mean - self.a_ *x_mean
return self