当前位置: 首页 > news >正文

深度学习-Kaggle实战1(房价预测)

目录

1 基本原理

2 Kaggle

3 数据集

3.1数据下载

3.2 数据预处理

4 训练

4.1 定义模型

4.2 模型选择

5 预测并提交

参考文献


1 基本原理

        本章是第一次kaggle实战,我将先讲解书中关于数据集下载的方法和kaggle的注册部分,然后我们按照数据预处理、模型训练与参数选择、提交预测结果的顺序来完成实战。

2 Kaggle

        Kaggle是一个当今流行举办机器学习比赛的平台。注册时如果无法显示验证码,参考该贴解决(这里)。

        房价预测的项目由此进入(这里)。如下图所示,点击右上角加入比赛

3 数据集

3.1数据下载

        按照书中代码来编写,首先定义了DATA_HUB用于存放 dataName->[url,sha-1key] 的映射,其中sha-1秘钥用于检查文件完整性。然后定义了DATA_URL,这是接下来用到的各种数据集的下载地址根目录。

import hashlib
import os
import tarfile
import zipfile
import requests#@save
DATA_HUB = dict()
DATA_URL = 'http://d2l-data.s3-accelerate.amazonaws.com/'

        接下来定义了三个函数,分别实现指定数据集的下载,指定数据集下载和解压以及下载DATA_HUB中所有数据集。

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:breaksha1.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 fnamedef 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_dirdef download_all():  #@save"""下载DATA_HUB中的所有文件"""for name in DATA_HUB:download(name)

        接下来使用上面定义的函数下载房价预测的数据集

%matplotlib inline
import numpy as np
import pandas as pd
import torch
from torch import nn
from d2l import torch as d2lDATA_HUB['kaggle_house_train'] = (  #@saveDATA_URL + 'kaggle_house_pred_train.csv','585e9cc93e70b39160e7921475f9bcd7d31219ce')DATA_HUB['kaggle_house_test'] = (  #@saveDATA_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)

        训练集和测试集的大小分别为1460和1459,训练集每个样本有80个特征和1个标签,而测试集样本没有标签。

        查看训练集第一行的前三列和后三列

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

        可以看到第一列Id并不适合作为特征值参与训练,在整理数据集时我们将训练集第一列和最后一列(标签)去掉,测试集第一列去掉,然后两组数据特征合并来参与后续处理。

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

3.2 数据预处理

        处理前先查看all_freatures的形状

        由于all_freatures是DataFrame类型,可以通过dtypes查看各列的类型

        可以看到特征值有各种不同的数据类型。首先我们对其中数值型的特征值进行标准化处理

# 若无法获得测试数据,则可根据训练数据计算均值和标准差
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
all_features[numeric_features] = all_features[numeric_features].fillna(0)

        上面的代码中all_features.dtypes是series类型,也可以看做自定义索引的list类型,所以可以像普通list一样用同规格的bool型series作为索引从而提取出类型不为object的所有元素。再用.index取出索引值,这样numeric_features中就包含了所有数值型特征名。再用其作为all_features的索引批量应用lambda函数进行标准化,使得所有数值型特征值满足均值为0,方差为1。标准化以后各特征值的均值都为0,所以对于缺失值使用均值填充时填入0即可。

        接下来处理非数值项(离散值)。采用独热编码处理即可。

        独热编码(One-Hot Encoding)是一种将分类变量转换为二进制向量的技术。它的主要目的是将分类变量转换为机器学习算法能够处理的格式,从而避免数值关系的误判。

        独热编码的基本原理是为每个分类特征的每个可能值创建一个新的二进制特征。在任何给定时间,只有一个特征被激活(标记为1),而其他所有特征都被标记为0。例如,对于动物类别“猫、狗、乌龟、鱼”,可以将其编码为:

  • 猫:[1, 0, 0, 0]

  • 狗:[0, 1, 0, 0]

  • 乌龟:[0, 0, 1, 0]

  • 鱼:[0, 0, 0, 1]

# “Dummy_na=True”将“na”(缺失值)视为有效的特征值,并为其创建指示符特征
all_features = pd.get_dummies(all_features, dummy_na=True)

        独热编码调用pd.get_dummies()函数即可自动完成,其中选项dummy_na=True表示显示地将缺失值作为一列参与编码。

        查看编码后的特征维度,可以看到经过独热编码后特征数从79变为了331

        数据处理完成后,重新将all_featrues划分为训练集和测试集,并转换为tensor

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)

4 训练

4.1 定义模型

        定义一个函数,返回单层的线性模型。该模型训练时采用均方误差损失。

loss = nn.MSELoss()
in_features = train_features.shape[1]def get_net():net = nn.Sequential(nn.Linear(in_features,1))return net

        定义误差评价函数。由于我们更关心相对误差,所以根据以下公式得到函数

\sqrt{\frac{1}{n}\sum_{i=1}^n\left(\log y_i -\log \hat{y}_i\right)^2}.

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

        定义训练函数。与前面的SGD优化器不同,这里使用了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

4.2 模型选择

        这里采用前面提到的k折交叉验证(这里)来完成模型参数的选择。

        首先定义k折交叉验证的数据划分函数和训练函数。

def get_k_fold_data(k, i, X, y):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], 0)y_train = torch.cat([y_train, y_part], 0)return X_train, y_train, X_valid, y_validdef 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()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.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折交叉验证每一轮训练时都会重新初始化一个新的线性模型,训练之后进行验证。所以其主要目的在于多次验证用于初始化模型的超参数设置是否合理。

        接下来设置一组超参数进行5折交叉验证

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

        为了寻找更好的模型,下面进行了几种调整

        1.调整学习率5->14

        2.为模型增加隐藏层,并调整学习率、训练轮次和权重衰减

net = nn.Sequential(nn.Linear(in_features,3),nn.ReLU(),nn.Linear(3,1))
k, num_epochs, lr, weight_decay, batch_size = 5, 50, 0.3, 10, 64

5 预测并提交

        采用调整好的模型预测测试集数据

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()# 将其重新格式化以导出到Kaggletest_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)

        jupyter notebook默认工作路径在%HOMEPATH%,运行上述代码后即可在该路径下看到预测结果的csv文件

        在kaggle比赛界面中点击右上角提交按钮,在将该文件拖拽至提交框提交即可。

        下面分别展示提交书中原始模型以及两种优化后的模型得分

        以及菜菜的排名展示


参考文献

[1]《动手学深度学习》,https://zh-v2.d2l.ai/

[2]Kaggle,https://www.kaggle.com/

[3]如何注册kaggle账号,https://zhuanlan.zhihu.com/p/623467866

http://www.dtcms.com/a/458072.html

相关文章:

  • 邢台高端网站建设公司wordpress 单页模板
  • 有设计师做的装修效果图的网站关于做营销型网站的建议
  • C#+WPF+Opencv模块化开发视觉对位系统
  • 网站专业优化公司广州工商学院门户网站
  • 贪心:Stall Reservations S
  • 商务网站怎么做wordpress模板 更换
  • 企业建设网站的目的wordpress路由与模板调用
  • 滕州住房和城乡建设局网站企业网站设计建设
  • C4D域功能深度解析:随机域、着色器域、声音域、公式域与Python域详解
  • SQL 面试题解析:如何用多表查询写用户订单统计?
  • 建设网站需要收费吗wordpress前台注册登录弹窗代码
  • 双通道记忆网络架构在实际部署时平衡计算资源
  • 网站与域名的区别提供中山精品网站建设
  • 从定性到量化:为何指标是非功能性需求的灵魂与尺度
  • UV环境+UV环境中CUDA安装
  • 一家专门做动漫的网站钓鱼网站源码
  • 网站打开慢 可以只换空间不换域名吗在国外建设网站
  • Oracle 11gR2 RMAN备份
  • C++---》stl : pair 从使用到模拟实现
  • 自己做的网站很卡百度seo规则最新
  • 网站建设管理教程视频厦门网站建设哪家比较好
  • Java-Spring入门指南(二十一)Thymeleaf 视图解析器
  • wordpress phpdisk上海做网站seo
  • 徐州网站简介校园网站建设需要什么
  • mysql基础【SQL语句】
  • 二手车网站程序霍山网站建设
  • 【深度学习新浪潮】有没有专门的风格迁移库可以在Python中使用?
  • php做的网站用什么后台基层政权和社区建设司网站
  • 在VMWare上安装openEuler 25.09
  • 网站即将上线页面代码如何开科技软件