深度学习实战kaggle比赛:房价预测(kaggle-house-price)(代码片段)

ZSYL ZSYL     2023-02-12     213

关键词:

实战Kaggle比赛:房价预测

作为深度学习基础篇章的总结,我们将对本章内容学以致用。下面,让我们动手实战一个Kaggle比赛:房价预测本节将提供未经调优的数据的预处理、模型的设计和超参数的选择。我们希望读者通过动手操作、仔细观察实验现象、认真分析实验结果并不断调整方法,得到令自己满意的结果。

Kaggle比赛

Kaggle是一个著名的供机器学习爱好者交流的平台。图3.7展示了Kaggle网站的首页。为了便于提交结果,需要注册Kaggle账号。

图3.7 Kaggle网站首页

我们可以在房价预测比赛的网页上了解比赛信息和参赛者成绩,也可以下载数据集并提交自己的预测结果。该比赛的网页地址是 https://www.kaggle.com/c/house-prices-advanced-regression-techniques

图3.8 房价预测比赛的网页信息。比赛数据集可通过点击“Data”标签获取

图3.8展示了房价预测比赛的网页信息。

Kaggle网站如果没有VPN,无法正常注册,因此需要数据集的可以私聊我。

获取和读取数据集

比赛数据分为训练数据集和测试数据集。两个数据集都包括每栋房子的特征,如街道类型、建造年份、房顶类型、地下室状况等特征值。

这些特征值有连续的数字、离散的标签甚至是缺失值“na”。只有训练数据集包括了每栋房子的价格,也就是标签。我们可以访问比赛网页,点击图3.8中的“Data”标签,并下载这些数据集。

我们将通过pandas库读入并处理数据。在导入本节需要的包前请确保已安装pandas库,否则请参考下面的代码注释。

# 如果没有安装pandas,则反注释下面一行
# !pip install pandas

%matplotlib inline
import torch
import torch.nn as nn
import numpy as np
import pandas as pd
import sys
sys.path.append("..") 
import d2lzh_pytorch as d2l

print(torch.__version__)
torch.set_default_tensor_type(torch.FloatTensor)

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

train_data = pd.read_csv('../../data/kaggle_house/train.csv')
test_data = pd.read_csv('../../data/kaggle_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:]))

预处理数据

我们对连续数值的特征做标准化(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)

接下来将离散数值转成指示特征

举个例子,假设特征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)

请参考【特征提取】pd.get_dummies() 详解(One-Hot Encoding)

可以看到这一步转换将特征数从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)

训练模型

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

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_n y^1,,y^n和对应的真实标签 y 1 , … , y n y_1,\\ldots, y_n y1,,yn,它的定义为

1 n ∑ i = 1 n ( log ⁡ ( y i ) − log ⁡ ( y ^ i ) ) 2 . \\sqrt\\frac1n\\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

K K K折交叉验证

我们在3.11节(模型选择、欠拟合和过拟合)中介绍了 K K K折交叉验证。它将被用来选择模型设计并调节超参数。下面实现了一个函数,它返回第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 K K折交叉验证中我们训练 K 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(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

输出:

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, 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))

有时候你会发现一组参数的训练误差可以达到很低,但是在 K K K折交叉验证上的误差可能反而较高。

这种现象很可能是由过拟合造成的。因此,当训练误差降低时,我们要观察 K K K折交叉验证上的误差是否也相应降低。

预测并在Kaggle提交结果

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

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)

设计好模型并调好超参数之后,下一步就是对测试数据集上的房屋样本做价格预测。如果我们得到与交叉验证时差不多的训练误差,那么这个结果很可能是理想的,可以在Kaggle上提交结果。

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

输出:

train rmse 0.162085

上述代码执行完之后会生成一个submission.csv文件。这个文件是符合Kaggle比赛要求的提交格式的。

这时,我们可以在Kaggle上提交我们预测得出的结果,并且查看与测试数据集上真实房价(标签)的误差。

具体来说有以下几个步骤:

  1. 登录Kaggle网站,访问房价预测比赛网页,
  2. 并点击右侧“Submit Predictions”或“Late Submission”按钮;
  3. 然后,点击页面下方“Upload Submission File”图标所在的虚线框选择需要提交的预测结果文件;
  4. 最后,点击页面最下方的“Make Submission”按钮就可以查看结果了,

如图3.9所示:

图3.9 Kaggle预测房价比赛的预测结果提交页面

小结

  • 通常需要对真实数据做预处理。
  • 可以使用 K K K折交叉验证来选择模型并调节超参数。
import torch
import torch
import torch.nn as nn
import numpy as np
import pandas as pd
print(torch.__version__)
torch.set_default_tensor_type(torch.FloatTensor)  # 设置默认的tensor类型
1.9.1

Jupyter Notebook

读取数据

train_data = pd.read_csv('./data/house_price/train.csv')
test_data = pd.read_csv('./data/house_price/test.csv')
train_data.shape # 输出 (1460, 81)
(1460, 81)
test_data.shape # 输出 (1459, 80)
(1459, 80)
train_data.head()
IdMSSubClassMSZoningLotFrontageLotAreaStreetAlleyLotShapeLandContourUtilities...PoolAreaPoolQCFenceMiscFeatureMiscValMoSoldYrSoldSaleTypeSaleConditionSalePrice
0160RL65.08450PaveNaNRegLvlAllPub...0NaNNaNNaN022008WDNormal208500
1220RL80.09600PaveNaNRegLvlAllPub...0NaNNaNNaN052007WDNormal181500
2360RL68.011250PaveNaNIR1LvlAllPub...0NaNNaNNaN092008WDNormal223500
3470RL60.09550PaveNaNIR1LvlAllPub...0NaNNaNNaN022006WDAbnorml140000
4560RL84.014260PaveNaNIR1LvlAllPub...0NaNNaNNaN0122008WDNormal250000

5 rows × 81 columns

# 查看前4个样本的前4个特征、后2个特征和标签(SalePrice)
train_data.iloc[0:4, [0, 1, 查看详情  

小白学习之pytorch框架之实战kaggle比赛:房价预测(k折交叉验证*args**kwargs)

本篇博客代码来自于《动手学深度学习》pytorch版,也是代码较多,解释较少的一篇。不过好多方法在我以前的博客都有提,所以这次没提。还有一个原因是,这篇博客的代码,只要好好看看肯定能看懂(前提是python语法大概了解)... 查看详情

pytorch-在竞赛中去摸索用法,用房价预测比赛了解数据处理流程(代码片段)

实战Kaggle比赛:房价预测让我们动手实战一个Kaggle比赛:房价预测HousePrices-AdvancedRegressionTechniques|Kaggle。本文将提供未经调优的数据的预处理、模型的设计和超参数的选择。通过动手操作、仔细观察实验现象、认真分析实... 查看详情

kaggle房价预测经典文章

1:::​​xgboost​​2:::​​随机森林​​3:::​​​xgboost线性模型​​​4:::​​xgboost数据预处理​​            ​​数据预处理2​​5:::​​文章集合​​6:::... 查看详情

房价预测(代码片段)

--数据来源kaggle比赛本文仅就学习的机器学习算法进行简单的实践。 一、问题及数据导入     显然,目的肯定是根据现有的数据,来对房价进行预测了,本数据变量较多,这里不再一一叙述,官网下载的数... 查看详情

比赛教程-如何参加kaggle数据科学比赛(上)

...比赛,再作探讨#TODO#)万物皆数据,数据科学特别是机器学习正在改变世界。说到数据科学就绕不开Kaggle-Google旗下全球最大的数据科学平台(Kaggle-YourHomeforDataScience)。Google首席经济师哈尔·范里安称Kaggle提供了一种“将... 查看详情

预告-分享kaggle上的nfl比赛码数预测

Hello,近期会分享最近的一个Kaggle上的比赛,NFL比赛的码数预测,通过这个比赛还是学到很多,虽然最后分数不理想。。。。这篇分享的内容适用于绝大多于的关于团队竞技类比赛的场景下的预测问题,比如足球、篮球、王者荣... 查看详情

kaggle比赛总结

做完Kaggle比赛已经快五个月了,今天来总结一下,为秋招做个准备。题目要求:根据主办方提供的超过4天约2亿次的点击数据,建立预测模型预测用户是否会在点击移动应用广告后下载应用程序。数据集特点:数据量很大,有2亿... 查看详情

kaggle房价预测全过程+原始数据集+预处理后数据集(代码片段)

1.数据集链接:https://pan.baidu.com/s/1GPpCp04MPhCRjmoXr59kiQ 提取码:8ko6 2.数据集读取#数据读取train_data=pd.read_csv("train.csv")test_data=pd.read_csv("test.csv")print("train_ 查看详情

kaggle比赛之『旧金山犯罪分类预测』demo(代码片段)

importpandasaspdimportnumpyasnp#用pandas载入csv训练数据,并解析第一列为日期格式train=pd.read_csv(‘../input/train.csv‘,parse_dates=[‘Dates‘])test=pd.read_csv(‘../input/test.csv‘,parse_dates=[‘Dates‘])trainimportpandasasp 查看详情

机器学习:kaggle项目(房价:先进的回归技术)(代码片段)

一、项目目录(一)数据加载基础统计特征分类基本分布(scatter) (二)数据分析正态性检验偏离度分析(hist|scatter)峰度分析(hist|scatter)分散度分析(box)特征本身分散度SalePrice的分散度方差齐次检验方差分析(bar)scipy.stats.f_oneway()... 查看详情

我的第一个kaggle比赛学习-titanic(代码片段)

背景Titanic:MachineLearningfromDisaster-Kaggle2年前就被推荐照着这个比赛做一下,结果我打开这个页面便蒙了,完全不知道该如何下手。两年后,再次打开这个页面,看到清清楚楚的TitanicTutorial-Kaggle,完全傻瓜式的照着做就能做下来。... 查看详情

kaggle比赛实践m5-比赛介绍

...场竞争中,除了传统的预测方法外,你还面临着使用机器学习来提高预测精度的挑战。尼科西亚大学马克里奇斯开放预测中心(MOFC)进行前沿预测研究,并提供商业预测培训。它帮助公司实现准确的预测,估计不确定性水平,... 查看详情

遇事不决,xgboost,梯度提升比深度学习更容易赢得kaggle竞赛

...c;用什么算法最容易拿奖金?你可能会说:当然是深度学习。还真不是,据统计获胜最多的是像XGBoost这种梯度提升算法,之前在周志华教授的boosting视频中也有详细介绍。这就奇 查看详情

遇事不决,xgboost,梯度提升比深度学习更容易赢得kaggle竞赛

...c;用什么算法最容易拿奖金?你可能会说:当然是深度学习。还真不是,据统计获胜最多的是像XGBoost这种梯度提升算法,之前在周志华教授的boosting视频中也有详细介绍。这就奇了怪了,深 查看详情

kaggle实战入门:泰坦尼克号生还预测(进阶版)(代码片段)

...入门:泰坦尼克号生还预测(基础版)对机器学习的全流程进行了总体介绍。本文继续以泰坦尼克号生还预测为例,对机器学习中的特征工程、模型构建进行深入解读。1.加载数据由于针对训练数据集、测试数据... 查看详情

深度学习模型不提供预测作为输入层是不兼容的

】深度学习模型不提供预测作为输入层是不兼容的【英文标题】:Deeplearningmodelnotgivingpredictionsasinputlayerisincompatible【发布时间】:2020-12-3019:58:12【问题描述】:以下是使用Kaggle对手势识别进行图像分类的简单模型dataset#--编码:ut... 查看详情

《机器学习算法分类讲解与kaggle实战》专栏概述

查看详情