【从零开始学习深度学习】15. Pytorch实战Kaggle比赛:房价预测案例【含数据集与源码】

简介: 【从零开始学习深度学习】15. Pytorch实战Kaggle比赛:房价预测案例【含数据集与源码】


1 获取和读取数据集

数据分为训练数据集测试数据集。两个数据集都包括每栋房子的特征,如街道类型、建造年份、房顶类型、地下室状况等特征值。这些特征值有连续的数字、离散的标签甚至是缺失值“na”。只有训练数据集包括了每栋房子的价格,也就是标签。

我们将通过pandas库读入并处理数据。在导入本节需要的包前请确保已安装pandas库。

%matplotlib inline
import torch
import torch.nn as nn
import numpy as np
import pandas as pd
import sys 
import d2lzh_pytorch as d2l
torch.set_default_tensor_type(torch.FloatTensor)

假设解压后的数据位于./data/house/目录,它包括两个csv文件。下面使用pandas读取这两个文件。

train_data = pd.read_csv('./data/house/train.csv')
test_data = pd.read_csv('./data/house/test.csv')

训练数据集包括1460个样本、80个特征和1个标签。

train_data.shape # 输出 (1460, 81)

测试数据集包括1459个样本和80个特征。我们需要将测试数据集中每个样本的标签预测出来。

test_data.shape # 输出 (1459, 80)

让我们来查看前4个样本的前4个特征、后2个特征和标签(SalePrice)

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

可以看到第一个特征是Id,它能帮助模型记住每个训练样本,但难以推广到测试样本,所以我们不使用它来训练。我们将所有的训练数据和测试数据的79个特征按样本连结。

all_features = pd.concat((train_data.iloc[:, 1:-1], test_data.iloc[:, 1:]))

2 数据预处理

我们对连续数值的特征做标准化(standardization):设该特征在整个数据集上的均值为μ \muμ,标准差为σ \sigmaσ。那么,我们可以将该特征的每个值先减去μ \muμ再除以σ \sigmaσ得到标准化后的每个特征值。对于缺失的特征值,我们将其替换成该特征的均值。

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,所以可以直接用0来替换缺失值
all_features[numeric_features] = all_features[numeric_features].fillna(0)

接下来将离散数值转成One-hot指示特征。举个例子,假设特征MSZoning里面有两个不同的离散值RL和RM,那么这一步转换将去掉MSZoning特征,并新加两个特征MSZoning_RL和MSZoning_RM,其值为0或1。如果一个样本原来在MSZoning里的值为RL,那么有MSZoning_RL=1且MSZoning_RM=0。

# dummy_na=True表示将缺失值也当作合法的特征值并为其创建指示特征
all_features = pd.get_dummies(all_features, dummy_na=True)
all_features.shape # (2919, 331)

可以看到这一步转换将特征数从79增加到了331。

最后,通过values属性得到NumPy格式的数据,并转成Tensor方便后面的训练。

n_train = train_data.shape[0]
train_features = torch.tensor(all_features[:n_train].values, dtype=torch.float)
test_features = torch.tensor(all_features[n_train:].values, dtype=torch.float)
train_labels = torch.tensor(train_data.SalePrice.values, dtype=torch.float).view(-1, 1)

3 训练模型

我们使用基本的线性回归模型和平方损失函数来训练模型。

loss = torch.nn.MSELoss()
def get_net(feature_num):
    net = nn.Linear(feature_num, 1)
    for param in net.parameters():
        nn.init.normal_(param, mean=0, std=0.01)
    return net

下面定义比赛用来评价模型的对数均方根误差。给定预测值y ^ 1 , … , y ^ n \hat y_1, \ldots, \hat y_ny^1,,y^n和对应的真实标签y 1 , … , y n y_1,\ldots, y_ny1,,yn,它的定义为

1 n ∑ i = 1 n ( log ⁡ ( y i ) − log ⁡ ( y ^ i ) ) 2 . \sqrt{\frac{1}{n}\sum_{i=1}^n\left(\log(y_i)-\log(\hat y_i)\right)^2}.n1i=1n(log(yi)log(y^i))2.

对数均方根误差的实现如下。

def log_rmse(net, features, labels):
    with torch.no_grad():
        # 将小于1的值设成1,使得取对数时数值更稳定
        clipped_preds = torch.max(net(features), torch.tensor(1.0))
        rmse = torch.sqrt(loss(clipped_preds.log(), labels.log()))
    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 = [], []
    dataset = torch.utils.data.TensorDataset(train_features, train_labels)
    train_iter = torch.utils.data.DataLoader(dataset, batch_size, shuffle=True)
    # 这里使用了Adam优化算法
    optimizer = torch.optim.Adam(params=net.parameters(), lr=learning_rate, weight_decay=weight_decay) 
    net = net.float()
    for epoch in range(num_epochs):
        for X, y in train_iter:
            l = loss(net(X.float()), y.float())
            optimizer.zero_grad()
            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

4 K KK折交叉验证

之前文章介绍了K KK折交叉验证。它将被用来选择模型设计并调节超参数。下面实现了一个函数,它返回第i折交叉验证时所需要的训练和验证数据。

def get_k_fold_data(k, i, X, y):
    # 返回第i折交叉验证时所需要的训练和验证数据
    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), dim=0)
            y_train = torch.cat((y_train, y_part), dim=0)
    return X_train, y_train, X_valid, y_valid

K KK折交叉验证中我们训练K KK次并返回训练和验证的平均误差。

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(X_train.shape[1])
        train_ls, valid_ls = train(net, *data, num_epochs, learning_rate,
                                   weight_decay, batch_size)
        train_l_sum += train_ls[-1]
        valid_l_sum += valid_ls[-1]
        if i == 0:
            d2l.semilogy(range(1, num_epochs + 1), train_ls, 'epochs', 'rmse',
                         range(1, num_epochs + 1), valid_ls,
                         ['train', 'valid'])
        print('fold %d, train rmse %f, valid rmse %f' % (i, train_ls[-1], valid_ls[-1]))
    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('%d-fold validation: avg train rmse %f, avg valid rmse %f' % (k, train_l, valid_l))

输出:

fold 0, train rmse 0.170585, valid rmse 0.156860
fold 1, train rmse 0.162552, valid rmse 0.190944
fold 2, train rmse 0.164199, valid rmse 0.168767
fold 3, train rmse 0.168698, valid rmse 0.154873
fold 4, train rmse 0.163213, valid rmse 0.183080
5-fold validation: avg train rmse 0.165849, avg valid rmse 0.170905

有时候你会发现一组参数的训练误差可以达到很低,但是在K KK折交叉验证上的误差可能反而较高。这种现象很可能是由过拟合造成的。因此,当训练误差降低时,我们要观察K KK折交叉验证上的误差是否也相应降低。

5 预测并保存结果

下面定义预测函数。在预测之前,我们会使用完整的训练数据集来重新训练模型,并将预测结果存成提交所需要的格式。

def train_and_pred(train_features, test_features, train_labels, test_data,
                   num_epochs, lr, weight_decay, batch_size):
    net = get_net(train_features.shape[1])
    train_ls, _ = train(net, train_features, train_labels, None, None,
                        num_epochs, lr, weight_decay, batch_size)
    d2l.semilogy(range(1, num_epochs + 1), train_ls, 'epochs', 'rmse')
    print('train rmse %f' % train_ls[-1])
    preds = net(test_features).detach().numpy()
    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)

设计好模型并调好超参数之后,下一步就是对测试数据集上的房屋样本做价格预测。

train_and_pred(train_features, test_features, train_labels, test_data, num_epochs, lr, weight_decay, batch_size)

输出:

train rmse 0.162085

总结

  • 通常需要对真实数据做预处理。
  • 可以使用K KK折交叉验证来选择模型并调节超参数。


相关文章
|
9月前
|
机器学习/深度学习 PyTorch TensorFlow
TensorFlow与PyTorch深度对比分析:从基础原理到实战选择的完整指南
蒋星熠Jaxonic,深度学习探索者。本文深度对比TensorFlow与PyTorch架构、性能、生态及应用场景,剖析技术选型关键,助力开发者在二进制星河中驾驭AI未来。
987 13
|
11月前
|
机器学习/深度学习 数据采集 算法
PCB电路板缺陷检测数据集(近千张图片已划分、已标注)| 适用于YOLO系列深度学习检测任务【数据集分享】
在现代电子制造中,印刷电路板(PCB)是几乎所有电子设备的核心组成部分。随着PCB设计复杂度不断增加,人工检测PCB缺陷不仅效率低,而且容易漏检或误判。因此,利用计算机视觉和深度学习技术对PCB缺陷进行自动检测成为行业发展的必然趋势。
PCB电路板缺陷检测数据集(近千张图片已划分、已标注)| 适用于YOLO系列深度学习检测任务【数据集分享】
|
11月前
|
机器学习/深度学习 人工智能 监控
河道塑料瓶识别标准数据集 | 科研与项目必备(图片已划分、已标注)| 适用于YOLO系列深度学习分类检测任务【数据集分享】
随着城市化进程加快和塑料制品使用量增加,河道中的塑料垃圾问题日益严重。塑料瓶作为河道漂浮垃圾的主要类型,不仅破坏水体景观,还威胁水生生态系统的健康。传统的人工巡查方式效率低、成本高,难以满足实时监控与治理的需求。
|
11月前
|
机器学习/深度学习 人工智能 监控
坐姿标准好坏姿态数据集(图片已划分、已标注)|适用于YOLO系列深度学习分类检测任务【数据集分享】
坐姿标准好坏姿态数据集的发布,填补了计算机视觉领域在“细分健康行为识别”上的空白。它不仅具有研究价值,更在实际应用层面具备广阔前景。从青少年的健康教育,到办公室的智能提醒,再到驾驶员的安全监控和康复训练,本数据集都能发挥巨大的作用。
坐姿标准好坏姿态数据集(图片已划分、已标注)|适用于YOLO系列深度学习分类检测任务【数据集分享】
|
机器学习/深度学习 人工智能 监控
单车、共享单车已标注数据集(图片已划分、已标注)|适用于深度学习检测任务【数据集分享】
数据是人工智能的“燃料”。一个高质量、标注精准的单车与共享单车数据集,不仅能够推动学术研究的进步,还能为智慧交通、智慧城市的建设提供有力支撑。 在计算机视觉领域,研究者们常常会遇到“数据鸿沟”问题:公开数据集与真实业务需求之间存在不匹配。本次分享的数据集正是为了弥补这一不足,使得研究人员与工程师能够快速切入单车检测领域,加速模型从实验室走向真实应用场景。
|
11月前
|
PyTorch 算法框架/工具 异构计算
PyTorch 2.0性能优化实战:4种常见代码错误严重拖慢模型
我们将深入探讨图中断(graph breaks)和多图问题对性能的负面影响,并分析PyTorch模型开发中应当避免的常见错误模式。
578 9
|
机器学习/深度学习 数据采集 存储
深度学习在DOM解析中的应用:自动识别页面关键内容区块
本文探讨了如何通过深度学习模型优化东方财富吧财经新闻爬虫的性能。针对网络请求、DOM解析与模型推理等瓶颈,采用代理复用、批量推理、多线程并发及模型量化等策略,将单页耗时从5秒优化至2秒,提升60%以上。代码示例涵盖代理配置、TFLite模型加载、批量预测及多线程抓取,确保高效稳定运行,为大规模数据采集提供参考。
524 0
|
机器学习/深度学习 编解码 人工智能
计算机视觉五大技术——深度学习在图像处理中的应用
深度学习利用多层神经网络实现人工智能,计算机视觉是其重要应用之一。图像分类通过卷积神经网络(CNN)判断图片类别,如“猫”或“狗”。目标检测不仅识别物体,还确定其位置,R-CNN系列模型逐步优化检测速度与精度。语义分割对图像每个像素分类,FCN开创像素级分类范式,DeepLab等进一步提升细节表现。实例分割结合目标检测与语义分割,Mask R-CNN实现精准实例区分。关键点检测用于人体姿态估计、人脸特征识别等,OpenPose和HRNet等技术推动该领域发展。这些方法在效率与准确性上不断进步,广泛应用于实际场景。
1645 64
计算机视觉五大技术——深度学习在图像处理中的应用
|
机器学习/深度学习 自然语言处理 监控
深入探索:深度学习在时间序列预测中的强大应用与实现
时间序列分析是数据科学和机器学习中一个重要的研究领域,广泛应用于金融市场、天气预报、能源管理、交通预测、健康监控等多个领域。时间序列数据具有顺序相关性,通常展示出时间上较强的依赖性,因此简单的传统回归模型往往不能捕捉其中复杂的动态特征。深度学习通过其非线性建模能力和层次结构的特征提取能力,能够有效地捕捉复杂的时间相关性和非线性动态变化模式,从而在时间序列分析中展现出极大的潜力。
1315 0
|
机器学习/深度学习 运维 资源调度
深度学习在资源利用率优化中的应用:让服务器更聪明
深度学习在资源利用率优化中的应用:让服务器更聪明
739 6

热门文章

最新文章

推荐镜像

更多