import numpy as np
import sklearn.datasets as datasets
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
from sklearn.metrics import mean_squared_error,mean_absolute_error

# 随机数种子
np.random.seed(206)

# 定义简单线性回归类
class SimpleLinearRegression():
    def __init__(self):
        self.a_=None
        self.b_=None
    # 最小二乘法训练模型
    def fit(self,x_train,y_train):
        assert (x_train.ndim==1 and y_train.ndim==1),
            'Simple Linear Regression model can only solve single feature training data'
        assert len(x_train)==len(y_train),
            'the size of x_train must be equal to y_train'
        x_mean=np.mean(x_train)
        y_mean=np.mean(y_train)
        self.a_=np.vdot((x_train-x_mean),(y_train-y_mean))/np.vdot((x_train-x_mean),(x_train-x_mean))
        self.b_=y_mean-self.a_*x_mean
    # 预测
    def predict(self,input_x):
        assert input_x.ndim==1 ,
            'Simple Linear Regression model can only solve single feature data'
        return np.array([self.pred_(x) for x in input_x])
    # 线性回归方程
    def pred_(self,x):
        return self.a_*x+self.b_
    def __repr__(self):
        return 'SimpleLinearRegressionModel'

if __name__ == '__main__':
    boston_data = datasets.load_boston()
    print(boston_data['DESCR'])
    x = boston_data['data'][:, 5]
    y = boston_data['target']
    x = x[y < 50]  # total x data (490,)
    y = y[y < 50]  # total x data (490,)
    plt.scatter(x, y)
    plt.xlabel('房间数量')
    plt.ylabel('房屋价格')
    plt.title('房间数量与房屋价格的关系')
    plt.show()
    x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3)
    # 最小二乘法训练模型
    regs = SimpleLinearRegression()
    regs.fit(x_train, y_train)
    # 预测
    y_hat = regs.predict(x_test)
    # 评价指标
    rmse = np.sqrt(np.sum((y_hat - y_test) ** 2) / len(x_test))
    mse = mean_squared_error(y_test, y_hat)
    mae = mean_absolute_error(y_test, y_hat)
    R_squared_Error = 1 - mse / np.var(y_test)
    # 输出评价指标
    print('mean squared error:%.2f' % (mse))
    print('root mean squared error:%.2f' % (rmse))
    print('mean absolute error:%.2f' % (mae))
    print('R squared Error:%.2f' % (R_squared_Error))
    # 绘制拟合曲线
    a = regs.a_
    b = regs.b_
    x_plot = np.linspace(4, 8, 50)
    y_plot = x_plot * a + b
    plt.scatter(x, y)
    plt.plot(x_plot, y_plot, color='red', label='最小二乘法') # 添加最小二乘法拟合曲线
    # 梯度下降法训练模型
    lr = 0.01 # 学习率
    iterations = 1000 # 迭代次数
    m = len(x_train)
    theta0 = np.random.randn()
    theta1 = np.random.randn()
    for i in range(iterations):
        y_pred = theta1 * x_train + theta0
        theta1 -= lr * (1/m) * np.sum((y_pred - y_train) * x_train)
        theta0 -= lr * (1/m) * np.sum(y_pred - y_train)
    y_plot_gd = x_plot * theta1 + theta0
    plt.plot(x_plot, y_plot_gd, color='blue', label='梯度下降法') # 添加梯度下降法拟合曲线
    plt.xlabel('房间数量')
    plt.ylabel('房屋价格')
    plt.title('房间数量与房屋价格的关系')
    plt.legend() # 显示图例
    plt.show()

代码解释:

  1. 导入库: 导入必要的库,包括numpy用于数值计算,sklearn.datasets用于加载波士顿房价数据集,sklearn.model_selection用于划分训练集和测试集,matplotlib.pyplot用于绘图,sklearn.metrics用于计算评价指标。

  2. 设置随机数种子: 使用np.random.seed(206)设置随机数种子,确保代码运行结果一致。

  3. 定义简单线性回归类: 定义SimpleLinearRegression类,包含以下方法:

    • __init__: 初始化类,设置参数a_b_None
    • fit: 使用最小二乘法训练模型,计算参数a_b_
    • predict: 预测新样本的值。
    • pred_: 计算线性回归方程。
    • __repr__: 返回类的字符串表示。
  4. 加载数据: 加载波士顿房价数据集,并选择房间数量作为特征,房屋价格作为目标变量。

  5. 划分数据集: 将数据集划分为训练集和测试集,比例为7:3。

  6. 最小二乘法训练模型: 使用SimpleLinearRegression类训练模型,并使用测试集预测结果。

  7. 计算评价指标: 计算模型的均方误差(MSE)、均方根误差(RMSE)、平均绝对误差(MAE)和R方。

  8. 绘制拟合曲线: 使用matplotlib.pyplot绘制散点图和最小二乘法拟合的直线。

  9. 梯度下降法训练模型: 使用梯度下降法训练线性回归模型。

  10. 绘制梯度下降法拟合曲线: 使用matplotlib.pyplot绘制梯度下降法拟合的直线。

  11. 显示图例: 使用plt.legend()显示图例,区分最小二乘法和梯度下降法的拟合曲线。

代码运行结果:

代码运行后,将会输出模型的评价指标,并绘制散点图和两条拟合曲线,分别代表最小二乘法和梯度下降法的拟合结果。

补充说明:

  • 代码中使用的波士顿房价数据集需要提前下载,可以通过sklearn.datasets.load_boston()方法加载。
  • 梯度下降法的学习率和迭代次数可以根据实际情况调整。
  • 拟合曲线图可以根据实际情况调整颜色和标签。
  • 本代码只是简单线性回归的一个示例,可以根据实际需求进行扩展和改进。

希望本代码和解释能够帮助您理解简单线性回归以及最小二乘法和梯度下降法的应用。

Python简单线性回归:最小二乘法与梯度下降法比较

原文地址: https://www.cveoy.top/t/topic/nlcV 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录