当前位置:   article > 正文

02 机器学习算法之线性回归算法_线性回归训练集

线性回归训练集

机器学习算法之线性回归算法

目录

  • 1.线性回归算法简介
  • 2.简单线性回归算法的实现

          2.1 for循环方式实现

          2.2 向量化方式实现

  • 3.衡量线性回归算法的指标
  • 4.最好的衡量线性回归法的指标R Squared
  • 5.多元线性回归
  • 6.波士顿房价预测问题

一、线性回归算法简介

  • 解决回归问题
  • 思想简单,实现容易
  • 许多强大的非线性模型的基础
  • 结果具有很好的可解释性
  • 蕴含机器学习中的很多重要思想

简单来说,线性回归算法以一个坐标系里一个维度为结果,其它维度为特征(如二维平面坐标系中横轴为特征,纵轴为结果),无数的训练集放在坐标系中,发现他们是围绕这一条线分布的。线性回归算法的期望,就是寻找一条直线,最大程度的拟合样本特征和样本输出标记的关系

å¨è¿éæå¥å¾çæè¿°

简单线性回归(样本特征只有一个时的回归问题)为例,将房屋的面积作为x轴,将房屋的价格作为y轴,每一个点为(X(i) ,y(i)),那么我们期望寻找的直线就是y=ax+b,当给出一个新的点x(j)的时候,我们希望预测的y^(j)=ax(j)+b

å¨è¿éæå¥å¾çæè¿°

注意:

  • 这里不使用直接相减的方式,是由于差值有正有负,会进行抵消;
  • 这里不使用绝对值的方式,是由于绝对值函数存在不可导的点;

因此,简单线性回归问题的目标是

å¨è¿éæå¥å¾çæè¿°

通过上面的推导,我们也可以归纳出一类机器学习算法的基本思路,如下图:其中损失函数是计算期望值和预测值的差值,而期望其差值(也就是损失)越来越小,而效用函数则是用来描述拟合度,期望拟合度越来越好

å¨è¿éæå¥å¾çæè¿°

二、简单线性回归的实现

1.数据集

  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. x = np.array([1.,2.,3.,4.,5.])
  4. y = np.array([1.,3.,2.,3.,5.])
  5. plt.scatter(x,y)
  6. plt.axis([0,6,0,6])
  7. plt.show()

a,b的计算公式

2.以for循环的方式实现简单的线性回归算法

  1. class SimpleLinearRegression1:
  2. def __inint__(self):
  3. """初始化Simple Linear Regression 模型"""
  4. self.a_ = None
  5. self.b_ = None
  6. def fit(self,x_train,y_train):
  7. """根据训练数据集x_train,y_train训练Simple Linear Regression模型"""
  8. assert x_train.ndim == 1,"Simple Linear Regressor can only solve single feature training data."
  9. assert len(x_train) == len(y_train),"the size of x_train must be equal to the size of y_train"
  10. # 求均值
  11. x_mean = np.mean(x_train)
  12. y_mean = np.mean(y_train)
  13. # 分子
  14. num = 0.0
  15. # 分母
  16. d = 0.0
  17. # 计算分子和分母
  18. for x,y in zip(x_train,y_train):
  19. num += (x-x_mean)*(y-y_mean)
  20. d += (x-x_mean)**2
  21. # 计算参数a和b
  22. self.a_ = num / d
  23. self.b_ = y_mean - self.a_*x_mean
  24. return self
  25. def predict(self,x_predict):
  26. """给定待预测数据集x_predict,返回表示x_predict的结果向量"""
  27. assert x_predict.ndim == 1,"Simple Linear Regressor can only solve single feature training data."
  28. assert self.a_ is not None and self.b_ is not None,"must fit before predict!"
  29. return np.array([self._predict(x) for x in x_predict])
  30. def _predict(self, x_single):
  31. """给定单个待预测数据x,返回x的预测结果值"""
  32. return self.a_ * x_single + self.b_
  33. def __repr__(self):
  34. return "SimpleLinearRegression1()"

a.调用自己的封装函数

  1. reg1 = SimpleLinearRegression1()
  2. reg1.fit(x,y)

b.进行预测

  1. x_predict = 6
  2. print(reg1.predict(np.array([x_predict])))
[5.2]

c.查看参数a和b

  1. print(reg1.a_)
  2. print(reg1.b_)
  1. 0.8
  2. 0.39999999999999947

d.绘图展示

  1. y_hat1 = reg1.predict(x)
  2. plt.scatter(x,y)
  3. plt.plot(x,y_hat1,color="red")
  4. plt.axis([0,6,0,6])
  5. plt.show()

3.以向量化的方式实现简单线性回归算法

  1. class SimpleLinearRegression2:
  2. def __init__(self):
  3. """初始化Simple Linear Regression模型"""
  4. self.a_ = None
  5. self.b_ = None
  6. def fit(self, x_train, y_train):
  7. """根据训练数据集x_train,y_train训练Simple Linear Regression模型"""
  8. assert x_train.ndim == 1, \
  9. "Simple Linear Regressor can only solve single feature training data."
  10. assert len(x_train) == len(y_train), \
  11. "the size of x_train must be equal to the size of y_train"
  12. # 均值
  13. x_mean = np.mean(x_train)
  14. y_mean = np.mean(y_train)
  15. # 使用向量化点乘计算参数a和b
  16. self.a_ = (x_train - x_mean).dot(y_train - y_mean) / (x_train - x_mean).dot(x_train - x_mean)
  17. self.b_ = y_mean - self.a_ * x_mean
  18. return self
  19. def predict(self, x_predict):
  20. """给定待预测数据集x_predict,返回表示x_predict的结果向量"""
  21. assert x_predict.ndim == 1, \
  22. "Simple Linear Regressor can only solve single feature training data."
  23. assert self.a_ is not None and self.b_ is not None, \
  24. "must fit before predict!"
  25. return np.array([self._predict(x) for x in x_predict])
  26. def _predict(self, x_single):
  27. """给定单个待预测数据x_single,返回x_single的预测结果值"""
  28. return self.a_ * x_single + self.b_
  29. def __repr__(self):
  30. return "SimpleLinearRegression2()"

a.调用自己的封装函数

  1. reg2 = SimpleLinearRegression2()
  2. reg2.fit(x,y)

b.进行预测

reg2.predict(np.array([x_predict]))
[5.2]

c.查看参数和a和b

  1. print(reg2.a_)
  2. print(reg2.b_)
  1. 0.8
  2. 0.39999999999999947

d.进行绘图展示

  1. y_hat2 = reg2.predict(x)
  2. plt.scatter(x,y)
  3. plt.plot(x,y_hat2,color="red")
  4. plt.axis([0,6,0,6])
  5. plt.show()

å¨è¿éæå¥å¾çæè¿°

4.for循环和向量化性能对比

a.数据集的提供

  1. m = 1000000
  2. big_x = np.random.random(size=m)
  3. big_y = big_x * 2.0 + 3.0 + np.random.normal(size=m)

b.性能测试

  1. %timeit reg1.fit(big_x,big_y)
  2. %timeit reg2.fit(big_x,big_y)
  1. 1.11 s ± 14.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
  2. 17.4 ms ± 211 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

三、衡量线性回归算法的指标

1.衡量标准

a.MSE(Mean Squared Error)均分误差

其中衡量标准是和m有关的,因为越多的数据量产生的误差和可能会更大,但是毫无疑问越多的数据量训练出来的模型更好,为此需要一个取消误差的方法,如下:

b.RMSE(Root Mean Squared Error)均方根误差

MSE 的缺点,量纲不准确,如果y的单位是万元,平方后就变成了万元的平方,这可能会给我们带来一些麻烦MSE 的缺点,量纲不准确,如果y的单位是万元,平方后就变成了万元的平方,这可能会给我们带来一些麻烦

c.MAE(Mean Absolute Error)平均绝对误差

总结:

RMSE平方累加后再开根号,如果某些预测结果和真实结果相差非常大,那么RMSE的结果会相对变大,所以RMSE有放大误差的趋势,而MAE没有,他直接就反应的是预测结果和真实结果直接的差距,正因如此,从某种程度上来说,想办法我们让RMSE变的更小小对于我们来说比较有意义,因为这意味着整个样本的错误中,那个最值相对比较小,而且我们之前训练样本的目标,就是RMSE根号里面1/m的这一部分,而这一部分的本质和优化RMSE是一样的
 

2.MSE,RMSE,MAE的源码实现

a.这里使用Boston房价数据集

  1. from sklearn import datasets
  2. boston = datasets.load_boston()
  1. # 简单线性回归算法
  2. x = boston.data[:,5] # 只选用了RM房间这个属性
  3. y = boston.target
  1. # 在图中表示一下
  2. plt.scatter(x,y)
  3. plt.show()

  1. # 从上图中可以看出存在上限值,我们需要将这些上限值排除在外
  2. x = x[y<50.0]
  3. y = y[y<50.0]
  1. # 重新绘图
  2. plt.scatter(x,y)
  3. plt.show()

b.调用简单线性回归函数

  1. # 先将数据集分为测试集和训练集
  2. from sklearn.model_selection import train_test_split
  3. x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.2,random_state=666)
  1. # 查看一下测试集和训练集数据
  2. print(x_train.shape,type(x_train))
  3. print(y_train.shape,type(y_train))
  4. print(x_test.shape,type(x_test))
  5. print(y_test.shape,type(y_test))
  1. (392,) <class 'numpy.ndarray'>
  2. (392,) <class 'numpy.ndarray'>
  3. (98,) <class 'numpy.ndarray'>
  4. (98,) <class 'numpy.ndarray'>
  1. reg = SimpleLinearRegression2()
  2. reg.fit(x_train,y_train)
  1. # 绘图预测
  2. plt.scatter(x_train,y_train)
  3. plt.plot(x_train,reg.predict(x_train),color="r")
  4. plt.show()

  1. # 预测值
  2. y_predict = reg.predict(x_test)

c.MSE评估

  1. mse_test = np.sum((y_predict-y_test)**2)/len(y_test)
  2. print(mse_test)
24.156602134387438

d.RMSE评估

  1. from math import sqrt
  2. rmse_test = sqrt(mse_test)
  3. print(rmse_test)
4.914936635846635

e.MAE的评估

  1. mae_test = np.sum(np.absolute(y_predict-y_test))/len(y_test)
  2. print(mae_test)
3.5430974409463873

3.使用scikit-learn自带的MSE和MAE

  1. from sklearn.metrics import mean_squared_error
  2. from sklearn.metrics import mean_absolute_error
mean_squared_error(y_test,y_predict)
24.156602134387438
mean_absolute_error(y_test,y_predict)
3.5430974409463873

总结:
RMSE和MAE的值对应不同的单位和量纲,无法具体比较

四、最好的衡量线性回归法的指标 R Square

1.R Squared简介

2.R Squared的意义

使用BaseLine Model产生的错误会很大,使用我们的模型预测产生的错误会相对少些(因为我们的模型充分的考虑了y和x之间的关系),用这两者相减,结果就是拟合了我们的错误指标,用1减去这个商结果就是我们的模型没有产生错误的指标

3.R Square的评价

4.R Square的公式

5.R Square源码实现

1-mean_squared_error(y_test,y_predict)/np.var(y_test)
0.6129316803937322
  1. # 直接调用sklearn
  2. from sklearn.metrics import r2_score
  3. r2_score(y_test,y_predict)
0.6129316803937324

五、多元线性回归

1,多元线性回归模型的简介

2.多元线性回归的实现

  1. class LinearRegression:
  2. def __init__(self):
  3. """初始化Linear Regression模型"""
  4. # 系数向量(θ1,θ2,.....θn)
  5. self.coef_ = None
  6. # 截距 (θ0)
  7. self.interception_ = None
  8. # θ向量
  9. self._theta = None
  10. def fit_normal(self, X_train, y_train):
  11. """根据训练数据集X_train,y_train 训练Linear Regression模型"""
  12. assert X_train.shape[0] == y_train.shape[0], \
  13. "the size of X_train must be equal to the size of y_train"
  14. # np.ones((len(X_train), 1)) 构造一个和X_train 同样行数的,只有一列的全是1的矩阵
  15. # np.hstack 拼接矩阵
  16. X_b = np.hstack([np.ones((len(X_train), 1)), X_train])
  17. # X_b.T 获取矩阵的转置
  18. # np.linalg.inv() 获取矩阵的逆
  19. # dot() 矩阵点乘
  20. self._theta = np.linalg.inv(X_b.T.dot(X_b)).dot(X_b.T).dot(y_train)
  21. self.interception_ = self._theta[0]
  22. self.coef_ = self._theta[1:]
  23. return self
  24. def predict(self, X_predict):
  25. """给定待预测数据集X_predict,返回表示X_predict的结果向量"""
  26. assert self.coef_ is not None and self.interception_ is not None,\
  27. "must fit before predict"
  28. assert X_predict.shape[1] == len(self.coef_),\
  29. "the feature number of X_predict must be equal to X_train"
  30. X_b = np.hstack([np.ones((len(X_predict), 1)), X_predict])
  31. return X_b.dot(self._theta)
  32. def score(self, X_test, y_test):
  33. """根据测试数据集 X_test 和 y_test 确定当前模型的准确度"""
  34. y_predict = self.predict(X_test)
  35. return r2_score(y_test, y_predict)
  36. def __repr__(self):
  37. return "LinearRegression()"

六、波士顿房价预测问题

1.获取数据集

  1. # 导入模块
  2. import numpy as np
  3. import matplotlib.pyplot as plt
  4. from sklearn import datasets
  1. # 获取数据集
  2. boston = datasets.load_boston()
  3. x = boston.data
  4. y = boston.target
  5. x = x[y<50.0]
  6. y = y[y<50.0]
  1. # 查看一下数据集
  2. print(x.shape,type(x))
  3. print(y.shape,type(y))
  1. (490, 13) <class 'numpy.ndarray'>
  2. (490,) <class 'numpy.ndarray'>
  1. # 将数据集划分为测试集和训练集
  2. from sklearn.model_selection import train_test_split
  3. x_train,x_test,y_train,y_test = train_test_split(x,y)

2.建立线性回归模型Linear Regression

  1. from sklearn.linear_model import LinearRegression
  2. lin_reg = LinearRegression()
  1. # 训练模型得出参数
  2. lin_reg.fit(x_train,y_train)
  1. LinearRegression(copy_X=True, fit_intercept=True, n_jobs=None,
  2. normalize=False)
  1. # 查看模型参数
  2. print(lin_reg.coef_)
  1. [-1.04156138e-01 3.86619027e-02 -4.51033368e-02 3.98933894e-01
  2. -1.44605989e+01 3.72025936e+00 -1.38861106e-02 -1.21248375e+00
  3. 2.65937183e-01 -1.33953987e-02 -9.40424839e-01 8.81098776e-03
  4. -3.56489837e-01]
print(lin_reg.intercept_)
34.29394259562285
  1. # 调用R2进行衡量指标
  2. lin_reg.score(x_test,y_test)
0.7392238735878867

补充

在01机器学习算法之KNN中,讲到KNN可以进行线性回归,当时并没有例子,在这里我们用KNN实现线性回归。

KNN实现线性回归

a.调用KNN

  1. from sklearn.neighbors import KNeighborsRegressor
  2. knn_reg = KNeighborsRegressor()
  3. knn_reg.fit(x_train,y_train)
  4. print(knn_reg.score(x_test,y_test))
0.6545104997332957

b.使用网格搜索超参数

  1. from sklearn.model_selection import GridSearchCV
  2. param_grid = [
  3. {
  4. "weights" : ["uniform"],
  5. "n_neighbors":[i for i in range(1,11)]
  6. },
  7. {
  8. "weights" : ["distance"],
  9. "n_neighbors":[i for i in range(1,11)],
  10. "p":[i for i in range(1,6)]
  11. }
  12. ]
  13. knn_reg = KNeighborsRegressor()
  14. grid_search = GridSearchCV(knn_reg,param_grid,n_jobs=-1,verbose=1)
  15. grid_search.fit(x_train,y_train)
  1. # 查看一下最好的参数
  2. grid_search.best_params_
{'n_neighbors': 8, 'p': 1, 'weights': 'distance'}
  1. # 调用参数进行验证
  2. grid_search.best_estimator_.score(x_test,y_test)
0.6735218877136675

线性回归算法的可解释性

  1. from sklearn import datasets
  2. import numpy as np
  3. from sklearn.linear_model import LinearRegression
  4. boston = datasets.load_boston()
  5. x = boston.data
  6. y = boston.target
  7. lin_reg = LinearRegression()
  8. lin_reg.fit(x,y)
  1. LinearRegression(copy_X=True, fit_intercept=True, n_jobs=None,
  2. normalize=False)
lin_reg.coef_
  1. [-1.08011358e-01, 4.64204584e-02, 2.05586264e-02, 2.68673382e+00,
  2. -1.77666112e+01, 3.80986521e+00, 6.92224640e-04, -1.47556685e+00,
  3. 3.06049479e-01, -1.23345939e-02, -9.52747232e-01, 9.31168327e-03,
  4. -5.24758378e-01]
  1. # 将特征结果排序
  2. np.argsort(lin_reg.coef_)
[ 4,  7, 10, 12,  0,  9,  6, 11,  2,  1,  8,  3,  5]
  1. # 将排序过后的坐标对应的名称展示出来,方便观察理解
  2. boston.feature_names[np.argsort(lin_reg.coef_)]
['NOX', 'DIS', 'PTRATIO', 'LSTAT', 'CRIM', 'TAX', 'AGE', 'B','INDUS', 'ZN', 'RAD', 'CHAS', 'RM']

总结

RM对应的是房间数,是正相关最大的特征,也就是说房间数越多,房价越高,这是很合理的
NOX对应的是一氧化氮浓度,也就是说一氧化氮浓度越低,房价越低,这也是非常合理的
由此说明,我们的线性回归具有可解释性,我们可以在对研究一个模型的时候,可以先用线性回归模型看一下,然后根据感性的认识去直观的判断一下是否符合我们的常识。
 

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号