Pytorch学习笔记(七)----多层神经网络预测房价(回归模型)+GPU的使用

序言

上一节学习了使用多层神经网络进行多分类问题的研究,这次我们使用多层神经网络进行回归问题的探索。同时学会如何在pytorch上使用GPU进行计算。本次的数据集不像上一节直接从网上下载就可以使用的标准数据集,模拟“自己采集的数据集”进行预处理,再进行训练。

基础理论

本节没有过多理论,只提一点,想使用GPU进行计算,只需要再输入的tensor与模型上加上‘.cuda()’就行,但想把计算结果转numpy必须先通过‘.cpu()’把tensor转入cpu才能进行,详情见代码。
数据集:https://pan.baidu.com/s/1bbXS5OZBvNzMEohljs-PtA
下载后解压放入代码同级文件夹,内含两个csv文件。

详细代码

代码中有很多详细的注解,方便理解整个流程。

import pandas as pd
import numpy as np
import torch
from torch.utils.data import DataLoader,TensorDataset
import time

strat = time.clock()
#读取原始数据
o_train = pd.read_csv('./dataset/train.csv')
o_test = pd.read_csv('./dataset/test.csv')
# print(o_train.shape)#(1314, 81)
# print(o_test.shape)#(146, 81)
#自己的数据集,需要对原始数据进行处理
#原数据 第一列是序号, 从第二列到导数第二列都是 维度,最后一列是房价
#对各维度的预处理(标准化)方式:数值型的转为[-1,1]之间 z-score 标准化,新数据=(原数据-均值)/标准差
#非数值型中的  无序型进行独热编码(one-hot encoding),有序型 自己定义其数值 转换为数值型  本数据集默认全部为无序型
#空值:每一个特征的全局平均值来代替无效值

#将训练集与测试集的特征数据合并在一起 统一进行处理
#loc:通过行标签索引数据 iloc:通过行号索引行数据 ix:通过行标签或行号索引数据(基于loc和iloc的混合)
all_features = pd.concat((o_train.loc[:,'MSSubClass':'SaleCondition'],o_test.loc[:,'MSSubClass':'SaleCondition']))
all_labels = pd.concat((o_train.loc[:,'SalePrice'],o_test.loc[:,'SalePrice']))

#对特征值进行数据预处理
# 取出所有的数值型特征名称
numeric_feats = all_features.dtypes[all_features.dtypes != "object"].index
object_feats = all_features.dtypes[all_features.dtypes == "object"].index
# 将数值型特征进行 z-score 标准化
all_features[numeric_feats] = all_features[numeric_feats].apply(lambda x: (x - x.mean()) / (x.std()))
#对无序型进行one-hot encoding
all_features = pd.get_dummies(all_features,prefix=object_feats, dummy_na=True)#
#空值:每一个特征的全局平均值来代替无效值 NA就是指空值
all_features = all_features.fillna(all_features.mean())

#对标签进行数据预处理
#对标签进行 z-score 标准化
mean = all_labels.mean()
std = all_labels.std()
all_labels = (all_labels - mean)/std

num_train = o_train.shape[0]
train_features = all_features[:num_train].values.astype(np.float32)#(1314, 331)
test_features = all_features[num_train:].values.astype(np.float32)#(146, 331)
train_labels = all_labels[:num_train].values.astype(np.float32)
test_labels = all_labels[num_train:].values.astype(np.float32)
#至此 输入数据准备完毕 可以看见 经过one-hot编码后  特征维度增加了很多 81->331

train_features = torch.from_numpy(train_features).cuda()
train_labels = torch.from_numpy(train_labels).unsqueeze(1).cuda()
test_features = torch.from_numpy(test_features).cuda()
test_labels = torch.from_numpy(test_labels).unsqueeze(1).cuda()
train_set = TensorDataset(train_features,train_labels)
test_set = TensorDataset(test_features,test_labels)
#定义迭代器
train_data = DataLoader(dataset=train_set,batch_size=64,shuffle=True)
test_data  = DataLoader(dataset=test_set,batch_size=64,shuffle=False)

#构建网络结构
class Net(torch.nn.Module):# 继承 torch 的 Module
    def __init__(self, n_feature, n_output):
        super(Net, self).__init__()     # 继承 __init__ 功能
        # 定义每层用什么样的形式
        self.layer1 = torch.nn.Linear(n_feature, 600).cuda()   #
        self.layer2 = torch.nn.Linear(600, 1200).cuda()   #
        self.layer3 = torch.nn.Linear(1200, n_output).cuda()

    def forward(self, x):   # 这同时也是 Module 中的 forward 功能
        x = self.layer1(x)
        x = torch.relu(x)      #
        x = self.layer2(x)
        x = torch.relu(x)      #
        x = self.layer3(x)
        return x
net = Net(331,1)

#反向传播算法 SGD Adam等
optimizer = torch.optim.Adam(net.parameters(), lr=1e-4)
#均方损失函数
criterion =	torch.nn.MSELoss()

#记录用于绘图
losses = []#记录每次迭代后训练的loss
eval_losses = []#测试的

for i in range(100):
    train_loss = 0
    # train_acc = 0
    net.train() #网络设置为训练模式 暂时可加可不加
    for tdata,tlabel in train_data:
        #前向传播
        y_ = net(tdata)
        #记录单批次一次batch的loss
        loss = criterion(y_, tlabel)
        #反向传播
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        #累计单批次误差
        train_loss = train_loss + loss.item()

    losses.append(train_loss / len(train_data))
    # 测试集进行测试
    eval_loss = 0
    net.eval()  # 可加可不加
    for edata, elabel in test_data:
        # 前向传播
        y_ = net(edata)
        # 记录单批次一次batch的loss,测试集就不需要反向传播更新网络了
        loss = criterion(y_, elabel)
        # 累计单批次误差
        eval_loss = eval_loss + loss.item()
    eval_losses.append(eval_loss / len(test_data))

    print('epoch: {}, trainloss: {}, evalloss: {}'.format(i, train_loss / len(train_data), eval_loss / len(test_data)))

#测试最终模型的精准度 算一下测试集的平均误差
y_ = net(test_features)
y_pre = y_ * std + mean
print(y_pre.squeeze().detach().cpu().numpy())
print(abs(y_pre - (test_labels*std + mean)).mean().cpu().item() )
end =time.clock()
print(end - strat)

结果展示与总结

epoch: 0, trainloss: 0.6617992662248158, evalloss: 0.19140221327543258
epoch: 1, trainloss: 0.2552897252497219, evalloss: 0.11139353662729264
epoch: 2, trainloss: 0.1762520470434711, evalloss: 0.08382588773965835
。。。
epoch: 97, trainloss: 0.0004879648414706545, evalloss: 0.08184200525283813
epoch: 98, trainloss: 0.0005651702446075866, evalloss: 0.08210518658161163
epoch: 99, trainloss: 0.0007712384457201031, evalloss: 0.0808665007352829

测试集平均误差:14676.31640625
使用gpu运算时间:18.571839933365858
使用cpu计算时间:26.877053331428794
可以发现 使用gpu的运算速度会加快,当迭代次数越大或者数据集越大的时候,gpu的优势越明显。在之后学习CNN进行图像识别的时候,必须要通过GPU才能进行训练,CPU的效率根本无法满足我们的需求。
其实,数据的预处理在模型训练中是非常重要的一环,有一半的代码量都是在对原数据进行处理,这是我们在实际生产中必须学会的技能。
大家可以尝试更改模型和模型的参数以及迭代次数优化最后的结果。

  • 20
    点赞
  • 129
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值