机器学习实验2——线性回归求解加州房价问题

news2024/10/6 1:38:03

文章目录

    • 🧡🧡实验内容🧡🧡
    • 🧡🧡数据预处理🧡🧡
      • 代码
      • 缺失值处理
      • 特征探索
      • 相关性分析
      • 文本数据标签编码
      • 数值型数据标准化
      • 划分数据集
    • 🧡🧡线性回归🧡🧡
      • 闭合形式参数求解原理
      • 梯度下降参数求解原理
      • 代码
      • 运行结果
    • 🧡🧡总结🧡🧡

🧡🧡实验内容🧡🧡

基于California Housing Prices数据集,完成关于房价预测的线性回归模型训练、测试与评估。

🧡🧡数据预处理🧡🧡

代码

"""
    数据预处理
"""
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

df=pd.read_csv("data/housing.csv")
df.info()

### =====================填充缺失值=====================
print(df.isna().sum())
median_bedrooms = df['total_bedrooms'].median()
df['total_bedrooms'].fillna(median_bedrooms, inplace=True)

### =====================特征探索=====================
df.hist(bins=50,figsize=(20,15),edgecolor="black")
plt.show()

### =====================相关性分析=====================
corr_matrix=df.corr()
corr_matrix['median_house_value'].sort_values(ascending=False)

### =====================组合特征=====================
df['population_per_household']=df['population']/df['households'] # 每家有几个人
df['rooms_per_household']=df['total_rooms']/df['households'] # 每家有几个房屋
df['bedrooms_per_room']=df['total_bedrooms']/df['total_rooms']  # 每个房屋有几个卧室 
# corr_matrix=df.corr()
# corr_matrix['median_house_value'].sort_values(ascending=False)
df.drop(["population","households","total_rooms","total_bedrooms"],axis=1,inplace=True)

### =====================文本型数据:独热编码=====================
df = pd.get_dummies(df, columns=['ocean_proximity'])

### =====================连续型数据:标准化=====================
df['income_copy']=df['median_income'] # 留着后面分层抽样
con_cols=['longitude','latitude','housing_median_age','median_income',
          'population_per_household','rooms_per_household','bedrooms_per_room','median_house_value']
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
df[con_cols] = scaler.fit_transform(df[con_cols])
df

"""
    划分数据集
"""
### =====================划分数据集:分层抽样=====================
# 将median_income这个连续数据映射分级,放到新属性income_cat中
df['income_cat'] = pd.cut(df['income_copy'],
                            bins=[0, 1.5, 3.0, 4.5, 6, np.inf],
                            labels=["1", "2", "3", "4", "5"])
df["income_cat"].hist(edgecolor="black", bins=11, grid=False)

# 分层抽样——按照income_cat属性中比例分层(它最接近符合正态分布)
from sklearn.model_selection import StratifiedShuffleSplit
ss=StratifiedShuffleSplit(n_splits=1, test_size=0.2, random_state=42)
for train_idx, test_idx in ss.split(df, df['income_cat']):
    train_strat=df.loc[train_idx]
    test_strat=df.loc[test_idx]

print(f"train_len: {len(train_strat)}, test_len: {len(test_strat)}")
print("train 和 test 中 income_cat 比例: \n", train_strat["income_cat"].value_counts()/len(train_strat))

# 删除无用特征
df.drop(['latitude','longitude','median_house_value','income_copy','income_cat'],axis=1,inplace=True)
train_strat.drop(['income_cat','income_copy','latitude','longitude'],axis=1,inplace=True)
test_strat.drop(['income_cat','income_copy','latitude','longitude'],axis=1,inplace=True)

# 划分train和test
y_train=train_strat['median_house_value'].values # .values转array
x_train=train_strat.drop('median_house_value',axis=1).values
y_test=test_strat['median_house_value'].values
x_test=test_strat.drop('median_house_value',axis=1).values

缺失值处理

如下图,统计出total_bedrooms出现207个空值,而总样本数为20640个,大约占1%,因此可以考虑直接剔除,也可以替代,这里这个特征属于连续型变量,采用中位数替代。
在这里插入图片描述

特征探索

对数据集中的连续型特征绘制其直方图,总结出一些处理建议:

  • 前两幅图为房地的经纬度,因此数值比较分散,不呈正态分布,情有可原
  • total_rooms、total_bedrooms、population、households这几幅图很类似,同时考虑到其表达的含义比较相似,可以对它们考虑进行特征组合(后述)。另外,它们都呈现较偏左边的正态分布,右半部分比较空缺,可以考虑通过采样优化其分布(后述)。
  • median_income比较接近理想的正态分布,在划分数据集时,可以考虑以它为基准进行分层抽样,这样也能保证total_rooms等特征分布呈较为合理的正态分布。
  • 在这里插入图片描述

相关性分析

各个特征与房价median_house_value的相关性分析如下图,越接近1和-1越相关,0表示没有线性关系。可以看出收入median_income与房价呈很强的正相关关系,househols、total_bedrooms、popultion这几个特征对于房价来说相关性很小,结合前面特征探索中,可以将其组合出新的特征。例如

  • 对于地区家庭数目households和总房屋数目total_rooms,组合成“每个家庭的房屋数量”更具有代表性。
  • 对于地区卧室总数目total_bedrooms和总房屋总数目total_rooms,显然单知道两者数目比较空泛,现实生活中更看重“房间卧室的占比”,是一个衡量房价的重要指标
  • 对于地区总人口和总家庭数目,可以尝试组合成“每个家庭有多少人”,可能可以从侧面反应出房间大小,进而体现房价。
    在这里插入图片描述
    组合新特征出如下图,可以看到,新组合出的特征rooms_per_households和bedrooms_per_rom比原特征对于房价的相关性要更大,显然房间卧室的占比越小,房价越贵,符合事实。
    在这里插入图片描述

文本数据标签编码

对于地区举例海洋的距离ocean_proximity这个特征,虽然印象里认为“离海越近房价越高”(毕竟海景房更招人喜欢),考虑使用标签编码是不错的选择,但是这个特征值表示的仅是与海的距离分级,离海越接近不一定代表有更多客户青睐(毕竟能稍微远一点也能看到海景,还不用担心极端天气海边发生突发状况)。综合以上可能存在的不确定的主观因素,以及对于现实情况还不够太了解,我选择独热编码,让机器自行训练自行分辨。
在这里插入图片描述

数值型数据标准化

采用z-score标准化,对于每一列特征,均处理成(X-均值) / 方差。

在这里插入图片描述

划分数据集

前面特征探索流程中,观察得出收入median_income最接近合理的正态分布,并且它与房价的相关性程度最大,因此依据不同收入median_income的等级比例来进行分层抽样。首先将连续型的收入median_income依据大小映射成不同的收入等级income_cat,并统计不同等级比例,然后依据这个等级比例分层抽样划分出训练集和测试集(即不管是在训练集和测试集中,数据比例满足收入等级对应的比例)。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

🧡🧡线性回归🧡🧡

闭合形式参数求解原理

主要是通过最小化残差平方和来找到最优的回归系数

  • 设要求的函数为
    在这里插入图片描述
  • 其中X为样本,θ为参数向量
    在这里插入图片描述
    在这里插入图片描述
  • 代价函数表示为最小化残差平方和(预测值和真实值的误差):
    在这里插入图片描述
  • 对代价函数求导:
    在这里插入图片描述
  • 令导数为0:
    在这里插入图片描述
    得到如上线性回归模型的闭合形式解,能够直接计算出最优的回归系数,然而其中(XT*X)-1有时很难求解。

梯度下降参数求解原理

通过迭代优化,逐步调整回归系数以最小化损失函数,从而得到较优值对应的回归系数。

  • 确定损失函数
    在这里插入图片描述
  • 计算梯度
    在这里插入图片描述
  • 梯度下降(负梯度方向)
    在这里插入图片描述
    其中α为下降的步幅(学习率),需提前设定。
    重复计算梯度并且更新系数,直到达到预先设定的迭代次数或者损失函数收敛至某个阈值,本实验中通过设定每两次迭代中损失函数变化不超过1e-8,则认为损失函数收敛至某个阈值。

代码

### =====================指标评估函数=====================
def mean_absolute_error(y_true, y_pred):
    return np.mean(np.abs(y_pred - y_true))

def mean_squared_error(y_true, y_pred):
    return np.mean((y_pred - y_true) ** 2)

def root_mean_squared_error(y_true, y_pred):
    return np.sqrt(mean_squared_error(y_true, y_pred))

def r_squared(y_true, y_pred):
    y_mean = np.mean(y_true)
    ss_total = np.sum((y_true - y_mean) ** 2)
    ss_residual = np.sum((y_true - y_pred) ** 2)
    r2 = 1 - (ss_residual / ss_total)
    return r2

def goodness_of_fit(y_true, y_pred):
    return np.sqrt(r_squared(y_true, y_pred))


### =====================求解=====================
import time

## 闭合式求解法
def close_solve(X,Y):
    # np.linalg.inv求矩阵的逆, .T求矩阵的转置
    theta=np.linalg.inv(X.T.dot(X)).dot(X.T).dot(Y)
    return theta

start_time = time.time()  # 记录程序开始时间
print("============闭合式求解:==========")
theta=close_solve(x_train, y_train)
print(f"theta: {theta}")
y_pred=np.dot(x_test,theta)
print("MAE:", mean_absolute_error(y_test, y_pred)) #  平均绝对误差
print("MSE:", mean_squared_error(y_test, y_pred)) # 均方误差
print("RMSE:", root_mean_squared_error(y_test, y_pred)) # 均方根误差
print("R方:", r_squared(y_test, y_pred)) # R方
print("拟合优度:", goodness_of_fit(y_test, y_pred)) # 拟合优度
print(f"===运行时间===:{time.time()-start_time} 秒\n")


## 梯度下降法求解
# 定义损失函数
def loss_func(y_true, y_pred):
    return  (1/2)*mean_squared_error(y_true,y_pred) # 1/2 MSE

def gradient_descent(x_train, y_train, lr):
    n,m=x_train.shape # 样本数目
    theta=np.zeros(m)
    while True:
        # 计算误差error和损失loss
        y_pred=np.dot(x_train, theta)
        error=y_pred - y_train
        loss=loss_func(y_train, y_pred)
        # 计算梯度、更新参数
        gradient= 2 * np.dot(x_train.T, error) / n
        theta-=lr*gradient
        
        if len(loss_histroy)!=0 and abs( loss - loss_histroy[-1]) < 1e-8: #结束条件
            break
        loss_histroy.append(loss)
        
    return theta

start_time = time.time()  # 记录程序开始时间
loss_histroy=[]
print("============梯度下降法求解:============")
theta=gradient_descent(x_train, y_train, lr=0.01)
print(f"theta: {theta}")
y_pred=np.dot(x_test,theta)
print("MAE:", mean_absolute_error(y_test, y_pred)) #  平均绝对误差
print("MSE:", mean_squared_error(y_test, y_pred)) # 均方误差
print("RMSE:", root_mean_squared_error(y_test, y_pred)) # 均方根误差
print("R方:", r_squared(y_test, y_pred)) # R方
print("拟合优度:", goodness_of_fit(y_test, y_pred)) # 拟合优度
print(f"===运行时间===:{time.time()-start_time} 秒\n")
plt.plot(loss_histroy)
plt.xlabel("iter")
plt.ylabel("loss")

## print特征对应的参数
for f,t in zip(df.columns,theta):
    print(f"{f}\t{t}")

运行结果

通过闭合式求解和梯度下降法求解,并用MAE、MSE、RMSE、R方、拟合优度等来比较两种求解方式的求解效果如下
在这里插入图片描述
可以看见,两种方法得出的结果差别不大,总体来看,闭合式求解的误差(MAE、MSE、RMSE)相对小,拟合效果(R方、拟合优度)相对大,因此在本次实验中闭合式求解的效果整体优于梯度下降法。
另外,能明显从运行时间看出两者的计算速度差异,闭合式由于只需计算结果公式(XT*X)-1X^TY,而梯度下降法中需要不断迭代更新theta很多次才能得到较优解,所以一般来说闭合式会快得多;但本实验中特征维度还算不多,闭合式会比较快,如若特征维度增多,闭合式的求解效率会变得很艰难,而梯度下降法在高纬度中仍然能以很快的速度求解出较优值。
总结来说:

  • 闭合式求解法在可解的情况下,一定能求解出全局最优解,但计算速度受维度影响大,当维度较大时,可能出现不可解的情况。
  • 梯度下降法不一定能求解出最优解,但在高维度时计算速度仍然有可观的效果。

🧡🧡总结🧡🧡

讨论实验结果,分析各个特征与目标预测值的正负相关性
在这里插入图片描述
- 呈负相关性的特征:
对于population_per_household,实验结果表明平均家庭人口越少,可能意味着住房拥挤,家庭成员较多时,每个人的居住空间和私密性可能会减少,进而可能会间接降低该地区的房价,但相关性很小,只有0.03,接近0,因此可以认为这个特征实际上对于房价影响不大,改进实验时应该不再组合这个新特征。
对于ocean_proximity_INLAND,实验结果表明靠近内陆的地区房价会越低,且相关性程度达0.42,结合实际,内陆地区由于缺乏海洋景观等吸引力因素,房价则相对较低。
- 呈正相关性的特征:
相关性程度较大的主要是收入median_income,高达0.68,结合实际考虑,高收入人群通常更愿意支付更高的房价,因此高收入区域的房价往往更高。其次主要是与海洋远近的特征,结合实际考虑,靠近海湾和靠近海洋的地区往往景色优美、气候宜人,因此房价会相应较高。
剩余特征如房龄housing_median_age、卧室占比bedrooms_per_room等等,对房价的影响程度较小。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

router4j--SpringCloud动态路由利器

前言 本文介绍Java的动态路由中间件&#xff1a;router4j。router4j用于SpringCloud项目&#xff0c;它可以将某个url请求路由到指定的机器上&#xff0c;也可以将所有请求强制转到指定机器。 问题描述 Java后端在开发SpringCloud项目时如果同一个应用起了多个实例&#xff…

汽车网络架构与常用总线汇总

汽车CAN总线简述 CAN 是控制器局域网Controller Area Network 的缩写&#xff0c;1986年&#xff0c;由德国Bosch公司为汽车开发的网络技术&#xff0c;主要用于汽车的监测与控制&#xff0c;目的为适应汽车“减少线束的数量”“通过多个网络进行大量数据的高速传输”的需求。…

php中laravel项目开发技巧与避坑

公司开发新业务&#xff0c;涉及到地址引用和循环遍历&#xff0c;结果测试人员说部分数据对不上&#xff0c;经排查&#xff0c;ID无值&#xff0c;name却有值&#xff0c;断点定位后&#xff0c;发现是地址引用的问题引起的 问题原因 数据库查询也确实是0 解决方案 注意事项…

理想架构的非对称高回退Doherty功率放大器理论与仿真

Doherty理论—理想架构的非对称高回退Doherty功率放大器理论与仿真 参考&#xff1a; 三路Doherty设计 01 射频基础知识–基础概念 Switchmode RF and Microwave Power Amplifiers、 理想架构的Doherty功率放大器&#xff08;等分经典款&#xff09;的理论与ADS电流源仿真参考…

什么是ORM思想?

1. ORM概念 ORM&#xff08;Object Relational Mapping&#xff09;对象关系映射模式&#xff0c;是一种技术&#xff0c;解决了面向对象与关系型数据库存互不匹配的现象。 ORM在业务逻辑层和数据库层之间充当了桥梁的作用。 2. ORM由来 在软件开发的过程中&#xff0c;通常…

UE5.2、CesiumForUnreal实现加载GeoJson绘制单面

文章目录 前言一、实现目标二、实现过程1.实现原理2.数据读取3.三角剖分3.具体代码 4.蓝图测试 前言 UE5、CesiumForUnreal实现加载GeoJson绘制单面&#xff08;Polygon&#xff09;功能&#xff08;StaticMesh方式&#xff09; 一、实现目标 通过读取本地的Geojson数据&…

【Go学习】Ginkgo测试框架学习实践 + 问题记录 + 怎么解决(0)

1、ginkgo测试框架介绍&#xff1a;https://onsi.github.io/ginkgo/ 2、重点是学习实践 问题记录 怎么解决 3、送福利&#xff1a;国内好用的ChatGpt有很多&#xff0c;比如&#xff1a;天工、文心一言、讯飞星火、通义万相等 1. 安装 xxxmacdeMacBook-Pro-3  /Volumes/mac…

关于网络模型的笔记

1. OSI 七层参考模型&#xff1a; 简介&#xff1a; 七层模型&#xff0c;亦称 OSI&#xff08;Open System Interconnection&#xff09;参考模型&#xff0c;即开放式系统互联。参考模型 是国际标准化组织&#xff08;ISO&#xff09;制定的一个用于计算机或通信系统间互联…

mc我的世界服务器多少钱一个月?

我的世界服务器多少钱一个月&#xff1f;低至7元一个月&#xff0c;阿里云和腾讯云均可以选择mc服务器&#xff0c;阿里云2核2G3M轻量服务器87元一年、腾讯云轻量2核2G3M服务器88元一年&#xff0c;阿里云ECS云服务器2核2G3M带宽99元一年&#xff0c;腾讯云2核4G5M带宽轻量应用…

IPoE技术汇总

在国内并没有遇到这么多的IPoE&#xff08;IP over Ethernet&#xff09;技术&#xff0c;可能也是因为我来日本多年了&#xff0c;没有接触国内的IPv4 over IPv6的技术&#xff0c;感觉国内IPv4地址紧张&#xff0c;用的传统NAT和PPPoE非常多&#xff0c;大多数设备还是建立在…

docker - compose 部署 Tomcat

目录 下面用 docker-compose 方法部署 Tomcat 1、准备工作 2、部署容器 启动容器 查看新启动的容器 3、总结 下面用 docker-compose 方法部署 Tomcat 1、准备工作 先在主机创建工作文件夹&#xff0c;为了放置 Tomcat 的配置文件等。创建文件夹的方法&#xff0c;自己搞…

【linux】远程桌面连接到Debian

远程桌面连接到Debian系统&#xff0c;可以使用以下几种工具&#xff1a; 1. VNC (Virtual Network Computing) VNC&#xff08;Virtual Network Computing&#xff09;是一种流行的远程桌面解决方案&#xff0c;它使用RFB&#xff08;Remote Framebuffer Protocol&#xff0…

上位机图像处理和嵌入式模块部署(流程)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 前面我们说过&#xff0c;传统图像处理的方法&#xff0c;一般就是pccamera的处理方式。camera本身只是提供基本的raw data数据&#xff0c;所有的…

sublime text 开启vim模式

sublime text 开启vim模式 打开配置文件 mac下点击菜单栏 Sublime Text -> Settings... -> Settings 修改配置文件并保存 添加配置 // 开启vim模式 "ignored_packages": [// "Vintage", ], // 以命令模式打开文件 "vintage_start_in_comman…

【博客搭建记录贴】问题记录:hexo : 无法加载文件 C:\Program Files\nodejs\hexo.ps1,因为在此系统上禁止运行脚本。

1&#xff0c;背景 hexo&#xff08;博客框架&#xff09;安装完毕之后&#xff0c;正准备看看其版本&#xff0c;发现出现下面脚本禁止运行的错误。 PS C:\Users\PC> hexo -v hexo : 无法加载文件 C:\Program Files\nodejs\hexo.ps1&#xff0c;因为在此系统上禁止运行脚…

【Android】在WSA安卓子系统中进行新实验性功能试用与抓包(2311.4.5.0)

前言 在根据几篇22和23的WSA抓包文章进行尝试时遇到了问题&#xff0c;同时发现新版Wsa的一些实验性功能能优化抓包配置时的一些步骤&#xff0c;因而写下此篇以作记录。 Wsa版本&#xff1a;2311.40000.5.0 本文出现的项目&#xff1a; MagiskOnWSALocal MagiskTrustUserCer…

自然语言处理--概率最大中文分词

自然语言处理附加作业--概率最大中文分词 一、理论描述 中文分词是指将中文句子或文本按照语义和语法规则进行切分成词语的过程。在中文语言中&#xff0c;词语之间没有明显的空格或标点符号来分隔&#xff0c;因此需要通过分词工具或算法来实现对中文文本的分词处理。分词的…

RPC教程 3.服务注册

0. 前言 这一节要熟悉Go中的反射reflet&#xff0c;不然可能比较难理解。在使用到反射的一些函数时候&#xff0c;我也会讲解关于反射reflect的用法。 1.引出反射reflect 这个例子是表示客户端想使用Foo服务的Sum方法。即是想调用Foo结构体的Sum方法。 client.Call("F…

uniapp 在static/index.html中添加全局样式

前言 略 在static/index.html中添加全局样式 <style>div {background-color: #ccc;} </style>static/index.html源码&#xff1a; <!DOCTYPE html> <html lang"zh-CN"><head><meta charset"utf-8"><meta http-…

Java线程池,看这一篇足够

目录一览 Java线程池1. Executors提供6个线程池快捷创建方式2. ThreadPoolExecutor的7大参数3. 自定义线程池 Java线程池 上一篇《Async注解的注意事项》说到Async注解要配合自定义线程池一起使用&#xff0c;这一节说下Java的线程池。 1. Executors提供6个线程池快捷创建方式…