简单线性回归
一、什么是线性回归
线性回归是指使用一个线性关系来表示数据
我们数学中学习的 y = a*x + b ,就是最典型的线性回归
二、线性回归的分类
根据未知数的数量,线性回归分为:
-
一元线性回归
-
多元线性回归
例如:
对于结果 y 而言,若只含有一个未知数 x,就是一元线性回归
若有未知数 x1,x2,x3,x4,就是多元线性回归
三、一元线性回归的数学知识
对于一元线性回归,表达式的行式为:
y = a*x + b
根据数学知识,可以得到:
mean(x) 表示 X的的平均数
四、封装一个自己的一元线性回归
import numpy as np
class SimpleLinearRegression3:
def __init__(self):
self.a = None
self.b = None
def fit(self, x_arr, y_arr):
assert x_arr.ndim == y_arr.ndim and x_arr.ndim == 1, "the ndim of x_arr and y_arr must be 1"
assert x_arr.shape[0] == y_arr.shape[0], 'the length of x_arr must be equal to y_arr'
self.x_mean_ = np.mean(x_arr)
self.y_mean_ = np.mean(y_arr)
upper = (x_arr - self.x_mean_).dot(y_arr - self.y_mean_)
down = (x_arr - self.x_mean_).dot(x_arr - self.x_mean_)
self.a = upper / down
self.b = self.y_mean_ - self.a * self.x_mean_
return self
def predict(self, x_preduct):
return np.array([self._predict(x) for x in np.array(x_preduct)])
def _predict(self, x):
return self.a * x + self.b
def score(self,X_test,y_test):
""" R-Squared """
return r2_score(y_test,self.predict(X_test))
def __repr__(self):
return "SimpleLinearRegression3()"
这里的 r2_score() 在下面的评判方法中有具体的介绍和实现代码
五、使用自己的一元线性回归预测波士顿房价
我们使用一元线性回归方法预测一下波士顿的房价
sklearn 中的波士顿房价有多个特征值,这里我们只取出其中的一个特征:房价数量RM
from playML.SimpleLinearRegression import SimpleLinearRegression3
from sklearn import datasets
from sklearn.model_selection import train_test_split
boston = datasets.load_boston()
# 查看数据集的关键字
print(boston.keys())
# dict_keys(['data', 'target', 'feature_names', 'DESCR', 'filename'])
# 查看一下数据集的特征值都有什么
print(boston.feature_names)
# 第六个特征 RM 便是房间数量
# ['CRIM' 'ZN' 'INDUS' 'CHAS' 'NOX' 'RM' 'AGE' 'DIS' 'RAD' 'TAX' 'PTRATIO'
'B' 'LSTAT']
X = boston.data
y = boston.target
X_data = X[y<50][:,5]
y_data = y[y<50]
X_train , X_test , y_train , y_test = train_test_split(X_data , y_data,test_size=0.2,random_state=666)
linear = SimpleLinearRegression3()
linear.fit(X_train , y_train)
y_predict = linear.predict(X_test)
print(y_predict[:10])
print(linear.score(X_test,y_test))
# 0.6129316803937324
六、使用sklearn的一元线性回归预测波士顿房价
这里我们仍然只取出其中的一个特征:房价数量RM
from sklearn.linear_model import LinearRegression
from sklearn import datasets
import numpy as np
from sklearn.model_selection import train_test_split
boston = datasets.load_boston()
X = boston.data
y = boston.target
用散点图的方式简单看一下 RM 一列与房价的大概关系
from matplotlib import pyplot as plt
plt.scatter(X[:,5],y)
plt.show()
可以看到有一小部分数据的房价达到了最大值,这些数据的房价极有可能并不是50,而是50+
所以,我们可以过滤掉这些极端值
# 过滤掉极大值
X_data = X[y<50]
y_data = y[y<50]
# 我们使用的是一元线性回归,所以需要把数据集由矩阵转换为向量
X_data = X_data[:,5].reshape(-1,1)
# 数据集划分为训练集与测试集
X_train , X_test , y_train , y_test = train_test_split(X_data,y_data,test_size=0.2,random_state=666)
# 生成线性回归对象
linear = LinearRegression()
# 训练模型
linear.fit(X_train,y_train)
# 预测数据
y_predict = linear.predict(X_test)
print(y_predict)
# 查看预测的准确率
linear.score(X_test,y_test)
# 0.6129316803937324
因为在数据集中,波士顿房价有13个特征值,而我们在这里进行回归时只取出了一个特征,所以模型预测出来的准确度比较低
七、回归算法的评判方法
1、MSE:均方误差
公式:
y(i) 表示实际值
y(j) 表示预测值
自己实现
def mean_squared_error(y_test, y_predict):
"""均方误差 MSE"""
assert len(y_test) == len(y_predict), "the length of y_test must be equal to y_predict"
assert y_test.ndim == 1 and y_predict.ndim == 1, "the ndim of y_test and y_predict must be 1"
return np.sum((y_test - y_predict) ** 2) / len(y_test)
该方法对应于 sklearn 库中的 mean_squared_error( y_test , y_predict )
from sklearn.metrics import mean_squared_error
2、RMSE均方根误差
公式:
def mean_absolute_error(y_test, y_predict):
"""平均绝对误差"""
assert len(y_test) == len(y_predict), "the length of y_test must be equal to y_predict"
assert y_test.ndim == 1 and y_predict.ndim == 1, "the ndim of y_test and y_predict must be 1"
return np.sum(np.abs(y_test - y_predict)) / len(y_test)
sklearn 中没有该评测方法
这种评测方法其实就是 MSE 评分的开方
3、平均绝对误差
公式:
def mean_absolute_error(y_test, y_predict):
"""平均绝对误差"""
assert len(y_test) == len(y_predict), "the length of y_test must be equal to y_predict"
assert y_test.ndim == 1 and y_predict.ndim == 1, "the ndim of y_test and y_predict must be 1"
return np.sum(np.abs(y_test - y_predict)) / len(y_test)
该方法对应于 sklearn 库中的 mean_absolute_error( y_test , y_predict )
from sklearn.metrics import mean_absolute_error
4、R-squared
公式:
def r2_score(y_test, y_predict):
""" R**2 """
assert len(y_test) == len(y_predict), "the length of y_test must be equal to y_predict"
assert y_test.ndim == 1 and y_predict.ndim == 1, "the ndim of y_test and y_predict must be 1"
return 1 - (np.sum((y_test - y_predict) ** 2)) / (np.sum((y_test - np.mean(y_test)) ** 2))
该方法对应于 sklearn 库中的 r2_score( y_test , y_predict )
from sklearn.metrics import r2_score
前三种评测方法的结果绝大多数情况下都是一个大于 1 的数值
对于同一种算法而言,即使使用不同类型的数据训练,对不同类型的数据进行预测,根据前三种评测结果,无法得出谁好谁坏的结论
例如使用多元线性回归算法,分别预测下个月的销售额和下次考试的语文成绩,评测结果无法看出是预测的销售额准确,还是预测的语文成绩准确
R-Squared 评测方法 完美解决了这个问题
-
R-Squared 将评测结果转换到 0~1 之间(也有可能会小于0)
-
R-squared 的最大值为 1 ,最小值可能会小于0
-
∑ ( y(i) - y(j) )² 表示我们的训练模型的预测值产生的错误大小
-
∑ ( y(i) - mean(y) )² 表示直接使用BaseModel模型预测数据产生的错误
-
当评测值小于 0 时,表示目前的训练模型效果还不如 BaseModel,此时数据之间很有可能不存在线性关系
BaseModel : 使用均值作为训练模型,即无论预测时传入的数据是什么,都预测为训练数据集的均值