当前位置:   article > 正文

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

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

本文参考了李沐老师的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

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

  1. import hashlib
  2. import os
  3. import tarfile
  4. import zipfile
  5. import requests
  6. #@save
  7. DATA_HUB = dict()
  8. DATA_URL = 'http://d2l-data.s3-accelerate.amazonaws.com/'
  9. def download(name, cache_dir=os.path.join('..', 'data')): #@save
  10. """下载一个DATA_HUB中的文件,返回本地文件名"""
  11. assert name in DATA_HUB, f"{name} 不存在于 {DATA_HUB}"
  12. url, sha1_hash = DATA_HUB[name]
  13. os.makedirs(cache_dir, exist_ok=True)
  14. fname = os.path.join(cache_dir, url.split('/')[-1])
  15. if os.path.exists(fname):
  16. sha1 = hashlib.sha1()
  17. with open(fname, 'rb') as f:
  18. while True:
  19. data = f.read(1048576)
  20. if not data:
  21. break
  22. sha1.update(data)
  23. if sha1.hexdigest() == sha1_hash:
  24. return fname # 命中缓存
  25. print(f'正在从{url}下载{fname}...')
  26. r = requests.get(url, stream=True, verify=True)
  27. with open(fname, 'wb') as f:
  28. f.write(r.content)
  29. return fname
  30. def download_extract(name, folder=None): #@save
  31. """下载并解压zip/tar文件"""
  32. fname = download(name)
  33. base_dir = os.path.dirname(fname)
  34. data_dir, ext = os.path.splitext(fname)
  35. if ext == '.zip':
  36. fp = zipfile.ZipFile(fname, 'r')
  37. elif ext in ('.tar', '.gz'):
  38. fp = tarfile.open(fname, 'r')
  39. else:
  40. assert False, '只有zip/tar文件可以被解压缩'
  41. fp.extractall(base_dir)
  42. return os.path.join(base_dir, folder) if folder else data_dir
  43. def download_all(): #@save
  44. """下载DATA_HUB中的所有文件"""
  45. for name in DATA_HUB:
  46. download(name)

通过pandas处理数据

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

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

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

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

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

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

  1. # train_data.loc[:, train_data.columns != 'Sold Price'] # 这行代码用于提取除'Sold Price'外的其他列
  2. # 合并训练数据和测试数据,排除“Sold Price”列,因为这是我们预测的目标变量
  3. all_features = pd.concat((train_data.loc[:, train_data.columns != 'Sold Price'], test_data.iloc[:, 1:]))
  4. # 查看合并后的数据信息,以了解数据的整体情况
  5. all_features.info()
  6. # 将所有缺失的值替换为相应特征的平均值。通过将特征重新缩放到零均值和单位方差来标准化数据
  7. # 首先,确定哪些特征是数值型的,因为我们将对这些特征进行标准化
  8. numeric_features = all_features.dtypes[all_features.dtypes != 'object'].index
  9. # 对数值型特征进行标准化处理:减去均值并除以标准差
  10. all_features[numeric_features] = all_features[numeric_features].apply(
  11. lambda x: (x - x.mean()) / (x.std()))
  12. # 将缺失值替换为0,因为已经在上一步中进行了标准化,0在这个上下文中相当于均值
  13. all_features[numeric_features] = all_features[numeric_features].fillna(0)
  14. all_features = all_features[numeric_features[1:]] # 原本第一列是Id,去掉
  15. all_features.info()
  1. <class 'pandas.core.frame.DataFrame'>
  2. Index: 79065 entries, 0 to 31625
  3. Data columns (total 18 columns):
  4. # Column Non-Null Count Dtype
  5. --- ------ -------------- -----
  6. 0 Year built 79065 non-null float64
  7. 1 Lot 79065 non-null float64
  8. 2 Bathrooms 79065 non-null float64
  9. 3 Full bathrooms 79065 non-null float64
  10. 4 Total interior livable area 79065 non-null float64
  11. 5 Total spaces 79065 non-null float64
  12. 6 Garage spaces 79065 non-null float64
  13. 7 Elementary School Score 79065 non-null float64
  14. 8 Elementary School Distance 79065 non-null float64
  15. 9 Middle School Score 79065 non-null float64
  16. 10 Middle School Distance 79065 non-null float64
  17. 11 High School Score 79065 non-null float64
  18. 12 High School Distance 79065 non-null float64
  19. 13 Tax assessed value 79065 non-null float64
  20. 14 Annual tax amount 79065 non-null float64
  21. 15 Listed Price 79065 non-null float64
  22. 16 Last Sold Price 79065 non-null float64
  23. 17 Zip 79065 non-null float64
  24. dtypes: float64(18)
  25. memory usage: 11.5 MB

将numpy 转换成tensor

  1. # 从pandas格式中提取NumPy格式,并将其转换为张量表示
  2. n_train = train_data.shape[0]#shape获取行、列数,只取行数————获取训练集行数
  3. train_features = torch.tensor(all_features[:n_train].values,
  4. dtype=torch.float32)
  5. test_features = torch.tensor(all_features[n_train:].values,
  6. dtype=torch.float32)
  7. train_labels = torch.tensor(train_data['Sold Price'].values.reshape(-1, 1),
  8. dtype=torch.float32)

 设计模型

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

获取数据集,实例化模型

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

 定义相关函数

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

  1. # 定义获取K折交叉验证数据的函数
  2. def get_k_fold_data(k, i, X, y):
  3. assert k > 1
  4. fold_size = X.shape[0] // k
  5. X_train, y_train = None, None
  6. for j in range(k):
  7. idx = slice(j * fold_size, (j + 1) * fold_size)
  8. X_part, y_part = X[idx, :], y[idx]
  9. if j == i:
  10. X_valid, y_valid = X_part, y_part
  11. elif X_train is None:
  12. X_train, y_train = X_part, y_part
  13. else:
  14. X_train = torch.cat([X_train, X_part], 0)
  15. y_train = torch.cat([y_train, y_part], 0)
  16. 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δ。 这使得预测价格的对数与真实标签价格的对数之间出现以下均方根误差:

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

训练模型

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

结语

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

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号