python实现一元线性回归

这个专栏主要是自己用python入门深度学习和图像识别的一些学习笔记和心得体会。既有一些算法理论的理解,也有python代码的实现,争取对一个问题做到知其然并知其所以然,理论和实践并进。大家一起加油!栏目的框架主要从最基础的机器学习开始,到神经网络的基础,再用pytorch实现图像分类,目标检测,分割,产生式模型等。使用的工具主要是numpy和pytorch。

1.线性回归模型介绍

线性回归是机器学习中最为简单的模型。首先介绍两个概念,线性和回归。

线性:即变量之间的关系为一次函数,也就是说当因变量x和自变量y的关系画在平面上是一条直线。

回归:即预测一个连续问题的数值。举个很简单的例子,假设已知我国过去五个年份的人口,可以预测未来几年的人口。就是根据年份和人口数量可能呈线性关系来预测拟合的。

因此一元线性回归就很好理解了,就是我们的自变量和因变量只有一个。(例如例子里的年份和人口),当自变量有多个的时候(例如每个人的年龄,收入),一元线性回归就拓展成了多元线性回归。

2.一元线性回归最直观数学理解

讲白了,一元线性回归要我们干的事情就是你已知了一大堆互相对应的x和y,(并且发现了他们之间是近似于线性关系的,可以通过画散点图来看,spss非常方便!),你希望对于未知的x,你也能预测出对应的y。

用数学模型表示就是y=a*x+b,你希望在训练过程中求解出那个最完美的a,b,得到a,b后,你再来一个新的x值,预测的y值也是比较准确的。

那么最直观地想法就是我需要让我的预测值和真实值差值最小。即求min(y_predict-y),乍一眼看去没问题。但是你细细一想,y_predict一定是有正有负的,累计求和后正负是会抵消的,这显然与现实不符。

那马上就会想到,求(|y_predict-y|),这是没有问题的,但是我们要求参数的最小值必然要求导。绝对值函数我们知道它是不连续的,故无法求导又舍弃了。

因此,最完美的方法就是求sum((y_predict-y)^2)/n,这里就是对预测值和真实值的差求平方,因为有多个值,我们对他求和后除以样本的数量。

再把y=a*x+b带入就得我们的目标式子,专业名词叫误差函数:

在这里插入图片描述

那么我要去求参数a和b的最小值,就是分别对a和b求偏导。推导的过程就不列了,各大博客都有,这里直接给出结果:

在这里插入图片描述
在这里插入图片描述

这里的x_mean,y_mean就是平均值。至此,我们训练的任务也就完成了。

那么下一步就是需要对我们的模型做个评估,它究竟准确率如何呢?我们可以通过前面的误差函数来打分,但这里给出一个更为科学的评估函数,专门针对线性函数的R Square,也叫拟合优度。

在这里插入图片描述
这个公式科学在哪呢,仔细观察发现它的分子衡量的是y的预测值和真实值之间的差,分母衡量的是y的平均值和y的差,分母代表的是基准模型。也就是说当我们的模型预测出的值和基准模型一样时,r_square=0,当模型预测值和真实值一模一样,r_square=1,如果r_square<0,说明连基准模型都达不到。

3.python实现一元线性回归

有了理论的公式推导,我们完全可以实现它,总体思路如下:
1.将一元线性回归封装到类中
初始化参数a,b
训练函数,训练出a,b
预测函数,对于给定的x向量,可以输出y_predict
打分函数,利用r_square评估我们的模型
2.在主函数中输入数据集进行测试,并画出散点图

代码和注释如下:


```python
import numpy as np
import matplotlib.pyplot as plt

class SingleLinearRegression:
    def __init__(self):   #初始化a,b
        self.a_=None;
        self.b_=None;

    def fit(self,x_train,y_train):  #训练函数,训练出a,b
        x_mean = np.mean(x_train)
        y_mean = np.mean(y_train)  # 求x和y的平均值

        fenzi = 0.0;
        fenmu = 0.0;  # 对分子分母初始化
        for x_i, y_i in zip(x_train, y_train):  # 将x,y打包成元组的形式
            fenzi += (x_i - x_mean) * (y_i - y_mean)  # 根据最小二乘法求出参数
            fenmu += (x_i - x_mean) ** 2

        self.a_ = fenzi / fenmu
        self.b_ = y_mean - self.a_ * x_mean  #得到a,b

        return self

    def predict(self,x_test_group):  #预测函数,用户输入一组x(为一维向量),可以进行y的预测
        result=[]  #初始化一个列表,用来储存预测的y值
        for x_test in x_test_group:  #对于每个输入的x都计算它对应的预测y值并加入列表中
            result.append(self.a_*x_test+self.b_)
        y_predict=np.array(result)  #将列表转换为矩阵向量形式方便运算

        return y_predict

    def r_square(self,y_true,y_predict):  #打分函数,评估该模型的准确率
        mse=np.sum((y_true-y_predict)**2)/len(y_true)  #计算均方误差mse
        var=np.var(y_true)  #计算方差
        r=1-mse/var #计算拟合优度r的平方
        return r

if __name__=='__main__':
    x = np.array([1, 2, 4, 6, 8])
    y = np.array([2, 5, 7, 8, 9])
    l=SingleLinearRegression()  #创建一个对象,接下来调用对象的方法
    l.fit(x,y)
    print('6,8对应的的预测值是:')
    print(l.predict([6,8]))
    print('该模型的评估分数为:')
    print(l.r_square([8,9],l.predict([6,8])))

    #画出散点图和预测图
    plt.scatter(x, y, color='b')  # 画出原来值得散点图
    plt.plot(x,l.predict(x), color='r')  # 画出预测后的线

    plt.xlabel('x')  # 写上标签
    plt.ylabel('y')

    plt.show()  # 作图函数

结果是:
在这里插入图片描述
在这里插入图片描述

3.心得体会与收获

一元线性回归无论是原理理解还是代码实现应该都不太难,但是在代码实现中还是涉及到一些技巧,例如:

1.模型都应该封装到类中,一些需要训练的参数在类中初始化并训练。

2.可以使用python语法的zip将两对向量打包成元组的形式便于计算。

3.此题中的r_square可以转化为误差函数/方差的形式便于编程。

基本就这些,下一篇准备在一元线性回归的基础上更进一步,实现多元线性回归。

  • 9
    点赞
  • 68
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值