动手学深度学习(五)Kaggle房价预测

news2024/11/20 14:36:57

Kaggle房价数据集,前四个为房价特征,最后一个为标签(房价)。

一、下载数据集

import numpy as np
import pandas as pd
import torch
from torch import nn
from d2l import torch as d2l
import hashlib
import os
import tarfile
import zipfile
import requests

# 数据集下载
DATA_HUB = dict()
DATA_URL = 'http://d2l-data.s3-accelerate.amazonaws.com/'


def download(name, cache_dir=os.path.join('.', 'data')):  # @save
    """下载一个DATA_HUB中的文件,返回本地文件名"""
    assert name in DATA_HUB, f"{name} 不存在于 {DATA_HUB}"
    url, sha1_hash = DATA_HUB[name]
    os.makedirs(cache_dir, exist_ok=True)
    fname = os.path.join(cache_dir, url.split('/')[-1])
    if os.path.exists(fname):
        sha1 = hashlib.sha1()
        with open(fname, 'rb') as f:
            while True:
                data = f.read(1048576)
                if not data:
                    break
                sha1.update(data)
        if sha1.hexdigest() == sha1_hash:
            return fname  # 命中缓存
    print(f'正在从{url}下载{fname}...')
    r = requests.get(url, stream=True, verify=True)
    with open(fname, 'wb') as f:
        f.write(r.content)
    return fname


def download_extract(name, folder=None):  # @save
    """下载并解压zip/tar文件"""
    fname = download(name)
    base_dir = os.path.dirname(fname)
    data_dir, ext = os.path.splitext(fname)
    if ext == '.zip':
        fp = zipfile.ZipFile(fname, 'r')
    elif ext in ('.tar', '.gz'):
        fp = tarfile.open(fname, 'r')
    else:
        assert False, '只有zip/tar文件可以被解压缩'
    fp.extractall(base_dir)
    return os.path.join(base_dir, folder) if folder else data_dir


def download_all():  # @save
    """下载DATA_HUB中的所有文件"""
    for name in DATA_HUB:
        download(name)

DATA_HUB['kaggle_house_train'] = (
    DATA_URL + 'kaggle_house_pred_train.csv',
    '585e9cc93e70b39160e7921475f9bcd7d31219ce')

DATA_HUB['kaggle_house_test'] = (
    DATA_URL + 'kaggle_house_pred_test.csv',
    'fa19780a7b011d9b009e8bff8e99922a8ee2eb90')

train_data = pd.read_csv(download('kaggle_house_train'))
test_data = pd.read_csv(download('kaggle_house_test'))  # 读表

查看数据集大小和部分样本:

print(train_data.shape)
print(test_data.shape)

print(train_data.iloc[0:4, [0, 1, 2, 3, -3, -2, -1]])

(1460, 81)
(1459, 80)


   Id  MSSubClass MSZoning  LotFrontage SaleType SaleCondition  SalePrice
0   1          60       RL         65.0       WD        Normal     208500
1   2          20       RL         80.0       WD        Normal     181500
2   3          60       RL         68.0       WD        Normal     223500
3   4          70       RL         60.0       WD       Abnorml     140000

二、数据预处理

""" 数据预处理 """
all_features = pd.concat((train_data.iloc[:, 1:-1], test_data.iloc[:, 1:])) # 去掉id列

# 将所有缺失的值替换为相应特征的平均值。通过将特征重新缩放到零均值和单位方差来标准化数据
numeric_features = all_features.dtypes[all_features.dtypes != 'object'].index

all_features[numeric_features] = all_features[numeric_features].apply(
    lambda x: (x - x.mean()) / (x.std()))                                   # 标准化,将所有特征的均值变为0和方差变为1

all_features[numeric_features] = all_features[numeric_features].fillna(0)   # 将缺失项设置为0

# “Dummy_na=True”将“na”(缺失值)视为有效的特征值,并为其创建指示符特征
all_features = pd.get_dummies(all_features, dummy_na=True) # 为离散值生成独热编码,并增加一列表示空缺值

# 从pandas格式中提取NumPy格式,并将其转换为张量表示
n_train = train_data.shape[0]
train_features = torch.tensor(all_features[:n_train].values, dtype=torch.float32)
test_features = torch.tensor(all_features[n_train:].values, dtype=torch.float32)
train_labels = torch.tensor(
    train_data.SalePrice.values.reshape(-1, 1), dtype=torch.float32)

 查看特征总数大小:

print(all_features.shape)

(2919, 331) 

可以看到经过数据预处理会将特征总数由79增加到331。

三、训练函数

房价就像股票价格一样,我们关心的是相对误差,而不是绝对误差。比如说,农村的房价原本为12.5万,误差10万,和在市中心豪宅区的房价原本为420万,误差10万,显然使用绝对误差对结果评估的影响是不一样的,我们希望使用一种误差测量方法不受样本大小波动的影响,预测昂贵房屋和廉价房屋的误差能够同等影响预测结果,因此需要使用相对误差的测量方法,我们采用均方根损失来测量房价预测的相对误差。

""" 训练 """
loss = nn.MSELoss()
in_features = train_features.shape[1]   # 输入特征总数为331


def get_net():
    net = nn.Sequential(nn.Linear(in_features, 1))
    return net


def log_rmse(net, features, labels):
    # 为了在取对数时进一步稳定该值,将小于1的值设置为1
    clipped_preds = torch.clamp(net(features), 1, float('inf'))
    rmse = torch.sqrt(loss(torch.log(clipped_preds),
                           torch.log(labels)))
    return rmse.item()

均方根损失函数

# 均方根损失
def log_rmse(net, features, labels):
    # 为了在取对数时进一步稳定该值,将小于1的值设置为1
    clipped_preds = torch.clamp(net(features), 1, float('inf'))
    rmse = torch.sqrt(loss(torch.log(clipped_preds),
                           torch.log(labels)))
    return rmse.item()

训练函数

训练函数使用Adam优化器。

# 训练函数
def train(net, train_features, train_labels, test_features, test_labels,
          num_epochs, learning_rate, weight_decay, batch_size):
    train_ls, test_ls = [], []
    train_iter = d2l.load_array((train_features, train_labels), batch_size) # 加载训练数据
    # 这里使用的是Adam优化算法
    optimizer = torch.optim.Adam(net.parameters(),
                                 lr = learning_rate,
                                 weight_decay = weight_decay)
    for epoch in range(num_epochs):
        for X, y in train_iter:
            optimizer.zero_grad()
            l = loss(net(X), y)
            l.backward()
            optimizer.step()
        train_ls.append(log_rmse(net, train_features, train_labels))
        if test_labels is not None:
            test_ls.append(log_rmse(net, test_features, test_labels))
    return train_ls, test_ls

 

四、K折交叉验证(可选,炼丹步骤)

def get_k_fold_data(k, i, X, y):
    assert k > 1
    fold_size = X.shape[0] // k
    X_train, y_train = None, None
    for j in range(k):
        idx = slice(j * fold_size, (j + 1) * fold_size)
        X_part, y_part = X[idx, :], y[idx]
        if j == i:
            X_valid, y_valid = X_part, y_part
        elif X_train is None:
            X_train, y_train = X_part, y_part
        else:
            X_train = torch.cat([X_train, X_part], 0)
            y_train = torch.cat([y_train, y_part], 0)
    return X_train, y_train, X_valid, y_valid

 当我们在K折交叉验证中训练K次后,返回训练和验证误差的平均值

def k_fold(k, X_train, y_train, num_epochs, learning_rate, weight_decay,
           batch_size):
    train_l_sum, valid_l_sum = 0, 0  # 用于存储训练误差和验证误差的总和
    for i in range(k):
        data = get_k_fold_data(k, i, X_train, y_train)
        net = get_net() #选择模型
        train_ls, valid_ls = train(net, *data, num_epochs, learning_rate,
                                   weight_decay, batch_size) # 训练模型
        train_l_sum += train_ls[-1] # 将当前训练误差的最后一个值累加到train_l_sum变量中
        valid_l_sum += valid_ls[-1]
        if i == 0: # 第一次循环
            d2l.plot(list(range(1, num_epochs + 1)), [train_ls, valid_ls],
                     xlabel='epoch', ylabel='rmse', xlim=[1, num_epochs],
                     legend=['train', 'valid'], yscale='log')
        print(f'折{i + 1},训练log rmse{float(train_ls[-1]):f}, '
              f'验证log rmse{float(valid_ls[-1]):f}')
    return train_l_sum / k, valid_l_sum / k

五、模型选择(可选,炼丹步骤)

不断的更换超参数,保留最优的超参数。

k, num_epochs, lr, weight_decay, batch_size = 5, 100, 5, 0, 64
train_l, valid_l = k_fold(k, train_features, train_labels, num_epochs, lr,
                          weight_decay, batch_size)
print(f'{k}-折验证: 平均训练log rmse: {float(train_l):f}, '
      f'平均验证log rmse: {float(valid_l):f}')

六、训练

""" 训练与预测 """
def train_and_pred(train_features, test_features, train_labels, test_data,
                   num_epochs, lr, weight_decay, batch_size):
    net = get_net()
    train_ls, _ = train(net, train_features, train_labels, None, None,
                        num_epochs, lr, weight_decay, batch_size)
    d2l.plot(np.arange(1, num_epochs + 1), [train_ls], xlabel='epoch',
             ylabel='log rmse', xlim=[1, num_epochs], yscale='log')
    print(f'训练log rmse:{float(train_ls[-1]):f}')
    # 将网络应用于测试集。
    preds = net(test_features).detach().numpy()
    # 将其重新格式化以导出到Kaggle
    test_data['SalePrice'] = pd.Series(preds.reshape(1, -1)[0])
    submission = pd.concat([test_data['Id'], test_data['SalePrice']], axis=1)
    submission.to_csv('submission.csv', index=False)


k, num_epochs, lr, weight_decay, batch_size = 5, 100, 5, 0, 64
train_and_pred(train_features, test_features, train_labels, test_data,
               num_epochs, lr, weight_decay, batch_size)

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

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

相关文章

XSS简单介绍

目录 一、认识XSS 1.XSS原理 2.XSS分类 二、XSS漏洞复现 1.搭建靶机进行复现 2.案例解析 2.1第一关 2.2第二关 2.3第三关 2.4第四关 一、认识XSS 1.XSS原理 XSS跨站脚本攻击是指恶意攻击者往Web页面里插入恶意Script代码,当用户浏览该页之时,…

linux并发服务器 —— linux网络编程(七)

网络结构模式 C/S结构 - 客户机/服务器;采用两层结构,服务器负责数据的管理,客户机负责完成与用户的交互;C/S结构中,服务器 - 后台服务,客户机 - 前台功能; 优点 1. 充分发挥客户端PC处理能力…

分布式锁之redis实现

docker安装redis 拉取镜像 docker pull redis:6.2.6 查看镜像 启动容器并挂载目录 需要挂在的data和redis.conf自行创建即可 docker run --restart always -d -v /usr/local/docker/redis/redis.conf:/usr/local/etc/redis/redis.conf -v /usr/local/docker/redis/data:/dat…

leetcode986. 区间列表的交集(java)

区间列表的交集 题目描述贪心 - 合并区间代码演示 题目描述 难度 - 中等 leetcode986. 区间列表的交集 给定两个由一些 闭区间 组成的列表,firstList 和 secondList ,其中 firstList[i] [starti, endi] 而 secondList[j] [startj, endj] 。每个区间列表…

【数学建模竞赛】超详细Matlab二维三维图形绘制

二维图像绘制 绘制曲线图 g 是表示绿色 b--o是表示蓝色/虚线/o标记 c*是表示蓝绿色(cyan)/*标记 ‘MakerIndices,1:5:length(y) 每五个点取点(设置标记密度) 特殊符号的输入 序号 需求 函数字符结构 示例 1 上角标 ^{ } title( $ a…

Arthas教程 - 命令篇 (二)

目录 一、Attach 黏附一个进程 1.1 准备代码 1.2 启动Demo 1.3 启动arthas 1.4 通过浏览器连接arthas 二、常用命令 2.1 dashboard 仪表盘 2.2 cls 清屏 2.3 thread 线程 2.4 jad 反编译类 2.5 watch 监视 2.6 退出arthas 三、基础命令 3.1 help 3.2 cat 3.3 …

小米新机代号“Manet”:搭载高通8 Gen 3 处理器 + 金属中框设计

根据数码闲聊站和体验more的消息爆料,小米Redmi K70 Pro被代号为“Manet”,将搭载高通SM8650处理器,这是骁龙8 Gen 3移动平台的一部分。该处理器基于台积电N4P工艺制程打造,具有强大的性能表现。 CPU包含1*3.19GHz X45*2.96GHz A7…

Python Opencv实践 - 矩形轮廓绘制(直边矩形,最小外接矩形)

import cv2 as cv import numpy as np import matplotlib.pyplot as pltimg cv.imread("../SampleImages/stars.png") plt.imshow(img[:,:,::-1])img_gray cv.cvtColor(img, cv.COLOR_BGR2GRAY) #通过cv.threshold转换为二值图 ret,thresh cv.threshold(img_gray,…

Error from server (NotFound): pods “nginx-57d84f57dc-b866m“ not found

原因:机房断电,导致服务重启 [rootmaster1 logs]# kubectl get pod NAME READY STATUS RESTARTS AGE nginx-57d84f57dc-57fkf 1/1 Running 0 75s [rootmaster1 logs]# kubectl logs -f nginx-5…

nginx使用详解

文章目录 一、前言二、nginx使用详解2.1、nginx特点2.2 静态文件处理2.3 反向代理2.4 负载均衡2.5 高级用法2.5.1 正则表达式匹配2.5.2 重定向 三、总结 一、前言 本文将详细介绍nginx的各个功能使用,主要包括 二、nginx使用详解 2.1、nginx特点 高性能&#xff…

【JVM】垃圾收集算法

文章目录 分代收集理论标记-清除算法标记-复制算法标记-整理算法 分代收集理论 当前商业虚拟机的垃圾收集器,大多数都遵循了“分代收集”(Generational Collection)[1]的理论进 行设计,分代收集名为理论,实质是一套符…

C#循环定时上传数据,失败重传解决方案,数据库标识

有些时候我们需要定时的上传一些数据库的数据,在数据不完整的情况下可能上传失败,上传失败后我们需要定时在重新上传失败的数据,该怎么合理的制定解决方案呢?下面一起看一下: 当然本篇文章只是提供一个思路&#xff0…

windows系统bat脚本调用powershell脚本

前言 项目上有些项目既使用了bat脚本,又使用了powershell脚本; 需要两种脚本配合使用; bat调用powershell 不隐藏窗口运行 bat脚本代码:执行当前路径下的1.ps1脚本文件 start powershell .\1.ps1pause powershell脚本代码&…

025: vue父子组件中传递方法控制:$emit,$refs,$parent,$children

第025个 查看专栏目录: VUE ------ element UI 专栏目标 在vue和element UI联合技术栈的操控下,本专栏提供行之有效的源代码示例和信息点介绍,做到灵活运用。 (1)提供vue2的一些基本操作:安装、引用,模板使…

prometheus通过blackbox-exporter监控web站点证书

1 概述 线上站点普遍是https,因此监控https web站点的证书的过期时间,是一个基础性需求。例如,证书过期会导致tls握手失败,进而导致用户无法正常访问web站点。 blackbox-expoter是一个web服务,它暴露了一个接口&#…

如何在面试中处理竞争与压力

🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🦄 博客首页——🐅🐾猫头虎的博客🎐 🐳 《面试题大全专栏》 🦕 文章图文…

WebSocket与SSE区别

一,websocket WebSocket是HTML5下一种新的协议(websocket协议本质上是一个基于tcp的协议) 它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯的目的 Websocket是一个持久化的协议 websocket的原理 …

算法笔记:二叉树

1 基本二叉树 二叉树是一种树形数据结构,其中每个节点最多有两个子节点,通常称为“左子节点”和“右子节点”。 二叉树的根是唯一没有父节点的节点,而所有其他节点都有一个父节点和零个或两个子节点。 1.1 基础术语 节点(Node&…

服务运营 | MSOR文章精选:远程医疗服务中的统计与运筹(二)

作者信息:王畅,陈盈鑫 编者按 在上一期中,我们分享了与远程医疗中运营管理问题相关的两篇文章。其一发表在《Stochastic Systems》,旨在使用排队论与流体近似的方法解决远程医疗中资源配置的问题;其二发表在《Managem…

R_I相关指令函数(SMART PLC梯形图代码)

大部分小型PLC可能并没有R_I(浮点数转单字)指令,这篇博客我们介绍简单实用的一些转换FC,这些FC其实并不复杂,但是可以大大简化我们的代码量,使代码阅读起来更简介明了。SMART PLC的ABS()指令请查看下面文章链接: PLC绝对值指令AB…