[机器学习-原理及实现篇]线性回归-最小二乘法_茫茫人海一粒沙的博客-程序员宅基地

技术标签: Sklearn  机器学习  

线性回归到底要干什么,顾名思义很简单,即在已有数据集上通过构建一个线性的模型来拟合该数据集特征向量的各个分量之间的关系,对于需要预测结果的新数据,我们利用已经拟合好的线性模型来预测其结果。关于线性回归的方法,现在使用得比较广泛的就是梯度下降和最小二乘法;我打算把最小二乘法和梯度下降分两篇博客来写,这篇就来说一说我对线性回归及最小二乘法的理解以及原理实现。
在这里插入图片描述

线性模型在二维空间中就是一条直线,在三维空间是一个平面,高维空间的线性模型不好去描述长什么样子;如果这个数据集能够用一个线性模型来拟合它的数据关系,不管是多少维的数据,我们构建线性模型的方法都是通用的。之前看吴恩达机器学习视频,第一节课讲的就是线性回归算法,课程里面提到了一个非常简单的案例:房屋估价系统。房屋估价系统问题就是当知道房屋面积、卧室个数与房屋价格的对应关系之后,在得知一个新的房屋信息后如何得到对应的新房屋价格,如果我们将房屋面积用x1表示,卧室个数用x2表示,即房屋价格h(x)可以被表示为房屋面积与卧室个数的一维线性方程:
在这里插入图片描述
这就是我们所说的线性模型,当然这个案例中只有房屋面积和卧室个数两个特征分量作,现实情况下我们要拟合的模型可能有相当多的特征分量,那么线性模型中对应的权重值θ也会有相同多的数量。为了方便表示我们使用矩阵和向量来表示这些数据
在这里插入图片描述
向量θ(长度为n)中每一个分量都是估计表达式函数h(x)中一个参数,矩阵X(m*n)表示由数据集中每一个样本的特征向量所组成的矩阵。其实这样一个看起来很简单的式子,它的本质经常就是一个规模极其庞大的线性方程组。如果我们用向量Y(长度为m)来表示数据集的实际值,如果用实际值来建立一个方程组,参数向量θ中的每一个值就是我们要求的未知量;大多数情况下建立的是一个超定方程组(没有确定的解),这个时候我们只能求出超定方程组的最优解。通过建立一个损失函数来衡量估计值和实际之间的误差的大小,我们将最小化损失函数作为一个约束条件来求出参数向量的最优解。
在这里插入图片描述


函数J(θ)即为损失函数,它计算出数据集中每一个样例的估计值和实际值的平方差并求取平均。然后就是我们的最小二乘法登场了,最小二乘法通过数学推导(后面给出证明)可以直接得到一个标准方程,这个标准方程的解就是最优的参数向量。

推导方法一

最小二乘法通过数学推导出标准方程的过程其实非常简单,知乎上有一篇博客https://zhuanlan.zhihu.com/p/22474562写得很详细,这里借鉴一下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


推导方法二

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

推导方法三 (利用Hessian矩阵判断是否是极小值点)

在这里插入图片描述

通过正规方程计算得到最优的参数向量之后,就可以确定线性回归方程了,预测只需要将特征向量代入到回归方程之中,就可以计算出估计值了。

既然弄清了原理,那么实现就会显得非常简单;考虑到这个算法过程中使用矩阵乘法的次数很多,所以我使用了python语言以及调用numpy库来实现线性回归的算法,这里使用了sklearn库中的波士顿房价数据集,代码如下


import numpy as np
from sklearn.datasets import load_boston  # 导入博士顿房价数据集
from sklearn import linear_model

class LinerRegression:
    M_x = []  #
    M_y = []  #
    M_theta = []  # 参数向量
    trained = False

    def __init__(self):
        pass

    def regression(self, data, target):
        self.M_x = np.mat(data)
        # 每个向量添加一个分量1,用来对应系数θ0
        fenliang = np.ones((len(data), 1))
        self.M_x = np.hstack((self.M_x, fenliang))
        self.M_y = np.mat(target)
        M_x_T = self.M_x.T  # 计算X矩阵的转置矩阵
        self.M_theta = (M_x_T * self.M_x).I * M_x_T * self.M_y.T  # 通过最小二乘法计算出参数向量
        print('Start to train it with my own implementation of liearRegression')
        print(self.M_theta)
        self.trained = True

    def predict(self, vec):
        if not self.trained:
            print("You haven't finished the regression!")
            return
        M_vec = np.mat(vec)
        fenliang = np.ones((len(vec), 1))
        M_vec = np.hstack((M_vec, fenliang))
        estimate = np.matmul(M_vec, self.M_theta)
        return estimate

def test_my_linear_regression():
    # 从sklearn的数据集中获取相关向量数据集data和房价数据集target
    data, target = load_boston(return_X_y=True)
    lr = LinerRegression()
    lr.regression(data, target)
    # 提取一批样例观察一下拟合效果
    test = data[::51]
    M_test = np.mat(test)
    real = target[::51]  # 实际数值real
    estimate = np.array(lr.predict(M_test))  # 回归预测数值estimate
    # 打印结果
    for i in range(len(test)):
        print("实际值:", real[i], " 估计值:", estimate[i, 0])

def test_sklearn_liear_regression():
    data, target = load_boston(return_X_y=True)
    clf = linear_model.LinearRegression()
    clf.fit(data, target)
    print('Start to train it with Sklearn ')
    print(clf.coef_)
    print(clf.intercept_)

if __name__ == '__main__':
    test_sklearn_liear_regression()
    test_my_linear_regression()

运行结果如下:

Start to train it with Sklearn 
[-1.08011358e-01  4.64204584e-02  2.05586264e-02  2.68673382e+00
 -1.77666112e+01  3.80986521e+00  6.92224640e-04 -1.47556685e+00
  3.06049479e-01 -1.23345939e-02 -9.52747232e-01  9.31168327e-03
 -5.24758378e-01]
36.45948838509001
Start to train it with my own implementation of liearRegression
[[-1.08011358e-01]
 [ 4.64204584e-02]
 [ 2.05586264e-02]
 [ 2.68673382e+00]
 [-1.77666112e+01]
 [ 3.80986521e+00]
 [ 6.92224640e-04]
 [-1.47556685e+00]
 [ 3.06049479e-01]
 [-1.23345939e-02]
 [-9.52747232e-01]
 [ 9.31168327e-03]
 [-5.24758378e-01]
 [ 3.64594884e+01]]
实际值: 24.0  估计值: 30.003843377016256
实际值: 20.5  估计值: 23.97222284868958
实际值: 18.6  估计值: 19.79013683546337
实际值: 19.4  估计值: 17.286018936122648
实际值: 50.0  估计值: 43.18949843697001
实际值: 20.9  估计值: 21.695808865539043
实际值: 33.4  估计值: 35.56226856966765
实际值: 21.7  估计值: 22.718066074783085
实际值: 17.2  估计值: 13.70756369210629
实际值: 20.0  估计值: 18.51247609292085

可以看到用Sklearn里LinearRegarssion训练得到的参数其实和我实现的结果是一样的。
另外
绝大多数样例通过线性回归模型预测的结果与真实结果十分接近,但是存在有一定的误差,可以接受。

参考资料
https://blog.csdn.net/qq_32864683/article/details/80488523
https://blog.csdn.net/perfect_accepted/article/details/78383434

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/keeppractice/article/details/106860754

智能推荐

CSS DIV 上下左右完全全屏居中-程序员宅基地

CSS DIV 全屏居中,center { position: absolute; width: 800px; height: 520px; margin: auto; top: 0; left: 0; bottom: 0; right: 0; background-color: #ffffff; overflow-x: hidden; overflow-y: hidden;}资料来源

estemplate 导入MySQL_datax从mysql同步数据到elasticsearch(使用es的动态模板)-程序员宅基地

elasticsearch中设置动态模板PUT _template/hkey_transferbill{"index_patterns": "hkey_transferbill","settings": {"number_of_shards": 2,"number_of_replicas": 1},"mappings": {"data":{"dynamic_templates" : [ {"key..._es 迁移数据到mysql

02crm代码托管码云_国内永久免费crm代码-程序员宅基地

1.搭好框架后将代码进行代码托管1.idea安装gitee码云的插件2.安装好插件后从idea登录码云3.随便写点什么进行提交4.提交完成后若要更新先push_国内永久免费crm代码

ios因难缠的付费聊天原因被拒N天_苹果付费聊天上架-程序员宅基地

2019年12月底,有其他公司的同事前来请求协助,说他们的app反复被拒一个月了,想让我们帮忙看一下问题出在哪。看了一下他们的后台,苹果指出他们多条违规:1.1用户安全,5.0法律-促进有偿陪聊,2.3.1-Performance-hidden features,3.1.1支付问题…还有一些其他零零碎碎的小问题。这是我第一次遇到因为付费聊天被拒的实际案例,天真的以为不会落在我们头上…正好赶上..._苹果付费聊天上架

数据结构之内部排序--希尔排序_数据结构奇数个关键字怎样进行希尔排序-程序员宅基地

概要-IDE:Pycharm -Python版本:python3.x -算法分类:内部排序->插入类排序->希尔排序算法思想希尔排序又称缩小增量排序法,是一种基于插入思想的排序方法。它利用了直接插入排序的最佳性质,首先,将待排序的关键字序列分成若干个较小的序列,对子序列进行直接的插入排序,使整个待排序列排好序。 过程如下: 1.首先选定记录间的距离di(i=1)d..._数据结构奇数个关键字怎样进行希尔排序

python登录界面实现密码在明文与星号间切换_Python 隐藏输入密码时屏幕回显的实例...-程序员宅基地

我们再登录账号密码的时候,账号可以回显在屏幕上,但是对于比较隐私的项目例如密码最好是不要再屏幕上回显。就像我们再终端登录linux服务器的时候,输入信息的时候只显示用户名,而不显示登录密码。以下是Python代码对比:1、明文回显账号密码##代码[root@room1pc01 data]# cat login1.py#!/usr/bin/env python2.6username = raw_in...

随便推点

python ogr_解决python ogr shp字段写入中文乱码的问题-程序员宅基地

首先,先确认一下你的字段值是不是乱码,如果是,按照以下方法:我的字段值是来自于一个geojson字符串,我在对它解析时做了如下处理:properties = fea.get("properties")pro_json=json.dumps(properties)pro_json.replace('u\'','\'')#将unicode编码转化为中文先处理一下pro_json=pro_json.de..._ogr 中文乱码

如何在阿里云轻量服务器上部署javaweb项目?_启动文件是sh格式的项目如何在云服务器部署-程序员宅基地

最近由于项目需求,需要把项目部署到服务器上,所以选择阿里云服务器来进行操作,并在这里给大家分享一下部署的过程。第一步,购买服务器我这里购买的配置是轻量级服务器,预装环境是wordPress第二步,进入自己所购买的服务器控制台一般购买服务器后都会要求输入新的密码,用户名一般为root 。这里记下服务器的用户名和密码,后面会用到。第三步,下载XftpXftp是一款文件传输软件工具,它能..._启动文件是sh格式的项目如何在云服务器部署

Docker安装Mysql8_docker mysql8安装插件-程序员宅基地

CentOS 7.9 安装Docker搜寻仓库里面有那些镜像docker search mysql我们拉取mysql:latest的镜像docker pull mysql:latest查看镜像但是我们不知道mysql的具体版本号,我们使用docker inspect 命令来获取容器/镜像的元数据。然后将这些数据输入到grep 命令来查找version的字符串-i 或 --ignore-case : 忽略字符大小写的差别docker image inspect mysql:late_docker mysql8安装插件

记一次让自家旧主板支持M2接口固态硬盘的折腾记录_老主板pcie转m2做系统盘-程序员宅基地

首先这篇文章是针对小白的,大神可以绕路,大神可以绕路,大神可以绕路,重要的事情说三遍!也不要问我太多高精尖的问题,我只是借用了大神已攻克的问题,甚至为了偷懒,用了很多他们的图片,只是大神虽然都做到了,但是身为小白的我在逐步操作的过程中,还是遇到了很多问题,本着好记性不如烂笔头的想法,我决定记录下来。 旧主板上是没有m2接口的,所以购买了NVMe固态的小伙伴可能还需要购买一块PCIE转接卡,..._老主板pcie转m2做系统盘

Carson带你学Android:源码解析 Dialog的窗口机制_android dialog原理-程序员宅基地

本文将通过 Dialog 的创建、展示 & 销毁过程源码, 详细说明 Dialog 的窗口机制_android dialog原理

自定义“树”节点 (前端框架:layui+SpringMVC整合)_springmvc layui 修改-程序员宅基地

自定义“树”节点 (前端框架:layui+SpringMVC整合)_springmvc layui 修改