【动手学深度学习】part15-基于kaggle数据集预测房价算法实例

基于沐神part15课程学习、复现、理解预测房价算法实例

文章目录

一、学习目标

沐神在part15课程中,引入了一个“预测房价”的深度学习实例(其实也算不上深度学习,毕竟就简单的单隐藏层线性模型)。

  • 待解决问题

🌟实例中要解决的目标问题为:给定一个来源于kaggle网站的训练数据集(train_data)+测试数据集(test_data),基于train_data训练模型,应用与test_data以预测test_data上房价。

  • 数据集说明

① train_data:其包含待预测房价的79项特征+房价1项特征,经过独热码编码后变为330项特征+房价1项特征。

② test_data:其包含待预测房价的79项特征,经过独热码编码后变为330项特征。

二、算法实例

2.1实例代码

以免自己对代码中哪一行操作不理解,将每一行的操作进行了详细备注

import numpy as np
import pandas as pd
import torch
from torch import nn
from d2l import torch as d2l

train_data = pd.read_csv('../data/kaggle_house_pred_train.csv') #训练集数据
test_data = pd.read_csv('../data/kaggle_house_pred_test.csv')   #测试集数据

'''找出在test_data,但不在train_data的列
train_data比test_data多一个“SalePrice”列,即房价
'''
elements_in_train_not_in_test = train_data.columns.difference(test_data.columns)


print(train_data.shape)
print(test_data.shape)

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

#将id列删除,取train_data所有行,1列到-1列,test_data所有行,1列至最后一列
all_features = pd.concat((train_data.iloc[:, 1:-1], test_data.iloc[:, 1:]))

'''处理缺失值,替换为对应的特征的平均值'''
numeric_features = all_features.dtypes[all_features.dtypes != 'object'].index   #用来从一个DataFrame中提取非对象类型(即非字符串类型)的列名
# 通过将特征重新缩放到零均值和单位方差来标准化数据,对每列进行了标准化处理,每列的均值为0,标准差为1的标准正态分布。
# =============================================================================
# 标准化不会改变数据之间的相对关系。
# 标准化不会改变数据的分布形状。如果数据原来是正态分布的,标准化后仍然是正态分布;如果数据原来是偏态分布的,标准化后仍然是偏态分布。
# 对于某些机器学习算法(如线性回归、支持向量机、神经网络等),标准化可以提高模型的收敛速度和性能,因为这些算法对输入数据的尺度敏感。
# =============================================================================
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)

'''处理离散值。 我们用一次独热编码(one-hot)替换它们'''
all_features = pd.get_dummies(all_features, dummy_na=True)
all_features.shape

'''从pandas格式中提取NumPy格式,并将其转换为张量表示,训练集,验证集,训练标签'''
n_train = train_data.shape[0]
train_features = torch.tensor(all_features[:n_train].values.astype(float),
                              dtype=torch.float32)  #train_features取all_features前0至n_train行数据
test_features = torch.tensor(all_features[n_train:].values.astype(float),
                             dtype=torch.float32) #test_features取all_features前n_train至最后一行数据
train_labels = torch.tensor(train_data.SalePrice.values.reshape(-1, 1).astype(float),
                            dtype=torch.float32) #.reshape(-1, 1) 方法将一维数组转换为二维数组,其中 -1 表示自动计算该维度的大小,1 表示第二个维度的大小为1。这通常用于将一维数组转换为列向量。

loss = nn.MSELoss() #MSELoss 是均方误差损失函数,预测值与真实值之间的平方差的平均值。
in_features = train_features.shape[1]

'''采用单层的线性回归'''
def get_net():
    net = nn.Sequential(nn.Linear(in_features, 1)) #用于创建一个简单的线性回归模型,Y=WX+b,W、b在创建网络时会随机赋初值
    return net

'''用相对误差来估计,因为房价的偏差还要考虑房子的状态异同,例如大小、装修风格等'''
def log_rmse(net, features, labels):
    clipped_preds = torch.clamp(net(features), 1, float('inf')) #torch.clamp 是 PyTorch 中用于将张量中的值限制在一个指定范围内的重要函数,这里用于将 net(features) 的输出值限制在1到正无穷之间,在这里net输出的负值就直接改为1,这样不会带来误差吗?
    rmse = torch.sqrt(loss(torch.log(clipped_preds), torch.log(labels)))
    return rmse.item()  #将一个标量(scalar)张量转换为一个 Python 标准数据类型的值

'''用于打印net网络模型的参数,weight,bias'''
def outputPara_net(net):
    # 输出模型的结构
    print("Model Structure:")
    print(net)
    # 输出模型的参数
    print("\nModel Parameters:")
    for name, param in net.named_parameters():
        print(f"Parameter Name: {name}")
        print(f"Parameter Values: {param}")
        print(f"Parameter Shape: {param.shape}")
        print("-" * 50)

'''我们的训练函数将借助Adam优化器,理解为平滑的SGD,优势是对于学习率不敏感'''
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) #构造样本迭代获取器
    optimizer = torch.optim.Adam(net.parameters(), lr=learning_rate,
                                 weight_decay=weight_decay)
    for epoch in range(num_epochs): #一个 epoch 指的是在整个训练数据集上完成一次完整的前向传播和反向传播的过程
        for X, y in train_iter: #每次不重复地随机获取batch_size个训练样本
            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))
    #测试模型训练情况
    # aaa_t = net(test_features).detach().numpy
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值