波士顿房价预测——机器学习入门级案例

news2025/1/17 1:10:25

一、数据处理

1.1 数据集介绍

本实验使用波士顿房价预测数据集,共506条样本数据,每条样本包含了12种可能影响房价的因素和该类房屋价格的中位数,各字段含义如下表所示:

字段名类型含义
CRIMfloat该镇的人均犯罪率
ZNfloat占地面积超过25,000平方呎的住宅用地比例
INDUSfloat非零售商业用地比例
CHASint是否邻近 Charles River 1=邻近;0=不邻近
NOXfloat一氧化氮浓度
RMfloat每栋房屋的平均客房数
AGEfloat1940年之前建成的自用单位比例
DISfloat到波士顿5个就业中心的加权距离
RADint到径向公路的可达性指数
TAXint全值财产税率
PTRATIOfloat学生与教师的比例
LSTATfloat低收入人群占比
MEDVfloat同类房屋价格的中位数

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

1.2 数据导入

(1)波士顿房价预测数据集存储在文本文件中的数据格式为下图所示:
在这里插入图片描述
其中的X就是数据集介绍中的CRIM-LSTAT部分,而Y就是MEDV,即同类房屋价格的中位数,也就是我们后面要预测的值。

(2)使用Numpy从文件导入数据np.fromfile

# 导入需要用到的package
import numpy as np
import json
# 读入训练数据
datafile = 'housing.data'
data = np.fromfile(datafile, sep=' ')

导入结果:
在这里插入图片描述
注释: np.tofile和np.fromfile可以实现数组写到磁盘文件中

print(data.shape)
# 输出(7084,)

我们可以发现,我们进行上述代码操作以后,将文件中的数据集生成了一个一维的数组,通过打印data.shape可以发现这个一维数组的长度为7084。
细心的朋友不难发现,7084不就是506 x 14以后的结果吗~

没错,在这时候我们就需要重新将data数据重新处理一下,用reshape()方法将其处理为(506, 14)的二维数组。

# 每条数据包括14项,其中前面13项是影响因素,第14项是相应的房屋价格中位数
feature_names = ['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT', 'MEDV']
feature_num = len(feature_names)

# 将原始数据进行reshape, 变为[N, 14]这样的形状
data = data.reshape([data.shape[0] // feature_num, feature_num])
print(data.shape)
# 输出(506, 14)

# 查看数据
X = data[0]
print(X.shape)
print(X)
# 输出
#(14,)
# [6.320e-03 1.800e+01 2.310e+00 0.000e+00 5.380e-01 6.575e+00 6.520e+01
# 4.090e+00 1.000e+00 2.960e+02 1.530e+01 3.969e+02 4.980e+00 2.400e+01]

由此可以看出每条数据是一个长度为14的一维数组,前13项是影响房价的因素,最后一项是房价。

1.3 数据集划分

在机器学习和深度学习过程中,往往要将数据集划分为训练集和测试集两部分,训练集用来进行训练,一般会取数据集的80%-90%,而测试集用来对训练好的模型性能进行评估,一般只取少量数据集,大概为10%左右。

ratio = 0.8
offset = int(data.shape[0] * ratio)
train_data = data[:offset]
test_data = data[offset:]
print(train_data.shape)
print(test_data.shape)
# 输出:
# (404, 14)
# (102, 14)

波士顿房价预测数据集中原有数据集为506行,经过划分以后,训练集为原来的80%,即404,测试集为原来的20%,即102。

1.4 归一化处理

对特征取值范围进行归一化,有两个好处

  • 特征训练更高效
  • 特征前的权重大小可代表该变量对预测结果的贡献度

注意:预测时,样本数据同样也需要归一化,以训练样本的均值和极值计算

# 计算train数据集的最大值、最小值和平均值
maxinums, mininums, avgs = data_slice.max(axis=0), data_slice.min(axis=0), data_slice.sum(axis=0) / data_slice.shape[0]

# 对数据进行归一化处理
for i in range(feature_num):
    # print(maxinums[i], mininums[i], avgs[i])
    data[:, i] = (data[:, i] - avgs[i]) / (maxinums[i] - mininums[i])

1.5 将完整代码封装成load_data函数

def load_data():
    # 从文件导入数据
    datafile = 'housing.data'
    data = np.fromfile(datafile, sep=' ')
    print(data.shape)
    # 每条数据包括14项,其中前面13项是影响因素,第14项是相应的房屋价格中位数
    feature_names = ['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT', 'MEDV']
    feature_num = len(feature_names)

    # 将原始数据进行reshape, 变为[N, 14]这样的形状
    data = data.reshape([data.shape[0] // feature_num, feature_num])
    print(data.shape)
    X = data[0]
    print(X.shape)
    print(X)
    # 将原数据集拆分成训练集和测试集
    # 这里使用80%的数据做训练,20%的数据做测试
    # 测试集和训练集必须是没有交集的
    ratio = 0.8
    offset = int(data.shape[0] * ratio)
    data_slice = data[:offset]

    # 计算train数据集的最大值、最小值和平均值
    maxinums, mininums, avgs = data_slice.max(axis=0), data_slice.min(axis=0), data_slice.sum(axis=0) / data_slice.shape[0]

    # 对数据进行归一化处理
    for i in range(feature_num):
        # print(maxinums[i], mininums[i], avgs[i])
        data[:, i] = (data[:, i] - avgs[i]) / (maxinums[i] - mininums[i])

    # 训练集和测试集的划分比例
    # ratio = 0.8
    train_data = data[:offset]
    test_data = data[offset:]

    return train_data, test_data

1.6 获取数据

# 获取数据
train_data, test_data = load_data()
print(train_data.shape)
x = train_data[:, :-1]
y = train_data[:, -1:]
print(x[0])
print(y[0])
#[-0.02146321  0.03767327 -0.28552309 -0.08663366  0.01289726  0.04634817
#  0.00795597 -0.00765794 -0.25172191 -0.11881188 -0.29002528  0.0519112
# -0.17590923]
#[-0.00390539]

二、设计模型

波士顿房价预测案例是一个非常典型的线性回归问题。

2.1 前向计算

输入x一共有13个变量,y只有1个变量,所以权重w的shape是[13, 1]
- w可以任意赋初值如下

w = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, -0.1, -0.2, -0.3, -0.4, 0.0]
w = np.array(w).reshape([13, 1])

- 取出第1条样本数据,观察它与w相乘之后的结果

x1 = X[0]
t = np.dot(x1, w)
print(t)
# 输出:[0.03395597]

- 另外还需要初始化权重b,这里我们给它赋值-0.2观察输出

b = -0.2
z = t + b
print(z)
# 输出 [-0.16604403]

2.2 以类的方式实现网络结果(前向计算)

  1. 使用时可以生成多个模型示例
  2. 类成员变量有w和b,在类初始化函数时初始化变量(w随机初始化,b = 0)
  3. 函数成员forward 完成从输入特征x到输出z的计算过程(即前向计算
class NetWork(object):
    def __init__(self, num_of_weights):
        # 随机产生w的初始值
        # 为了保持程序每次运行结果的一致性,此处设置了固定的随机数种子
        np.random.seed(0)
        self.w = np.random.randn(num_of_weights, 1)
        self.b = 0

    def forward(self, x):
        z = np.dot(x, self.w) + self.b

        return z

随机选取一个样本测试下效果

net = NetWork(13)
x1 = x[0]
y1 = y[0]
z = net.forward(x1)
print(z)
# 输出 [-0.63182506]

此时我们可以看出,现阶段搭建的模型只有一个花架子,并不具备预测的能力,所以还需改进。

2.3 模型好坏的衡量指标——损失函数(loss function)

在这里插入图片描述

2.3.1 训练配置—同时计算多个样本的损失函数

在这里插入图片描述

class NetWork(object):
    def __init__(self, num_of_weights):
        # 随机产生w的初始值
        # 为了保持程序每次运行结果的一致性,此处设置了固定的随机数种子
        np.random.seed(0)
        self.w = np.random.randn(num_of_weights, 1)
        self.b = 0

    def forward(self, x):
        z = np.dot(x, self.w) + self.b

        return z

    def loss(self, z, y):
        error = z - y
        cost = error * error
        cost = np.mean(cost)

        return cost

net = NetWork(13)
x1 = x[0:3]
y1 = y[0:3]
z = net.forward(x1)
print('predict', z)
loss = net.loss(z, y1)
print('loss', loss)

# 输出 
# predict [[-0.63182506]
# [-0.55793096]
# [-1.00062009]]
# loss 0.7229825055441156

三、梯度下降代码实现

class NetWork(object):
    def __init__(self, num_of_weights):
        # 随机产生w的初始值
        # 为了保持程序每次运行结果的一致性,此处设置了固定的随机数种子
        np.random.seed(0)
        self.w = np.random.randn(num_of_weights, 1)
        self.b = 0

    def forward(self, x):
        z = np.dot(x, self.w) + self.b

        return z

    def loss(self, z, y):
        error = z - y
        cost = error * error
        cost = np.mean(cost)

        return cost

    def gradient(self, x, y):
        z = self.forward(x)
        gradient_w = (z - y) * x
        gradient_w = np.mean(gradient_w, axis=0)  # axis=0表示把每一行做相加然后再除以总的行数
        gradient_w = gradient_w[:, np.newaxis]
        gradient_b = (z - y)
        gradient_b = np.mean(gradient_b)
        # 此处b是一个数值,所以可以直接用np.mean得到一个标量(scalar)
        return gradient_w, gradient_b

    def update(self, gradient_w, gradient_b, eta=0.01):    # eta代表学习率,是控制每次参数值变动的大小,即移动步长,又称为学习率
        self.w = self.w - eta * gradient_w                 # 相减: 参数向梯度的反方向移动
        self.b = self.b - eta * gradient_b

    def train(self, x, y, iterations=1000, eta=0.01):
        losses = []
        for i in range(iterations):
            # 四步法
            z = self.forward(x)
            L = self.loss(z, y)
            gradient_w, gradient_b = self.gradient(x, y)
            self.update(gradient_w, gradient_b, eta)
            losses.append(L)
            if (i + 1) % 10 == 0:
                print('iter {}, loss {}'.format(i, L))
        return losses

完整代码

import numpy as np
from matplotlib import pyplot as plt


def load_data():
    # 从文件导入数据
    datafile = 'housing.data'
    data = np.fromfile(datafile, sep=' ')
    print(data.shape)
    # 每条数据包括14项,其中前面13项是影响因素,第14项是相应的房屋价格中位数
    feature_names = ['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT', 'MEDV']
    feature_num = len(feature_names)

    # 将原始数据进行reshape, 变为[N, 14]这样的形状
    data = data.reshape([data.shape[0] // feature_num, feature_num])
    print(data.shape)

    # 将原数据集拆分成训练集和测试集
    # 这里使用80%的数据做训练,20%的数据做测试
    # 测试集和训练集必须是没有交集的
    ratio = 0.8
    offset = int(data.shape[0] * ratio)
    data_slice = data[:offset]

    # 计算train数据集的最大值、最小值和平均值
    maxinums, mininums, avgs = data_slice.max(axis=0), data_slice.min(axis=0), data_slice.sum(axis=0) / data_slice.shape[0]

    # 对数据进行归一化处理
    for i in range(feature_num):
        # print(maxinums[i], mininums[i], avgs[i])
        data[:, i] = (data[:, i] - avgs[i]) / (maxinums[i] - mininums[i])

    # 训练集和测试集的划分比例
    # ratio = 0.8
    train_data = data[:offset]
    test_data = data[offset:]

    return train_data, test_data


class NetWork(object):
    def __init__(self, num_of_weights):
        # 随机产生w的初始值
        # 为了保持程序每次运行结果的一致性,此处设置了固定的随机数种子
        np.random.seed(0)
        self.w = np.random.randn(num_of_weights, 1)
        self.b = 0

    def forward(self, x):
        z = np.dot(x, self.w) + self.b

        return z

    def loss(self, z, y):
        error = z - y
        cost = error * error
        cost = np.mean(cost)

        return cost

    def gradient(self, x, y):
        z = self.forward(x)
        gradient_w = (z - y) * x
        gradient_w = np.mean(gradient_w, axis=0)  # axis=0表示把每一行做相加然后再除以总的行数
        gradient_w = gradient_w[:, np.newaxis]
        gradient_b = (z - y)
        gradient_b = np.mean(gradient_b)
        # 此处b是一个数值,所以可以直接用np.mean得到一个标量(scalar)
        return gradient_w, gradient_b

    def update(self, gradient_w, gradient_b, eta=0.01):    # eta代表学习率,是控制每次参数值变动的大小,即移动步长,又称为学习率
        self.w = self.w - eta * gradient_w                 # 相减: 参数向梯度的反方向移动
        self.b = self.b - eta * gradient_b

    def train(self, x, y, iterations=1000, eta=0.01):
        losses = []
        for i in range(iterations):
            # 四步法
            z = self.forward(x)
            L = self.loss(z, y)
            gradient_w, gradient_b = self.gradient(x, y)
            self.update(gradient_w, gradient_b, eta)
            losses.append(L)
            if (i + 1) % 10 == 0:
                print('iter {}, loss {}'.format(i, L))
        return losses




# 获取数据
train_data, test_data = load_data()
print(train_data.shape)
x = train_data[:, :-1]
y = train_data[:, -1:]

# 创建网络
net = NetWork(13)
num_iterations = 2000
# 启动训练
losses = net.train(x, y, iterations=num_iterations, eta=0.01)

# 画出损失函数的变化趋势
plot_x = np.arange(num_iterations)
plot_y = np.array(losses)
plt.plot(plot_x, plot_y)
plt.show()

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

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

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

相关文章

springboot中迁移接口报404错误找不到 main方法java.lang.UnsupportedClassVersionError的经历

一、出现问题公司有接口要迁移到新服务中,服务不能启动错误大概如下:错误: 在类 ### 中找不到 main 方法, 请将 main 方法定义为: public static void main(String[] args) 否则 JavaFX 应用程序类必须扩展javafx.application.Application问题1解决后&am…

字符串函数和内存函数

在c语言中,有非常多的库函数,比如我们经常使用的scanf和printf,除此之外,还有一些非常实用的函数,比如我们之前使用的qsort排序函数,可以对任意数据类型进行排序,strlen函数,可以计算…

1.5万字总结 Redis 常见面试题知识点

以下内容来源于于我开源的 JavaGuide (Java学习&&面试指南,Github 130k star,370人共同参与爱完善), 万字总结,质量有保障! Redis 基础 什么是 Redis? Redis 是一个基于 C 语言开发的开源数据库(BSD 许可),与传统数据库不同的是 Redis 的数据是存在内存中的…

磨金石教育插画技能干货分享|学习插画可以从事什么工作?

近几年插画师这个行业越来越热,许多有一定绘画基础的朋友,都在跃跃欲试,想要走进插画这个行业。但不少人都有一种担忧,就是插画师这个职位平时听的很少,认为这是个冷门行业,是不是难以就业,风险…

边双连通分量

如果还未学习强连通分量,建议先学习强连通分量的tarjan算法强连通分量(tarjan算法) 1,定义 相对于在单向图的强连通分量,双连通分量是在无向图中,无向图有一个特点,可以以任何一个点为根节点建…

Java开发常见漏洞及解决方案

文章目录1.健康监控Actuator暴露端口2.SSRF漏洞攻击3.富文本XSS攻击4.暴力破解短信验证码登录5.恶意短信轰炸骚扰用户6.低版本Fastjson导致RCE漏洞7.SQL注入漏洞8.水平越权信息泄露9.权限绕过漏洞1.健康监控Actuator暴露端口 ​ Actuator是Springboot提供的用来对应用系统进行…

html 判断视频是否播放

html 判断视频是否播放 html <video id"video" loop preload"auto" autoplay><source src"1.mp4" type"video/mp4">您的浏览器不支持Video标签。 </video> js代码 var videodocument.querySelector("#vide…

phpstudy如何安装PHP扩展sg11

1、下载sg11扩展文件压缩包&#xff0c;下载地址&#xff1a;PHP扩展sg11.zip - 蓝奏云 2、解压下载好的sg11压缩包&#xff0c;选择对应你自己的服务器系统文件夹&#xff0c;我的是Windows 64-bit 3、打开Windows 64-bit&#xff0c;复制对应PHP版本的.win文件&#xff0c;…

电脑一键重装系统win11步骤教程

win11系统是微软目前最新的操作系统&#xff0c;很多人都想给电脑重装系统win11体验。那么具体要怎么重装系统win11呢?我们可借助一键装机工具实现&#xff0c;下面就演示下简单的一键重装系统win11步骤教程 工具/原料&#xff1a; 系统版本&#xff1a;Windows 11 品牌型号…

基于轻量级ShuffleNetv2+YOLOv5的DIC-C2DH-HeLa细胞检测识别分析系统

ShuffleNetv2可以说是目前轻量级网络模型中的翘楚&#xff0c;将ShuffleNetv2于yolov5整合开发可以使得模型更加轻量化&#xff0c;在提升模型速度的同时保证有效的精度。本文的主要工作就是将ShuffleNetv2整合进yolov5中来开发构建细胞检测模型&#xff0c;首先看下效果图&…

4-3文件管理-磁盘组织与管理

文章目录一.磁盘的结构二.磁盘调度算法&#xff08;一&#xff09;一次读/写磁盘需要的时间&#xff08;二&#xff09;磁盘调度算法1.先来先服务FCFS2.最短寻找时间优先SSTF3.扫描算法/电梯调度算法SCAN4.循环扫描算法C-SCAN&#xff08;三&#xff09;减少磁盘延迟时间的方法…

再谈模板(19)

目录 1、非类型模板参数 2、模板的特化 1、定义 2、函数模板特化 3、类模板特化 1、全特化 2、偏特化 3、分离编译 1、什么是分离编译 2、模板不支持分离编译 4、模板总结 1、非类型模板参数 模板参数&#xff1a;类型形参与非类型形参。 类型形参&#xff1a;出现…

Leetcode - 24 - 两两交换链表中的节点

24. 两两交换链表中的节点 题目描述 给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0c;只能进行节点交换&#xff09;。 示例 1&#xff1a; 输入&#xff1a;h…

重写部分调试体系的DebugPort隐藏

背景逛世界上最大的交友网站的时候发现了一个开源的vt调试器&#xff0c;抱着学习的心态&#xff0c;下载下来学习学习。但是呢&#xff0c;实际编译出来的程序和release发布的有很大的区别&#xff0c;而且源码很乱&#xff0c;release版本的驱动至少能调试程序&#xff0c;但…

文件IO操作

日升时奋斗&#xff0c;日落时自省 目录 1、文件基本认知 1.1、文件路径 1.2、相对路径 1.3、文件类型 2、Java的文件操作 2.1、文件操作类File 3、数据流读写 3.1字节流读文件 3.2、字节流写文件 3.3、字符流读操作 3.4、字符流写操作 4、文件操作案例 4.1、删除…

【自学Python】Python类型转换

Python类型转换 Python类型转换教程 虽然 Python 是弱类型编程语言&#xff0c;不需要像 Golang 或 C/C 语言那样还要在使用 变量 前声明变量的类型&#xff0c;但在一些特定场景中&#xff0c;仍然需要用到类型转换。 对 Python 内置的数据类型进行转换时&#xff0c;可以使…

valgrind callgrind使用

valgrind --toolcallgrind --dump-instryes ./foo # ,这里会运行很久,执行完毕后会生成一个callgrind.out.1266511如果你调试的程序是多线程&#xff0c;你也可以在命令行中加一个参数 -separate-threadsyes。这样就会为每个线程单独生成一个性能分析文件。如下&#xff1a;val…

好玩的小游戏系列 (一)基于html+js 原生贪吃蛇

一朵花如果只被用来观赏那只呈现出它的外在意义只是它生命的一部分若是不能够将其内在更实质的美发挥出来充其量也不过就是一朵死的花而已。 目录 一、前言 二、代码介绍 三、效果显示 四、编码实现 index.html jquery-1.10.2.js 五、获取源码 获取源码&#xff1f;私信…

【vue2】组件进阶与插槽(匿名·具名·作用域插槽详解)

&#x1f973;博 主&#xff1a;初映CY的前说(前端领域) &#x1f31e;个人信条&#xff1a;想要变成得到&#xff0c;中间还有做到&#xff01; &#x1f918;本文核心&#xff1a;v-modedl表单双向绑定、ref|$ref操作dom、dynamic动态组件、$nextTick同步、匿名插槽、具…

Java常用开发工具有哪些

本节介绍一下 Java 常用的几个开发工具。下面这些工具或许功能和作用不同&#xff0c;但是有着一个共同的主旨&#xff0c;那就是——它们都是为了给 Java 编码和开发提供卓越的支持。 常用源码编辑工具介绍 Java 源代码本质上其实就是普通的文本文件&#xff0c;所以理论上来…