python-机器学习-波士顿房价回归分析

一、目的 

        以波士顿房价数据集为对象,理解数据和认识数据,掌握梯度下降法回归分析的初步方法,掌握模型正则化的一般方法,对回归分析的结果解读。


二、背景知识与要求

1、背景知识

        波士顿房价数据集是20世纪70年代中期波士顿郊区房价的中位数,统计了当时城市的13个指标与房价的数据,试图能找到那些指标与房价的关系。

        在数据集中包含506组数据,本文将前406个作为训练和验证集,剩下的100组数据作为测试集。数据在python的sklearn库的datasets中可以load_boston直接调用,也可以在下面的地址中下载。

        数据集下载地址:https://archive.ics.uci.edu/ml/machine-learning-databases/housing/。

        数据集中各特征的含义如下:


        我们所说的回归一般指的是线性回归(Linear regression)。回归能用来做什么呢?我们做回归是想找到变量与变量之间的关系,比如销售量与运输距离的关系,或者次品数量与机床使用时长之间的关系,或者寻找名人的离婚率与年龄之间的关系。

        回归的目的就是预测数值型的目标值,假如你要预测一台汽车功率的大小,可能会写出如下方程:

        P=0.0015*S-0.99*R

        其中,P代表功率,S代表年薪,R代表你收听电台的时长,这就是回归方程(regression equation),其中0.0015和-0.99称为回归系数(regression weights)或者说每个自变量影响因变量的权重,当然也有非线性回归,比如认为是S与R的乘积,我们这里所说的回归是线性回归,线性回归的一般方程如下,当然也包括Y的初始值(截距),如果没有即为0:

        Y=WX^{T}+C

        输入的数据存放在矩阵X中,回归系数存放在向量W中,那么我们所要做的就是求出W,怎么求出W呢?最常用的就是找出误差最小下的W,这里所说的误差指的是预测值与真实值之间的误差,如果二者相减所得的值再求和就会出现正值与负值相抵消的情况,所以采用平方误差,即:

        \sum_{i=1}^{m}(y_{i}-wx_{i}^{T})^{2}

        我们所要做的就是使其最小,也即找到最优的w估计值,这是统计学中最常见的问题,有很多方法如最小二乘估计或者最优化方法中的梯度下降法等,本文着重于梯度下降法,其他的这里就不一一列举。

        回归的一般步骤如下:

(1)收集数据:采用任意方法

(2)准备数据:回归需要的是数值型数据,标称型数据需要转换成二值型数据,如果有多个类别可以考虑采用独热编码(one-hot)

(3)分析数据:如果可以的话,绘出数据可视化的二维图像有助于对数据做出分析和理解与前后对比

(4)训练算法:找到回归系数,可以运用多种方法。

(5)测试算法:采用决定系数R^{2}或者预测值与数据的拟合度作为定量评判的标准

(6)使用算法:使用建立好的回归方程对于输入的变量进行预测,给出一个预测值。


        我们要找到平方误差的最小值,采用的方法是梯度下降法,也被叫做梯度上升法,该方法的思想是:要找到某函数的最小值(最大值),最好的方法是沿着梯度方向探寻,那么梯度是什么呢?如果是关于x的一元函数,那么梯度就是它的导数,在数学上,梯度的定义如下:

                                                \bigtriangledown f(x,y)=\binom{\frac{\partial f(x,y)}{\partial x}}{\frac{\partial f(x,y)}{\partial y}}

        我们把梯度记为\triangledown,梯度总是指向函数值增长最快的方向(反方向即减小最快的方向),但这里梯度仅仅指示方向,而未说明沿着这个方向走多少距离,我们用\alpha记作走的距离,即步长,那么梯度下降算法的迭代公式就很容易写出来:

                                                w:=w-\alpha \bigtriangledown _{_{w}}f(w)

        该公式被一直运行直到到达某个条件为止(如误差小于某个值时)。梯度上升算法只需要把中间的-号改成+号就行,梯度上升算法被用来求函数的最大值,而梯度下降被用来求最小值。


        刚刚我们说到,我们循环迭代梯度下降算法的目的就是让平方误差最小(或者小于一定范围),而我们把平方误差除以样本数量m。即:

                                                L(y,y^{`})=\frac{1}{m}\sum_{i=1}^{m}(y-y^{`})^{2}

        这被称为均方误差(MSE),也有另一种为平均绝对误差(MAE):

                                                L(y,y^{`})=\frac{1}{m}\sum_{i=1}^{m}\left | y-y^{`}\right |

        线性回归中,MSE(L2损失)计算简便,但MAE(L1损失)对异常点有更好的鲁棒性。当预测值和真实值接近时,误差的方差较小;反之误差方差非常大,相比于MAE,使用MSE会导致异常点有更大的权重,因此数据有异常点时,使用MAE作为损失函数更好,而RMSE就是在MSE的基础上再开根号。

        损失函数(loss function)就是用来度量模型的预测值y^{^{`}}  与真实值y的差异程度的运算函数,它是一个非负实值函数,通常使用L(y,y^{`})  来表示,损失函数越小,模型的拟合程度就越好。正则化(Regularization)就是在损失函数上加上某些规则(限制),缩小解空间,从而减少求出过拟合解的可能性(比如模型为了使损失函数最小,拟合出来的函数并不光滑,导致过拟合),具体方法就是不让损失函数中高次变量的参数大小不能太大,下面给出了一个例子:

        假设我的回归方程是:y=w_{1}x_{1}+w_{2}x_{2}^{5},那么为了使高次变量的参数大小不能太大,我们可以把损失函数写作如下形式:

                                                L(y,y^{`})=\frac{1}{m}\sum_{i=1}^{m}(y-y^{`})^{2}+1000w_{2}

        为了使损失函数最小,我们只能让w_{_{2}}极小,这样就实现了正则化,那么一般我们把前面的系数1000记作\lambda,而各个w有正有负,所以我们取平方,这样就有了损失函数的一般形式:

                        ​​​​​​​        ​​​​​​​        ​​​​​​​        L(y,y^{`})=\frac{1}{2m}[\sum_{i=1}^{m}(y-y^{`})^{2}+\lambda \sum_{j=1}^{n}w_{j}^{2}]

        相应的,梯度的公式也会随之变化,为了更好的计算梯度,在求导的时候可以约简,这里把\frac{1}{m}写成\frac{1}{2m},对于整体来说无太大影响,w的更新函数如下,即对上式求梯度再乘以\alpha(往梯度方向走\alpha步):

                                                w=w-\alpha [\frac{1}{m}(wx^{T}x-y^{T}x)-w\frac{\lambda }{m}]


2、要求

        要求回答以下问题

  1. 模型的错误率如何?以MSE,RMSE为例。
  2. 随着梯度下降法迭代的进行,错误率是如何变化的?画图表示。
  3. ​​​​​​​模型的正则化项对模型结果的影响如何?请画图(用横坐标表示正则化项的权重,纵坐标表示MSE)说明是如何选择正则化项的。
  4. 怎么对输入特征进行预处理(特征选择、行归一化、列归一化)。
  5. 编写程序实现模型的训练和测试,不使用SPSS或者调用其它机器学习的工具包实现。​​​​​​​​​​​​​​

 三、python代码实现

        首先导入相关库:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import load_boston

        先把数据存成csv格式并简单的查看一下数据:

boston = load_boston()
df = pd.DataFrame(boston.data, columns=boston.feature_names)
df['MEDV'] = boston['target']
df.to_csv('./boston.csv', index=None)
data = pd.read_csv(r'./boston.csv')
data.head()

        结果如下:

         查看数据是否存在空值:

data.isnull().sum()

        发现不存在空值。

        查看一下数据的行列数:

data.shape

        可以看出数据是506行*14列,由于各个特征值之间的量纲不同,为了消除量纲的影响,进行数据的规范化处理,有三种规范化方法:最大最小规范化、标准差规范化和十进制规范化。   ​

        各个规范化的代码如下表示:

(data - data.min())/(data.max() - data.min())   #最小-最大规范化
(data - data.mean())/data.std()                 #标准差规范化
data/10**np.ceil(np.log10(data.abs().max()))    #十进制规范化

        本文选择采用标准差规范化,规范化完成之后对训练集和测试集进行划分,选取前400行作为训练集,剩余的106行作为测试集:

cols = data.shape[1]                 # cols为data的列数
# 选取前400作为训练集
train_x = data.iloc[:400,:cols-1]    # 选取前13列作为因变量
train_y = data.iloc[:400,cols-1:cols]# 选取最后一列作为自变量
# 选取后106行作为测试集
test_x = data.iloc[400:,:cols-1]     
test_y = data.iloc[400:,cols-1:cols]

        数据的收集和准备工作已经做好了,接下来建立线性回归模型,定义一个线性模型的类:

class linearRegression:
    """python语言实现线性回归(梯度下降法)"""
    
    def __init__(self, alpha, times, l):
        """初始化方法
        
        参数解释:
        alpha:float
               步长,也被叫做学习率(权重调整的幅度)
        times: int
                循环迭代的次数,达到一定次数终止迭代
        l: int
                正则化参数
                
        """
        self.alpha = alpha
        self.times = times
        self.l= l
        
    # 损失函数
    def CostFunction(self, x, y, w):
        inner = np.power(y-(w*x.T).T, 2)
        return np.sum(inner)/(2*len(x))
    
    # 正则化损失函数
    def regularizedcost(self, x, y, w):
        reg = (self.l/(2*len(x))) * (np.power(w, 2).sum())
        return self.CostFunction(x, y, w) + reg     
    
    def fit(self,x,y):
        """建立模型
        
        参数解释:
        x:自变量,特征矩阵
        y:因变量,真实值
        """
        # 将数据转换成numpy矩阵
        x = np.matrix(x.values)
        y = np.matrix(y.values)
        # 添加截距列,值为1,axis=1 添加列
        x = np.insert(x,0,1,axis=1)
        # 创建权重向量W,初始值默认为0,长度比特征数量多1(多出的一项为截距)。
        self.w_ = np.zeros(x.shape[1])
        # 创建损失列表,用来保存每次迭代后的损失值。
        self.loss_ = []
        
        #进行times次数的迭代,在每次迭代过程中,计算损失值,不断调整权重值,使得损失值不断下降。
        for i in range(self.times):
            # 计算正则化损失函数值:
            loss = self.regularizedcost(x, y, self.w_)
            #加入到损失列表
            self.loss_.append(loss)
            # 根据步长调整权重w_
            self.w_ = self.w_ - (self.alpha / len(x)) * (self.w_  * x.T * x   - y.T * x) - (self.alpha * self.l / len(x)) * self.w_

    def predict(self, x):
        """根据参数传递的样本,对样本数据进行预测
        
        参数解释:
        x:测试样本。
        
        返回值:
        result:预测结果。
        """
        
        x = np.asarray(x)
        x = np.insert(x,0,1,axis=1)
        result = np.dot(x, self.w_.T) 
        return result

建立线性回归模型,设置初始参数,求出错误率(误差值):

alpha=0.001
times=10000
l=0
lr = linearRegression(alpha,times,l)
lr.fit(train_x,train_y)
MSE = lr.loss_
RMSE = list(map(lambda num:sqrt(num), lr.loss_))

查看一下结果和在测试集上的表现情况:

result = lr.predict(test_x)
# 为了防止画图出现中文乱码设置字体参数
rcParams["font.family"] = "SimHei"
rcParams["axes.unicode_minus"] = False
plt.figure(figsize=(10,10))
plt.plot(result, "ro-", label="预测值")
plt.plot(test_y.values, "go-", label="真实值") # pandas读取时serise类型,我们需要转为ndarray
plt.title("线性回归预测-梯度下降")
plt.xlabel("样本序号")
plt.ylabel("预测房价")
plt.legend()
plt.show()

 

出错误率(MSE)随迭代次数变化的图象:

fig, ax = plt.subplots(figsize=(20,10))
ax.plot(np.arange(times), MSE, 'r') # np.arange()返回等差数组
ax.set_xlabel('迭代次数')
ax.set_ylabel('错误率(MSE)')
ax.set_title('错误率(MSE)随迭代次数变化的图象')
plt.show()

 画出错误率(RMSE)随迭代次数变化的图象:

fig, ax = plt.subplots(figsize=(20,10))
ax.plot(np.arange(times), RMSE, 'r') # np.arange()返回等差数组
ax.set_xlabel('迭代次数')
ax.set_ylabel('错误率(RMSE)')
ax.set_title('错误率(RMSE)随迭代次数变化的图象')
plt.show()

 画出错误率(MSE)随正则化项的权重变化的图象:

MSE_ = []
for l_ in range(0,l):
    lr = linearRegression(alpha,times,l_)
    lr.fit(train_x,train_y)
    MSE_.append(lr.loss_[-1])
fig, ax = plt.subplots(figsize=(20,10))
ax.plot(np.arange(l), MSE_, 'r') # np.arange()返回等差数组
ax.set_xlabel('正则化项权重')
ax.set_ylabel('错误率(MSE)')
ax.set_title('错误率(MSE)随正则化项的权重变化的图象')
plt.show()

大功告成。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/115949.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ElasticSearch集群架构实战及其原理剖析

ES集群架构 为什么要使用ES集群架构 分布式系统的可用性与扩展性: 高可用性 服务可用性:允许有节点停止服务;数据可用性:部分节点丢失,不会丢失数据; 可扩展性 请求量提升/数据的不断增长(将数据分布…

【从零开始学习Redis | 第四篇】基于延时双删对Cache Aside的优化

前言: 在如今的单体项目中,为了减轻大量相同请求对数据库的压力,我们采取了缓存中间件Redis。核心思想为:把数据写入到redis中,在查询的时候,就可以直接从Redis中拿取数据,这样我们原本对数据库…

竞赛选题 深度学习手势检测与识别算法 - opencv python

文章目录 0 前言1 实现效果2 技术原理2.1 手部检测2.1.1 基于肤色空间的手势检测方法2.1.2 基于运动的手势检测方法2.1.3 基于边缘的手势检测方法2.1.4 基于模板的手势检测方法2.1.5 基于机器学习的手势检测方法 3 手部识别3.1 SSD网络3.2 数据集3.3 最终改进的网络结构 4 最后…

有方N58 HTTP POST 请求连接 TDengine

串口调试软件:格西调试精灵 第一步先注册网络获取IP地址 建立PPP连接 ATXIIC1\r PPP链路建立成功,查询IP地址 ATXIIC?\r 设置网络APN ATCREG?\r 运行结果,红线处是获…

Whisper 从0安装教程 windows

这里写自定义目录标题 Whisper 从0安装教程 windows安装过程安装python3.11安装Anaconda在Anaconda里面安装whisper安装 ffmpeg第一次运行whisper检查GPU 一些弯路 Whisper 从0安装教程 windows 因为需要把语音变成文字稿,问了做语言相关的朋友,决定使用…

结合组件库实现table组件树状数据的增删改

如图所示&#xff0c;可以实现树状数据的新增子项&#xff0c;新增平级&#xff0c;删除。主要用到了递归 代码&#xff1a; <template><el-table :data"tableData" style"width: 100%; margin-bottom: 20px" row-key"id" border def…

redis缓存击穿,redisson分布式锁,redis逻辑过期

什么是缓存击穿&#xff1a; 缓存击穿是指在高并发环境下&#xff0c;某个热点数据的缓存过期&#xff0c;导致大量请求同时访问后端存储系统&#xff0c;引起系统性能下降和后端存储压力过大的现象。 解决方案&#xff1a; 1. redisson分布式锁 本质上是缓存重建的过程中&…

selenium自动化测试入门 —— 操作元素对象

一、元素的常用操作 element.click() # 单击元素&#xff1b;除隐藏元素外&#xff0c;所有元素都可单击 element.submit() # 提交表单&#xff1b;可通过form表单元素提交表单 element.clear() # 清除元素的内容&#xff1b;如果可以的话 element.send_keys(‘需要输入的…

基于动力学模型的机械臂pid控制

参考资料&#xff1a; 一、如何实现机械臂的控制 在最常见的对机械臂动力学实现控制的问题中&#xff0c;我们会有一段机械臂末端的期望轨迹S&#xff0c;希望通过对机械臂关节处电机转矩的控制实现末端沿期望轨迹的完美运动。控制问题主要分为镇定和跟踪两种&#xff0c;上面…

LabVIEW实现变风量VAV终端干预PID控制

LabVIEW实现变风量VAV终端干预PID控制 变风量&#xff08;VAV&#xff09;控制方法的研究一直是VAV空调研究的重点。单端PID控制在温差较大时&#xff0c;系统容易出现过冲。针对空调终端单端PID控制的不足&#xff0c;设计一种干预控制与PID控制耦合的控制方法。项目使用LabV…

利用shp文件构建mask【MATLAB和ARCGIS】两种方法

1 ARCGIS &#xff08;推荐&#xff01;&#xff01;&#xff01;-速度很快&#xff09; 利用Polygon to Raster 注意&#xff1a;由于我们想要的mask有效值是1&#xff0c;在进行转换的时候&#xff0c;注意设置转换字段【Value field】 【Value field】通过编辑shp文件属性表…

el-table样式

1、实现效果&#xff0c;外部框是蓝绿色边框&#xff0c;深色背景&#xff0c;里面的表格首先设置透明色&#xff0c;然后应用自定义斑马纹。 2、代码 template代码&#xff0c;其中样式frameBordStyle是深色背景框&#xff0c;不负责表格样式&#xff0c;表格样式由tableStyl…

OSG多视口创建:osgViewer::CompositeViewer

1、效果 在osg的实际应用场景中&#xff0c;有时候需要同时创建多个场景视图&#xff0c;并保证各个场景视图中有不一样的显示和操作&#xff1a;例如&#xff1a;漫游器、照相机、粒子效果、多个模型组合等。此时就要用到OSG提供的osgViewer::CompositeViewer类来实现这个需求…

零信任网络:一种全新的网络安全架构

随着网络技术的不断发展&#xff0c;网络安全问题日益凸显。传统的网络安全策略往往基于信任和验证&#xff0c;但这种信任策略存在一定的局限性。为了解决这一问题&#xff0c;零信任网络作为一种全新的网络安全架构&#xff0c;逐渐受到人们的关注。本文将对零信任网络的概念…

推荐PHP付费进群源码

PHP付费进群源码带自动定位基于ThinkPHP框架开发的&#xff0c;可以快速搭建知识付费粉丝进群。 更新&#xff1a; 1.首页付款轮播 2.城市定位功能 3.更新及优化域名库及支付设置 4.新增一张图模板设置模式&#xff0c;简化后台模板设置 5.前后台其他优化 演示地址&#xff1a…

centos7部署nginx

CentOS7安装Nginx-1.16.1稳定版 小白教程&#xff0c;一看就会&#xff0c;一做就成。 1.安装依赖环境 yum -y install gcc gcc-c automake pcre pcre-devel zlib zlib-devel openssl openssl-devel 2.下载安装包&#xff08;不能联网的不行&#xff09;&#xff0c;可以留言…

电路正负反馈,电压电流反馈,串并联反馈详细判别方法

正/负反馈&#xff1a;假设输出升高&#xff0c;转一圈回来仍使其升高就是正反馈&#xff0c;反之就是负反馈。作图法&#xff1a;在RL的信号端画一个向上的小箭头&#xff0c;沿着反馈环路&#xff0c;每经过一个元器件就画一个相应的箭头&#xff0c;一直画到放大器的输出端&…

计算机组成与结构-安全性和可靠性

系统可靠性分析 概念 平均无故障时间 MTTF 1/失效率 平均故障修复时间 MTTR1/修复率 平均故障间隔时间 MTBFMTTFMTTR 系统可用性 MTTF/(MTTFMTTR)*100% 计算 串联系统 一个设备不可靠&#xff0c;整个系统崩溃RR1R2Rn 并联系统 所有设备不可靠&#xff0c;整个系统崩溃R1-(1…

基于单片机的商场防盗防火系统设计

收藏和点赞&#xff0c;您的关注是我创作的动力 文章目录 概要 一、系统分析二、系统总设计2.1基于单片机的商场防火防盗系统的总体功能2.2系统的组成 三 软件设计4.1软件设计思路4.2软件的实现4.2.1主控模块实物 四、 结论五、 文章目录 概要 本课题设计一种商场防火防盗报警…

Quartus II 13.0波形仿真(解决无法产生仿真波形问题)

目录 前言 新建工程 创建Verilog文件&#xff0c;写代码 波形仿真&#xff08;解决没有输出波问题&#xff09; 前言 这么说把Quartus II 13.0是我目前来讲见过最恶心的软件&#xff0c;总是一大堆麻烦事&#xff0c;稍微哪里没弄好就后面全都出问题。很多人在写完Verilog代…