本文代码,见github:
一, 简单线性回归原理
1.线性回归算法的优点。
解决回归问题;
思想简单,容易实现;
许多强大的非线性模型的基础;
结果具有很好的可解释性;
蕴含机器学习中的很多重要的思想;
2.分类问题和回归问题的不同点(为了可视化,我们以二维为例)
分类问题(左图),x,y均表示特征
回归问题(右图),x表示特征,y表示标记(分类问题中标记(target)是离散值,回归问题中,target是连续值,比如:房价)。
上图中只有一个特征,称为简单的线性回归;若有两个或多个特征,需要在三维及更高的维度,称为多元线性回归。
3.简单线性回归原理的介绍
(1)式不同的样本点可能会相互抵消(如上图:在红线左侧的点的真值和估计值的差值小于0,在红线左侧的点的真值和估计值的差值大于于0,最后所有样本真值和估计值的差值相加会产生抵消的情况,不能很好的知道是否预测的准确)
(2)式不是凸优化问题,存在不可导点(因为我们要计算函数最小值,最终转化为求导=0,寻求最小点)
目标:,而,所以找到a和b,使得最小。
转化为最小二乘问题:最小化误差的平方
最小二乘问题的原理,推导:见另一篇博客: 一些基本 的数学知识 2.最小二乘问题
这样我们就可以拟合出一条直线来近似的表示feature和target的线性关系:即
4. 根据上述原理,进行简单的代码实现
见 SimpleLinearRegression.ipynb (github地址在本文开始)
二. 衡量线性回归的指标
1. MSE,RMSE,MAE,R_Square, accuracy_score
但是在上述衡量线性回归的指标中,误差总是与预测数据的大小有关,也就是说,用上述的衡量误差方法,在用线性回归预测学生成绩和房价这两个场景中,显然是无法比较谁的预测更准确一点。即没有统一化的标准。
对R_Square进一步进行分析
将R_Square 变形为我们熟悉的形式,也方便编程的实现
一般, sklearn中的score 用的就是R_square
accuracy_score
np.sum(y_true == y_predict) / len(y_true)
2加载波士顿房价数据.对上述指标程序的实现。
具体程序见:MSE_RMSE_MAE_R2.ipynb
三. 多元线性回归
1.多元线性回归的原理及参数的求解
多元线性回归,x不再是表示某个样本的一个特征,而是表示某个样本多个特征组成的向量
多元线性回归的目标函数(同简单线性回归): m 表示样本的总数
(1),即找到,使得目标函数最小。
令 ,为系数(coefficients), 为截距(intercept).
,其中,。
(1) 式
扩展到多个样本,写成矩阵的形式:
得(2)为多元线性回归的正规方程解,
但是其时间复杂度高
2.多元线性回归的实现
见github代码:LinearRegression_KNeighborsRegressor.ipynb
1.(1)加载波士顿的房价数据,将数据分为训练数据和测试数据
(2)根据公式二计算出模型参数
(3)根据得到的模型参数,预测测试数据的房价
(4)同简单线性回归一样,用R_square衡量y_predict(预测值)预测y_test(测试集房价的真实值)准确性。
2 封装多元线性回归算法到本地文件LinearRegression
3.使用sklearn 中的回归算法
4.使用sklearn.neighbors 中的KNeighborsRegressor进行回归
5.由于4中拟合效果不好,故用网格搜索,对参数进行优化(from sklearn.model_selection import GridSearchCV)
6.编写自己的网格搜索函数(由于在搜索最有参数的过程中,不是按照我们的score标准来进行评判的,故在网格搜索得到的参数的模型下计算出的score 略低)。效果仍然不如LinearRegression
四.总结
1.线性回归算法的特点及与KNN算法的比较
(1)线性回归训练示意图
(3)线性回归只能解决回归问题,但是在很多分类方法中,新性回归是基础,比如逻辑回归(需后续学习)
KNN既可以解决分类问题,又可以解决回归问题。但在预测波士顿房价时,线性回归的性能更好一些。
(4)线性回归算法对数据有假设:线性
而KNN算法对数据没有假设
(5)多元线性回归的正规方程解的计算复杂度高,
2.线性回归算法具有可解释性的说明
注:蓝色的表示out(输出)
from sklearn import datasets
from sklearn.linear_model import LinearRegressionimport numpy as np
boston = datasets.load_boston()
X = boston.data
y = boston.target
X = X[y<50]
y = y[y<50]
X.shape
(490, 13)
y.shape
(490,)
#由于我们现在不做预测,所以不需要将数据集分成训练数据集和测试数据集
linReg = LinearRegression()
linReg.fit(X,y) #coef_ intercept_
coef = linReg.coef_
coef
array([-1.05574295e-01, 3.52748549e-02, -4.35179251e-02, 4.55405227e-01,
-1.24268073e+01, 3.75411229e+00, -2.36116881e-02, -1.21088069e+00,
2.50740082e-01, -1.37702943e-02, -8.38888137e-01, 7.93577159e-03,
-3.50952134e-01])
boston.keys()
dict_keys(['data', 'target', 'feature_names', 'DESCR'])
featureNames = boston.feature_names
featureNames
array(['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD','TAX', 'PTRATIO', 'B', 'LSTAT'], dtype='<U7')
# 根据我们拟合出来的系数,看一下哪写特征对房价的影响较大,
#某特征前面的系数越大,表明该特征对房价的影响因素越大
featureNames[np.argsort(coef)] #默认为从小到大
array(['NOX', 'DIS', 'PTRATIO', 'LSTAT', 'CRIM', 'INDUS', 'AGE', 'TAX',
'B', 'ZN', 'RAD', 'CHAS', 'RM'], dtype='<U7')
boston.DESCR
# 正相关系数比较大的
# - RM average number of rooms per dwelling 数据挖掘:房屋的面积?
# - CHAS Charles River dummy variable (= 1 if tract bounds river; 0 otherwise) 数据挖掘:附近是否有公园?
#负相关系数比较大的
# - NOX nitric oxides concentration (parts per 10 million) 数据挖掘:附件污染常矿的数量?
# - DIS weighted distances to five Boston employment centres 数据挖掘:到商业中心/产业区的距离?
# 可以看到这些结果与我们现实生活中的现象是一致的,同时也可以挖掘出新的数据特征。
# 通过搜集我们挖掘到的特征,再进行预测,或许可以进一步的提高预测的准确性。
代码:详见LinearRegression_Explanation.ipynb