目录
介绍
波士顿房价数据集
一、梯度下降法实现线性回归
1、模型实现
2、加载数据:
3、模型调用
二、最小二乘法实现线性回归
1、模型实现
2、模型调用
三、对比sklearn的实现
1、预测结果比较
2、评价指标比较
介绍
这节主要介绍三种线性回归方法,并对它们进行对比。前两种方法是我自己写的,分别使用梯度下降法和最小二乘法求得模型参数,第三种方法使用sklearn封装的线性回归。
实验数据是应用sklearn自带的波士顿房价数据,以下对该数据的调用进行介绍
波士顿房价数据集
首先从sklearn的数据集中调用波士顿房价数据
from sklearn.datasets import load_boston
其次加载数据集:
# 加载波士顿房价数据集,返回特征X和标签y X, y = load_boston(return_X_y=True) X.shape # (506, 13) y.shape # (506,)
一、梯度下降法实现线性回归
1、模型实现
import numpy as np
import matplotlib.pyplot as plt
class LinearRegression1:
'''梯度下降法实现线性回归'''
def __init__(self,learning_rate=0.1,epoch=5000):
'''
learning_rate: 学习率,控制参数更新的幅度
epoch: 在训练集上训练迭代的最大次数
cost_list: 记录每次迭代后的经验风险
'''
self.learning_rate = learning_rate
self.epoch = epoch
self.cost_list = []
# 模型训练:使用梯度下降法更新参数
def fit(self,X_train,y_train):
'''
X_train: m x n的矩阵
y_train: 有m个元素的一维数组
'''
# 模型有偏置项b,因此需要给每个测试样本增加特征x_temp = 1
x_temp = np.ones((X_train.shape[0], 1))
X_train = np.concatenate((x_temp, X_train), axis=1)
# 训练样本的数量
m = X_train.shape[0]
# 训练样本的维数
n = X_train.shape[1]
# 模型参数初始化
self.w = np.ones(n)
# 模型参数确定
for i in range(self.epoch):
# 计算训练样本预测值
y_pred = np.dot(X_train, self.w)
# 计算损失函数值
cost = np.dot(y_pred - y_train, y_pred - y_train) / (2 * m)
# 记录每次迭代对应的损失函数值
self.cost_list.append(cost)
# 参数更新
self.w -= self.learning_rate / m * np.dot(y_pred - y_train, X_train)
# 预测函数
def predict(self, X_test):
'''
X_test: m x n的矩阵
'''
# 模型有偏置项b,因此需要给每个测试样本增加特征x_temp = 1
x_temp = np.ones((X_test.shape[0], 1))
X_test = np.concatenate((x_temp, X_test), axis=1)
# 返回结果预测结果
return np.dot(X_test, self.w)
# 绘制损失函数的收敛趋势图
def plot_cost(self):
plt.plot(np.arange(self.epoch), self.cost_list)
plt.xlabel('epoch')
plt.ylabel('cost')
plt.show()
2、加载数据:
import numpy as np
import matplotlib.pyplot as plt
class LinearRegression1:
'''梯度下降法实现线性回归'''
def __init__(self,learning_rate=0.1,epoch=5000):
'''
learning_rate: 学习率,控制参数更新的幅度
epoch: 在训练集上训练迭代的最大次数
cost_list: 记录每次迭代后的经验风险
'''
self.learning_rate = learning_rate
self.epoch = epoch
self.cost_list = []
# 模型训练:使用梯度下降法更新参数
def fit(self,X_train,y_train):
'''
X_train: m x n的矩阵
y_train: 有m个元素的一维数组
'''
# 模型有偏置项b,因此需要给每个测试样本增加特征x_temp = 1
x_temp = np.ones((X_train.shape[0], 1))
X_train = np.concatenate((x_temp, X_train), axis=1)
# 训练样本的数量
m = X_train.shape[0]
# 训练样本的维数
n = X_train.shape[1]
# 模型参数初始化
self.w = np.ones(n)
# 模型参数确定
for i in range(self.epoch):
# 计算训练样本预测值
y_pred = np.dot(X_train, self.w)
# 计算损失函数值
cost = np.dot(y_pred - y_train, y_pred - y_train) / (2 * m)
# 记录每次迭代对应的损失函数值
self.cost_list.append(cost)
# 参数更新
self.w -= self.learning_rate / m * np.dot(y_pred - y_train, X_train)
# 预测函数
def predict(self, X_test):
'''
X_test: m x n的矩阵
'''
# 模型有偏置项b,因此需要给每个测试样本增加特征x_temp = 1
x_temp = np.ones((X_test.shape[0], 1))
X_test = np.concatenate((x_temp, X_test), axis=1)
# 返回结果预测结果
return np.dot(X_test, self.w)
# 绘制损失函数的收敛趋势图
def plot_cost(self):
plt.plot(np.arange(self.epoch), self.cost_list)
plt.xlabel('epoch')
plt.ylabel('cost')
plt.show()
2、加载数据:
利用介绍的方法调用波士顿房价数据集,并对数据进行预处理及数据集的划分。
代码实现如下:
from sklearn.datasets import load_boston from sklearn.model_selection import train_test_split from sklearn.preprocessing import MinMaxScaler # 加载波士顿房价数据集 X, y = load_boston(return_X_y=True) # 特征X归一化到 [0,1] 范围内:提升模型收敛速度 X = MinMaxScaler().fit_transform(X) # 数据集划分,其中测试集占20% X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.2)
3、模型调用
# 实例化一个对象
model1 = LinearRegression1()
# 用训练集训练此模型
model1.fit(X_train,y_train)
# 损失函数的收敛趋势图显示
model1.plot_cost()
# 进行预测
y_pred = model1.predict(X_test)
得到损失函数收敛趋势图如下:
二、最小二乘法实现线性回归
1、模型实现
import numpy as np
import matplotlib.pyplot as plt
class LinearRegression2:
'''最小二乘法实现线性回归'''
# 模型训练:使用梯度下降法更新参数
def fit(self, X_train, y_train):
'''
X_train: m x n的矩阵
y_train: 有m个元素的一维数组
'''
# 模型有偏置项b,因此需要给每个测试样本增加特征x_temp = 1
x_temp = np.ones((X_train.shape[0], 1))
X_train = np.concatenate((x_temp, X_train), axis=1)
# 训练样本的数量
m = X_train.shape[0]
# 训练样本的维数
n = X_train.shape[1]
# 初始化模型参数
self.w = np.ones((n, 1))
# 根据最小二乘法确定w
self.w = np.linalg.inv(X_train.T.dot(X_train)).dot(X_train.T.dot(y_train))
def predict(self,X_test):
'''
X_test: m x n的矩阵
'''
# 模型有偏置项b,因此需要给每个测试样本增加特征x_temp = 1
x_temp = np.ones((X_test.shape[0], 1))
X_test = np.concatenate((x_temp, X_test), axis=1)
# 返回结果预测结果
return np.dot(X_test, self.w)
数据加载和第一个一样
2、模型调用
# 实例化一个对象
model2 = LinearRegression2()
# 用训练集训练此模型
model2.fit(X_train,y_train)
# 预测数据
y_pred = model2.predict(X_test)
# 数据可视化
plt.scatter(y_test,y_pred)
plt.xlabel('y_test')
plt.ylabel('y_pred')
x_max = np.max(y_test)
x = np.arange(0,x_max)
plt.plot(x,x,c='r')
plt.show()
三、对比sklearn的实现
1、预测结果比较
# 引入 sklearn 线性回归模型
from sklearn.linear_model import LinearRegression
import pandas as pd
# 实例化模型对象
my_model1 = LinearRegression1() # 梯度下降法
my_model2 = LinearRegression2() # 最小二乘法
sklearn_model = LinearRegression() # sklearn自带线性回归模型
# 模型训练
my_model1.fit(X_train,y_train)
my_model2.fit(X_train,y_train)
sklearn_model.fit(X_train,y_train)
# 在测试集上预测
my_model1_pred = my_model1.predict(X_test)
my_model2_pred = my_model2.predict(X_test)
sklearn_model_pred = sklearn_model.predict(X_test)
# 数据输出以表格形式展示,且只展示前15行数据
house_price = pd.Dataframe([y_test,my_model1_pred,my_model2_pred,sklearn_model_pred]).T.head(15)
# 表头列名设置
house_price.columns = ['true_value','my_model1_pred','my_model2_pred','sklearn_model_pred']
# 写入excel
house_price.to_excel('price.xlsx')
1、预测结果比较
# 引入 sklearn 线性回归模型
from sklearn.linear_model import LinearRegression
import pandas as pd
# 实例化模型对象
my_model1 = LinearRegression1() # 梯度下降法
my_model2 = LinearRegression2() # 最小二乘法
sklearn_model = LinearRegression() # sklearn自带线性回归模型
# 模型训练
my_model1.fit(X_train,y_train)
my_model2.fit(X_train,y_train)
sklearn_model.fit(X_train,y_train)
# 在测试集上预测
my_model1_pred = my_model1.predict(X_test)
my_model2_pred = my_model2.predict(X_test)
sklearn_model_pred = sklearn_model.predict(X_test)
# 数据输出以表格形式展示,且只展示前15行数据
house_price = pd.Dataframe([y_test,my_model1_pred,my_model2_pred,sklearn_model_pred]).T.head(15)
# 表头列名设置
house_price.columns = ['true_value','my_model1_pred','my_model2_pred','sklearn_model_pred']
# 写入excel
house_price.to_excel('price.xlsx')
结果为:
| true_value | my_model1_pred | my_model2_pred | sklearn_model_pred | |
| 0 | 13.8 | 11.94996125 | 11.73018848 | 11.73018848 |
| 1 | 13 | 17.73910411 | 17.55439274 | 17.55439274 |
| 2 | 24.1 | 29.37649512 | 29.7145764 | 29.7145764 |
| 3 | 19.9 | 19.80421486 | 19.63501745 | 19.63501745 |
| 4 | 18.5 | 19.22821175 | 19.14250233 | 19.14250233 |
| 5 | 8.5 | 16.75091864 | 16.76076583 | 16.76076583 |
| 6 | 16.7 | 20.43923394 | 20.30291991 | 20.30291991 |
| 7 | 22.6 | 20.03720356 | 19.86363718 | 19.86363718 |
| 8 | 29.4 | 30.3883613 | 30.64937389 | 30.64937389 |
| 9 | 24.4 | 28.34047452 | 28.48494535 | 28.48494535 |
| 10 | 23.8 | 23.16698482 | 23.50557727 | 23.50557727 |
| 11 | 22.7 | 23.53185162 | 23.31590448 | 23.31590448 |
| 12 | 21.7 | 20.87276726 | 20.98183999 | 20.98183999 |
| 13 | 13.3 | 15.98472933 | 16.01499729 | 16.01499729 |
| 14 | 19 | 20.97518589 | 20.98509203 | 20.98509203 |
从结果可知,三种模型的预测结果还是较为相似的
2、评价指标比较
- MSE:均方误差
- MAE:平均绝对误差
- :相关系数
# 调用sklearn中的算法计算评价指标 from sklearn.metrics import mean_squared_error,mean_absolute_error,r2_score # MSE:均方误差 my_model1_mse = mean_squared_error(y_test,my_model1_pred) my_model2_mse = mean_squared_error(y_test,my_model2_pred) sklearn_model_mse = mean_squared_error(y_test,sklearn_model_pred) print(my_model1_mse,my_model2_mse,sklearn_model_mse) # MAE:平均绝对误差 my_model1_mae = mean_absolute_error(y_test,my_model1_pred) my_model2_mae = mean_absolute_error(y_test,my_model2_pred) sklearn_model_mae = mean_absolute_error(y_test,sklearn_model_pred) print(my_model1_mae,my_model2_mae,sklearn_model_mae) # R2:相关系数 my_model1_r2 = r2_score(y_test,my_model1_pred) my_model2_r2 = r2_score(y_test,my_model2_pred) sklearn_model_r2 = r2_score(y_test,sklearn_model_pred) print(my_model1_r2,my_model2_r2,sklearn_model_r2)
实验结果:
| my_model1 | my_model2 | sklearn_model | |
| MSE | 21.21 | 21.50 | 21.50 |
| MAE | 3.57 | 3.60 | 3.60 |
| R2 | 0.71 | 0.70 | 0.70 |



