【深度学习实战】利用Linear Regression预测房价

server/2024/9/24 13:22:58/

本文参考了李沐老师的b站深度学习课程 课程链接,使用了线性回归模型,特别适合深度学习初学者。通过阅读本文,你将学会如何用PyTorch训练模型,并掌握一些实用的训练技巧。希望这些内容能对你的深度学习学习有所帮助。

安装pytorch

在命令行输入下面这段指令

pip install pytorch torchvision -i https://pypi.tuna.tsinghua.edu.cn/simple

导入数据集

数据集来自kaggle一个比赛(比赛链接),可以通过链接自己下载数据集:

训练数据集 http://d2l-data.s3-accelerate.amazonaws.com/kaggle_house_pred_train.csv

测试数据集 http://d2l-data.s3-accelerate.amazonaws.com/kaggle_house_pred_test.csv

也可以通过一下这段代码下载

                                                                                    
import hashlib                                                                      
import os                                                                           
import tarfile                                                                      
import zipfile                                                                      
import requests                                                                     #@save                                                                              
DATA_HUB = dict()                                                                   
DATA_URL = 'http://d2l-data.s3-accelerate.amazonaws.com/'                           
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:                                                        break                                                           sha1.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 fname                                                                    
def 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_dir                   def download_all():  #@save                                                         """下载DATA_HUB中的所有文件"""                                                          for name in DATA_HUB:                                                           download(name)                                                              

通过pandas处理数据

import numpy as np # linear algebra                                             
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)          train_data = pd.read_csv('/kaggle/input/kaggle_house_pred_train.csv')     
test_data = pd.read_csv('/kaggle/input/kaggle_house_pred_test.csv')       

train_data是训练集包含47439条数据,40个feature,还有一个是房价(label) 测试集只有也是47439条,40个feature。 

 在开始建模之前,我们需要对数据进行预处理。 首先,我们将所有缺失的值替换为相应特征的平均值。然后,为了将所有特征放在一个共同的尺度上, 我们通过将特征重新缩放到零均值和单位方差来标准化数据:

中μ和σ分别表示均值和标准差。 现在,这些特征具有零均值和单位方差,即  

直观地说,我们标准化数据有两个原因: 首先,它方便优化。 其次,因为我们不知道哪些特征是相关的, 所以我们不想让惩罚分配给一个特征的系数比分配给其他任何特征的系数更大。 

将缺失值替换为0,因为已经在上一步中进行了标准化,0在这个上下文中相当于均值


# train_data.loc[:, train_data.columns != 'Sold Price'] # 这行代码用于提取除'Sold Price'外的其他列
# 合并训练数据和测试数据,排除“Sold Price”列,因为这是我们预测的目标变量
all_features = pd.concat((train_data.loc[:, train_data.columns != 'Sold Price'], test_data.iloc[:, 1:]))# 查看合并后的数据信息,以了解数据的整体情况
all_features.info()# 将所有缺失的值替换为相应特征的平均值。通过将特征重新缩放到零均值和单位方差来标准化数据
# 首先,确定哪些特征是数值型的,因为我们将对这些特征进行标准化
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)all_features = all_features[numeric_features[1:]] # 原本第一列是Id,去掉
all_features.info()
<class 'pandas.core.frame.DataFrame'>
Index: 79065 entries, 0 to 31625
Data columns (total 18 columns):#   Column                       Non-Null Count  Dtype  
---  ------                       --------------  -----  0   Year built                   79065 non-null  float641   Lot                          79065 non-null  float642   Bathrooms                    79065 non-null  float643   Full bathrooms               79065 non-null  float644   Total interior livable area  79065 non-null  float645   Total spaces                 79065 non-null  float646   Garage spaces                79065 non-null  float647   Elementary School Score      79065 non-null  float648   Elementary School Distance   79065 non-null  float649   Middle School Score          79065 non-null  float6410  Middle School Distance       79065 non-null  float6411  High School Score            79065 non-null  float6412  High School Distance         79065 non-null  float6413  Tax assessed value           79065 non-null  float6414  Annual tax amount            79065 non-null  float6415  Listed Price                 79065 non-null  float6416  Last Sold Price              79065 non-null  float6417  Zip                          79065 non-null  float64
dtypes: float64(18)
memory usage: 11.5 MB

将numpy 转换成tensor


# 从pandas格式中提取NumPy格式,并将其转换为张量表示
n_train = train_data.shape[0]#shape获取行、列数,只取行数————获取训练集行数
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['Sold Price'].values.reshape(-1, 1),dtype=torch.float32)

 设计模型


from torch import nn
from torch.utils.data import dataset, DataLoader, TensorDataset
from torch import optim
# 定义一个继承自nn.Module的模型类
class model(nn.Module):def __init__(self, in_features):super(model, self).__init__()### 定义模型 [b,40] ==> [b,1]self.net = nn.Sequential(nn.Linear(in_features, 1))def forward(self, x):##只有一层所以不需要激活函数return self.net(x)

获取数据集,实例化模型


# 将训练数据和标签封装为数据集
train_datasets = TensorDataset(train_features, train_labels)
# 创建数据加载器,用于迭代加载数据集中的数据
train_data = DataLoader(train_datasets, batch_size=64, shuffle=True)
# 同样的操作应用于测试数据
test_datasets = TensorDataset(test_features)
test_data = DataLoader(test_datasets, batch_size=64, shuffle=True)# 获取输入特征的数量
in_features = train_features.shape[1]
# 实例化模型
model = model(in_features)
# 定义均方误差损失函数
loss = nn.MSELoss()
# 定义优化器,使用Adam算法
optimizer = optim.Adam(model.parameters(), lr=0.001, weight_decay=0.01)
# 再次获取输入特征的数量,用于下面的函数
in_features = train_features.shape[1]

 定义相关函数

1. 定义获取K折交叉验证数据的函数:它有助于模型选择和超参数调整。 我们首先需要定义一个函数,在K折交叉验证过程中返回第i折的数据(将一个数据集分成k折,k-1折作为训练级 ,1折作为验证集)。 具体地说,它选择第i个切片作为验证数据,其余部分作为训练数据。 注意,这并不是处理数据的最有效方法,如果我们的数据集大得多,会有其他解决办法。

# 定义获取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_valid

2.房价就像股票价格一样,我们关心的是相对数量,而不是绝对数量。 因此,我们更关心相对误差y - \hat{y} / y\hat{}, 而不是绝对误差|y - y\hat{}|。 例如,如果我们在估计一栋房子的价格时, 假设我们的预测偏差了10万美元, 然而那里一栋典型的房子的价值是12.5万美元, 那么模型可能做得很糟糕。 另一方面,如果我们在加州豪宅区的预测出现同样的10万美元的偏差, (在那里,房价中位数超过400万美元) 这可能是一个不错的预测。

解决这个问题的一种方法是用价格预测的对数来衡量差异。 事实上,这也是比赛中官方用来评价提交质量的误差指标。 即将δ for |log⁡y−log⁡y^|≤δ 转换为e−δ≤y^y≤eδ。 这使得预测价格的对数与真实标签价格的对数之间出现以下均方根误差:

# 定义对数均方根误差函数
def log_rmse(preds, labels):clipped_preds = torch.clamp(preds, 1, float('inf'))rmse = torch.sqrt(loss(torch.log(clipped_preds), torch.log(labels)))return rmse.item()

训练模型


# 训练模型
for epochs in range(10):for batch_id, (x, y) in enumerate(train_data):# 获取K折交叉验证数据x_train, y_train, x_test, y_test = get_k_fold_data(5, 0, x, y)# 前向传播得到预测值pred = model(x_train)# 对预测值进行裁剪,确保其值在1到正无穷之间clipped_preds = torch.clamp(pred, 1, float('inf'))# 计算损失l = loss(torch.log(clipped_preds), torch.log(y_train))# 清零梯度optimizer.zero_grad()# 反向传播l.backward()# 更新参数optimizer.step()# 在测试数据上进行预测pred = model(x_test)# 打印当前批次的训练情况print(f'epoch {epochs + 1}, batch {batch_id}, valid log rmse {log_rmse(pred,y_test):f}')# 在测试集上进行最终预测
pred = model(test_features)

结语

非常感谢您的阅读!我衷心希望这篇关于使用PyTorch进行线性回归模型训练的博客文章能够对您有所帮助。


http://www.ppmy.cn/server/101084.html

相关文章

【Spark集群部署系列一】Spark local模式介绍和搭建以及使用(内含Linux安装Anaconda)

简介 注意&#xff1a; 在部署spark集群前&#xff0c;请部署好Hadoop集群&#xff0c;jdk8【当然Hadoop集群需要运行在jdk上】&#xff0c;需要注意hadoop&#xff0c;spark的版本&#xff0c;考虑兼容问题。比如hadoop3.0以上的才兼容spark3.0以上的。 下面是Hadoop集群部署…

MySQL 查询分组内最新的第一条数据

目录 1、MySQL 5版本的写法 2、MySQL 8版本的写法 由于MySQL 5不支持窗口函数&#xff0c;因此不能使用PARTITION()、ROW_NUMBER() &#x1f330;&#xff1a;获取每个班级中最新注册的学号人员信息 也就是从 user_info 学生表中获取每个 class_id 班级的最新一条记录 1、…

土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测

土地利用/土地覆盖数据是生态、环境和气象等领域众多模型的重要输入参数之一。基于遥感影像解译&#xff0c;可获取历史或当前任何一个区域的土地利用/土地覆盖数据&#xff0c;用于评估区域的生态环境变化、评价重大生态工程建设成效等。借助CLUE模型&#xff0c;实现对未来土…

虚拟人实时主持创意互动方案:赋能峰会论坛会议等活动科技互动感

随着增强现实、虚拟现实等技术的不断发展&#xff0c;“虚拟人实时主持”创意互动模式逐渐代替传统单一真人主持模式&#xff0c;虚拟主持人可以随时随地出现在不同活动现场&#xff0c;也可以同一时间在不同分会场中担任主持工作&#xff0c;在峰会、论坛、会议、晚会、发布会…

关于xilinx的FFTIP的使用和仿真

工具&#xff1a;vivado2018.3&#xff0c;modelsim10.6d 场景&#xff1a;在进行数据进行频谱分析的时候&#xff0c;使用FPGA来完成FFT的计算可以加快数据的计算速度。 下面使用仿真完成DDS产生的数据的FFT以及IFFT。原始数据使用DDSIP产生&#xff0c;通过IP产生的波形数据…

One-hot编码

One-hot编码是一种将分类变量&#xff08;如类别或标签&#xff09;转换为数值表示的方法。在机器学习和数据处理中&#xff0c;分类变量通常需要被转换为数值形式&#xff0c;以便可以输入到算法中进行训练或预测。 One-hot编码通过创建一个二进制的列向量来表示每一个可能的类…

【数据结构与算法】分治法

分治法目录 一.分治法的思想二.分治法的步骤三.举个例子四.具体实现五.完整代码 一.分治法的思想 将一个大问题,拆解成为若干个小问题,而且大问题与小问题的解决方法一样. 说到这里我们可以联想到递归,没错就是用递归的思想. 分:递归解决较小的问题 治:子问题的解构建原问题的…

等保测评与信息安全技术发展趋势:构建未来信息安全的坚实基石

随着信息技术的飞速发展&#xff0c;信息安全已成为保障社会稳定与经济发展的关键因素。等保测评作为我国信息安全等级保护制度的核心内容&#xff0c;不仅反映了当前信息安全技术的发展水平&#xff0c;也预示了未来信息安全技术的发展趋势。本文将探讨等保测评与信息安全技术…