一元线性回归 梯度下降法 含绘图

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

class LinearRegression:

    def __init__(self,dataX,dataY):
        # 存储原始数据
        self.dataOX = dataX;
        # 定义特征列和标签列
        self.dataX = LinearRegression.preHandle(dataX)
        self.dataY = dataY
        # 获取训练数据长度
        self.dataSize = self.dataX.shape[0]
        # 定义待求解的theta值,默认为全0数组
        self.theta = np.zeros((self.dataX.shape[1],1))
        # 定义学习率和迭代次数
        self.alpha = 0.01
        self.numIterations = 1000
        # 损失值的变化历史
        self.lossHistory = []
        self.thetaHistory = np.empty((self.numIterations,2))
        # 绘图设置,中文支持
        plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
        plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号
        self.fig = plt.figure()  
        self.fig.set_size_inches(10,10)
    
    # 基于当前的theta,计算loss值,不在train上调用此方法因为会重复计算
    def loss(self):
        # 计算预测值
        prediction = np.dot(self.dataX,self.theta)
        # 计算差值
        delta = prediction - self.dataY
        # 差值平方/2倍的size就是loss
        loss = np.dot(delta.T,delta) / (self.dataSize * 2)

    def train(self):
        for index in range(self.numIterations):
            prediction = np.dot(self.dataX,self.theta)
            delta = prediction-self.dataY
            # 新的theta值 = 旧的theta值 - 学习率/样本数量 * ((预测数据-真实数据)·样本数据)
            self.theta = self.theta - self.alpha / self.dataSize * np.dot(self.dataX.T,delta)
            # 计算当前的loss,MSE(1/2)
            mse = (np.dot(delta.T,delta) / (2 * self.dataSize))[0][0]
            # 记录此次的theta值和loss值
            self.lossHistory.append(mse)
            self.thetaHistory[index] = self.theta.reshape(2,)
        print("loss:",self.lossHistory[-1]," theta:" , self.theta)

    # 绘图(仅限单变量)
    def draw(self):
        self.drawOriginalScatter()
        self.drawNormalScatter()
        self.drawGD()
        self.drawRegression()
        plt.show()

    # 原始数据绘制散点图
    def drawOriginalScatter(self):
        ax = self.fig.add_subplot(221)
        ax.set_title("Original Data Scatter")
        ax.scatter(self.dataOX, self.dataY,label='Train Dataset',s = 5)
        ax.set_xlabel("x")
        ax.set_ylabel("y")
        ax.legend()

    # 归一化的数据和原始数据绘制散点图
    def drawNormalScatter(self):
        ax = self.fig.add_subplot(222)
        ax.set_title("Normal Data Scatter")
        ax.scatter(self.dataOX, self.dataY,label='Original Train Dataset',s = 5)
        ax.scatter(self.dataX[:,1], self.dataY,label='Normal Train Dataset',s = 5)
        ax.set_xlabel("x")
        ax.set_ylabel("y")
        ax.legend()

    # loss值随迭代次数变化曲线
    def drawGD(self):
        ax = self.fig.add_subplot(223)
        ax.set_title("NumIterations loss")
        ax.plot(np.linspace(0,self.numIterations,self.numIterations),self.lossHistory,label='loss')
        ax.plot(np.linspace(0,self.numIterations,self.numIterations),self.thetaHistory[:,0],label='x1')
        ax.plot(np.linspace(0,self.numIterations,self.numIterations),self.thetaHistory[:,1],label='x2')
        ax.set_xlabel("numIterations")
        ax.set_ylabel("loss")
        ax.legend()

    # 绘制回归线
    def drawRegression(self):
        ax = self.fig.add_subplot(224)
        ax.set_title("Regression Line")
        ax.scatter(self.dataOX, self.dataY,label='Original Train Dataset',s = 5)
        # 对比可见,回归方程是归一化处理后的数据的回归方程,而不是原始数据的回归方程
        ax.scatter(self.dataX[:,1], self.dataY,label='Normal Train Dataset',s = 5)
        # 从训练集的最小值到最大值,取训练集数量个点绘制回归线,注意原数据需要预处理一下
        xx = LinearRegression.preHandle(np.linspace(self.dataX.min(),self.dataX.max(),self.dataSize).reshape(self.dataSize,1))
        yy = np.dot(xx ,self.theta)
        ax.plot(xx[:,-1],yy,label="Regression Line")
        ax.set_xlabel("x")
        ax.set_ylabel("y")
        ax.legend()
    """
    预处理数据,零均值归一化处理
    """
    @staticmethod
    def preHandle(data):
        normalData = np.copy(data)
        # 平均值
        mean = np.mean(normalData)
        # 方差
        std = np.std(normalData)
        normalData = (normalData - mean) / std
        normalData = np.hstack((np.ones((normalData.shape[0],1)),normalData))
        return normalData


df = pd.read_csv("./data/world-happiness-report-2017.csv")
xName = "Economy..GDP.per.Capita."
yName = "Happiness.Score"
trainDataX = df[[xName]].values
trainDataY = df[[yName]].values

linearRegression = LinearRegression(trainDataX,trainDataY)
linearRegression.train()
linearRegression.draw()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
梯度下降法和最小二乘法是常用于求解参数优化的方法。在python中,我们可以结合这两种方法来实现: 首先,我们需要导入numpy库来处理矩阵运算,以及matplotlib库用于绘图展示结果。 接下来,我们需要定义一个梯度下降函数来更新参数。假设我们有一个损失函数J,我们的目标是找到最小化损失函数的参数。梯度下降法的步骤如下: 1.初始化参数:使用随机值或者零初始化参数向量。 2.计算损失函数的梯度:计算损失函数J对参数的偏导数,即梯度。 3.更新参数:使用学习率乘以梯度,并减去更新参数。 我们还需要定义一个最小二乘法函数,用于最小化误差方程。最小二乘法的步骤如下: 1.建立线性模型:假设我们的目标是拟合一个线性模型,我们需要定义线性模型的参数向量。 2.计算预测值:使用线性模型的参数,计算出预测值。 3.计算误差:求解预测值和真实值之间的误差。 4.最小化误差:对误差进行最小二乘法优化,求得最优参数值。 最后,我们可以使用这两个函数来进行模型的训练和预测。首先,我们需要载入数据集和设置相关参数,然后使用梯度下降法更新参数,最后使用最小二乘法函数来获得最优参数,以及对新样本的预测值。 这个是简单的梯度下降法和最小二乘法结合python实现的思路,具体的实现过程可以根据实际情况进行调整和改进。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值