文章目录

  • 1. Kaggle比赛
  • 2. 获取和读取数据集
  • 3. 预处理数据
  • 4. 训练模型
  • 5. KKK折交叉验证
  • 6. 模型选择
  • 7. 预测并在Kaggle提交结果

1. Kaggle比赛

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

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

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

2. 获取和读取数据集

比赛数据分为训练数据集和测试数据集。两个数据集都包括每栋房子的特征,如街道类型、建造年份、房顶类型、地下室状况等特征值。这些特征值有连续的数字、离散的标签甚至是缺失值“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 d2lprint(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:]))

3. 预处理数据

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

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

4. 训练模型

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

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​和对应的真实标签y1,…,yny_1,\ldots, y_ny1​,…,yn​,它的定义为

1n∑i=1n(log⁡(yi)−log⁡(y^i))2.\sqrt{\frac{1}{n}\sum_{i=1}^n\left(\log(y_i)-\log(\hat y_i)\right)^2}.n1​i=1∑n​(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

5. KKK折交叉验证

下面实现了一个函数,它返回第i折交叉验证时所需要的训练和验证数据。

def get_k_fold_data(k, i, X, y):# 返回第i折交叉验证时所需要的训练和验证数据assert k > 1fold_size = X.shape[0] // kX_train, y_train = None, Nonefor 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_partelif X_train is None:X_train, y_train = X_part, y_partelse: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

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

def k_fold(k, X_train, y_train, num_epochs,learning_rate, weight_decay, batch_size):train_l_sum, valid_l_sum = 0, 0for 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

6. 模型选择

我们使用一组未经调优的超参数并计算交叉验证误差。可以改动这些超参数来尽可能减小平均测试误差。

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

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

7. 预测并在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上提交我们预测得出的结果,并且查看与测试数据集上真实房价(标签)的误差。具体来说有以下几个步骤:登录Kaggle网站,访问房价预测比赛网页,并点击右侧“Submit Predictions”或“Late Submission”按钮;然后,点击页面下方“Upload Submission File”图标所在的虚线框选择需要提交的预测结果文件;最后,点击页面最下方的“Make Submission”按钮就可以查看结果了,如图3.9所示。

pytorch学习笔记(十四):实战Kaggle比赛——房价预测相关推荐

  1. 《动手深度学习》4.10. 实战Kaggle比赛:预测房价

    4.10. 实战Kaggle比赛:预测房价 本节内容预览 数据 下载和缓存数据集 访问和读取数据集 使用pandas读入并处理数据 数据预处理 处理缺失值&对数值类数据标准化 处理离散值-on ...

  2. PyTorch学习笔记(四):PyTorch基础实战

    PyTorch实战:以FashionMNIST时装分类为例: 往期学习资料推荐: 1.Pytorch实战笔记_GoAI的博客-CSDN博客 2.Pytorch入门教程_GoAI的博客-CSDN博客 本 ...

  3. 吴恩达《机器学习》学习笔记十四——应用机器学习的建议实现一个机器学习模型的改进

    吴恩达<机器学习>学习笔记十四--应用机器学习的建议实现一个机器学习模型的改进 一.任务介绍 二.代码实现 1.准备数据 2.代价函数 3.梯度计算 4.带有正则化的代价函数和梯度计算 5 ...

  4. Polyworks脚本开发学习笔记(十四)-WORKSPACE信息读取及管理

    Polyworks脚本开发学习笔记(十四)-WORKSPACE信息读取及管理 Polyworks的工作任务存储分为工作区和项目两级,通过WORKSPACE命令获取工作任务信息,实现更好的任务管理. 下 ...

  5. 04.10. 实战Kaggle比赛:预测房价

    4.10. 实战Kaggle比赛:预测房价 详细介绍数据预处理.模型设计和超参数选择. 通过亲身实践,你将获得一手经验,这些经验将有益数据科学家的职业成长. import hashlib import ...

  6. 实战Kaggle比赛:预测房价

    文章目录 实战Kaggle比赛:预测房价 1 - 下载和缓存数据集 2 - 访问和读取数据集 3 - 数据预处理 4 - 训练 5 - K折交叉验证 6 - 模型选择 7 - 提交你的Kaggle预测 ...

  7. AI Studio 飞桨 零基础入门深度学习笔记2-基于Python编写完成房价预测任务的神经网络模型

    AI Studio 飞桨 零基础入门深度学习笔记2-基于Python编写完成房价预测任务的神经网络模型 波士顿房价预测任务 线性回归模型 线性回归模型的神经网络结构 构建波士顿房价预测任务的神经网络模 ...

  8. 动手学深度学习:3.16 实战Kaggle比赛:房价预测

    3.16 实战Kaggle比赛:房价预测 作为深度学习基础篇章的总结,我们将对本章内容学以致用.下面,让我们动手实战一个Kaggle比赛:房价预测.本节将提供未经调优的数据的预处理.模型的设计和超参数 ...

  9. pytorch学习笔记十二:优化器

    前言 机器学习中的五个步骤:数据 --> 模型 --> 损失函数 --> 优化器 --> 迭代训练,通过前向传播,得到模型的输出和真实标签之间的差异,也就是损失函数,有了损失函 ...

最新文章

  1. 计算机视觉方向简介 | 人体骨骼关键点检测综述
  2. mysql 主从相关
  3. python爬虫能干什么-Python爬虫能做什么
  4. 【VLC-Android】LibVLC API简介(相当于VLC的MediaPlayer)
  5. 线性表的顺序存储——顺序存储结构的抽象实现
  6. 【五校联考6day2】san
  7. 微信平台开发1--开发者模式基本配置
  8. 网络WIFI摄像机方案主控芯片最全介绍
  9. Linux服务器iops性能测试-fio
  10. 如何卸载zabbix且删除
  11. python 下标 遍历列表_Python中遍历列表中元素的操作
  12. 我把视频变成链接_H5中加视频?这才是正确姿势
  13. Android 客户端无法访问 服务器,无法将Android客户端与本地XMPP服务器连接
  14. while循环语法结构
  15. 在线ER模型设计工具,支持MySQL、SQLServer、Oracle、Postgresql sql导入,支持表、视图等编辑
  16. PPT打开密码,如何解密?
  17. 2020中职技能高考计算机,我市62名中职学生获得2020年技能高考操作考试满分
  18. 1.Diagno-基本概述
  19. mt6765和骁龙665哪个好_联发科MT6750和骁龙450哪个好 高通骁龙450与联发科MT6750区别对比评测...
  20. 我的校招——南京烽火笔试+格力初面

热门文章

  1. 传统的分布式应用集成技术(网摘)
  2. 函数:找出一句话中的第二个单词
  3. 原DTCoreText学习(三)-自定义DTAttributedTextCell
  4. 不贵难得之货,使民不盗
  5. HikariCP不断打印WARN日志Failed to validate connection com.mysql.jdbc.JDBC4Connection@xxxxx (...) Possibly
  6. 多个if和一个ifelse的区别
  7. Opengl_9_复合变换
  8. 事务的隔离级别与锁的申请和释放
  9. AndroidManifest.xml中的android:name是否带.的区别
  10. PYSQLITE用法初探