线性回归分为:
- 简单线性回归:特征数量只有一个。
- 多元线性回归:特征数量有多个。
1 简单线性回归
寻找一条直线,最大程度的拟合样本特征与样本输出标记之间的关系。
预测值为: ,真值为
我们希望的差距尽量小
考虑所有样本:找到a和b,使 尽可能小
损失函数定义:用来度量预测错误的程度。 近乎所有参数学习算法,都是通过分析问题,确定问题的损失函数,通过最优化损失函数,使得预测错误的程度最小,来获得机器学习的模型。
1.1 最小二乘法
求a,b的过程,就是对a,b分别求导,令极值为0,求方程组的过程。
先给出结论:
公式编辑太麻烦,还是直接上图看推导过程吧,
此时求得 ,将其带入到对a求导中
此时根据红框里的等式进行变换,最终得到下面的式子
那么化简成这样的意义是什么呢?有什么好处呢?
答:向量化运算 使用for循环的效率是很低的,用向量的运算,效率会大大提高(相差好几十倍)。
1.2 代码起飞
import numpy as np
class SimpleLinearRegression:
def __init__(self):
"""初始化Simple Linear Regression模型"""
self.a_ = None
self.b_ = None
def fit(self, x_train, y_train):
"""根据训练数据集x_train, y_train训练Simple Linear Regression模型"""
assert x_train.ndim == 1, \
"简单线性回归,只有一维"
assert len(x_train) == len(y_train)
x_mean = np.mean(x_train)
y_mean = np.mean(y_train)
# 公式,用向量点积
self.a_ = (x_train - x_mean).dot(y_train - y_mean) / (x_train - x_mean).dot(x_train - x_mean)
self.b_ = y_mean - self.a_ * x_mean
return self
def predict(self, x_predict):
"""给定待预测数据集x_predict,返回表示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):
"""给定单个待预测数据x,返回x的预测结果值"""
return self.a_ * x_single + self.b_
def score(self, x_test, y_test):
"""根据测试数据集 x_test 和 y_test 确定当前模型的准确度,使用的是R Square衡量"""
y_predict = self.predict(x_test)
return r2_score(y_test, y_predict)
def __repr__(self):
return "SimpleLinearRegression()"
复制代码
2回归算法的评价
2.1 三个指标
衡量标准: 但是如果不同的样本个数相比,会有问题,因此以下改进
- 均方误差 MSE (Mean Squared Error)
还有量纲的问题,假如房价是万元,MSE的值是万^2,进行改进
- 均方根误差 RMSE (Root Mean Squared Error)
- 平均绝对误差 MAE (Mean Absolute Error)
那么RMSE与MAE区别是什么呢?
如果错误值非常大,例如两个样本的差距是100的话,RMSE就扩大到10000的差距了,因此RMSE 能放大 样本中预测结果与真实结果之间较大差异 的趋势,而MAE是没有的。因此从某种程度上讲,让RMSE的值更小相对意义更大,表示样本中错误值最大的比较小。
2.2 最好的线性回归评价指标 R Square
问题引入:假如使用RMSE、MAE预测房价误差是5万元,预测学生成绩误差是10分,那我们得到的模型是预测房价好呢还是学生成绩好呢,我们无法判断,这也是他们的局限性。
从而引入:
使用我们训练出来的模型产生的错误
使用预测产生的错误(也称基准模型)
-
越大越好。当我们预测模型不犯任何错误,得到最大值
-
当我们的模型等于基准模型时,
-
如果,说明我们学习到的模型还不如基准模型,预测的还不如不预测,此时,很有可能我们的数据不存在任何线性关系。
还可以将进行整理下,如下:
2.3 代码
import numpy as np
from math import sqrt
def mean_squared_error(y_true, y_predict):
"""MSE"""
assert len(y_true) == len(y_predict)
return np.sum((y_true - y_predict)**2) / len(y_true)
def root_mean_squared_error(y_true, y_predict):
"""RMSE"""
return sqrt(mean_squared_error(y_true, y_predict))
def mean_absolute_error(y_true, y_predict):
"""MAE"""
assert len(y_true) == len(y_predict)
return np.sum(np.absolute(y_true - y_predict)) / len(y_true)
def r2_score(y_true, y_predict):
"""R Square"""
return 1 - mean_squared_error(y_true, y_predict)/np.var(y_true)
复制代码
3 多元线性回归
:第i个样本的n个特征
预测值:
目标:找到使尽可能小
3.1 简单变换:
其中令恒等于1,虚拟的第0个特征,插入到n个特征的第一列
可以换成向量的点积,写成
上面是第i个向量的预测结果,而所有向量预测结果可以用矩阵表示
的第一列是插入的,虚拟的第0个特征
3.2 推导过程
那么如何求呢,和简单线性回归相似,对所有参数进行求导,令极值=0。
先给结论:
推到过程手写了,请看图,不忍直视的请略过
- 问题:时间复杂度高:
- 优点:不需要对数据做归一化处理
3.3 代码
,
其中为截距 是系数,因为在系数部分,每一个值对应样本的一个特征,可以看到每一个特征的贡献是如何的
import numpy as np
class LinearRegression:
def __init__(self):
"""初始化Linear Regression模型"""
self.coef_ = None # 系数
self.intercept_ = None # 截距
self._theta = None # θ
def fit_normal(self, X_train, y_train):
"""根据训练数据集X_train, y_train训练Linear Regression模型"""
assert X_train.shape[0] == y_train.shape[0]
# 在X_train矩阵第一列增加全为1的列
X_b = np.hstack([np.ones((len(X_train), 1)), X_train])
# 公式θ = (X_T·X)﹣¹·X_T·Y
self._theta = np.linalg.inv(X_b.T.dot(X_b)).dot(X_b.T).dot(y_train)
self.intercept_ = self._theta[0]
self.coef_ = self._theta[1:]
return self
def predict(self, X_predict):
"""给定待预测数据集X_predict,返回表示X_predict的结果向量"""
assert self.intercept_ is not None and self.coef_ is not None
assert X_predict.shape[1] == len(self.coef_)
X_b = np.hstack([np.ones((len(X_predict), 1)), X_predict])
return X_b.dot(self._theta)
def score(self, X_test, y_test):
"""确定当前模型的准确度,使用的是R Square衡量"""
y_predict = self.predict(X_test)
return r2_score(y_test, y_predict)
def __repr__(self):
return "LinearRegression()"
复制代码
小结
-
典型的参数学习 线性回归获取的系数,具有可解释性,可以看到每个系数对结果所占的比重。
-
只能解决回归问题 对比kNN:既可以解决分类问题,也可以解决回归问题
-
对数据有假设:假设存在线性 对比kNN,对数据没有假设
-
如果确实存在线性关系,线性回归会比kNN强不少
-
问题:时间复杂度高,解决方案-梯度下降法
下章预告:梯度下降法
声明:此文章为本人学习笔记,课程来源于慕课网:python3入门机器学习经典算法与应用。在此也感谢bobo老师精妙的讲解。
如果您觉得有用,欢迎关注我的公众号,我会不定期发布自己的学习笔记、AI资料、以及感悟,欢迎留言,与大家一起探索AI之路。