深度学习--------------Kaggle房价预测
目录
- 下载和缓存数据集
- 访问和读取数据集
- 总代码
- 数据预处理
- 训练
- K折交叉验证
- 模型选择
- 总代码
- 提交你的Kaggle预测
- 提交Kaggle
下载和缓存数据集
import hashlib
import os
import tarfile
import zipfile
import requests# download传递的参数分别是数据集的名称、缓存文件夹的路径
def download(name, cache_dir=os.path.join('..', 'data')): # @save"""下载一个DATA_HUB中的文件,返回本地文件名"""# 检查变量name是否存在于名为DATA_HUB的字典中,如果是异常则给出消息提示assert name in DATA_HUB, f"{name} 不存在于 {DATA_HUB}"# 检查与name相对应的元组并解包赋值给url和sha1_hashurl, sha1_hash = DATA_HUB[name]os.makedirs(cache_dir, exist_ok=True)# 缓存的路径和目标目录,[-1]:url指向文件名fname = os.path.join(cache_dir, url.split('/')[-1])if os.path.exists(fname): # 检查文件是否存在sha1 = hashlib.sha1() # 计算文件的哈希值,初始化哈希对象# with确保文件在使用后正确关闭with open(fname, 'rb') as f: # 读取文件内容while True: # 循环读取文件内容并更新哈希对象data = f.read(1048576) # 读取1MB到dataif not data: # 为真跳出break# 将读取到的数据块更新到哈希对象中sha1.update(data)# 检查计算出的哈希值是否与预期的哈希值匹配if sha1.hexdigest() == sha1_hash:return fname # 命中缓存print(f'正在从{url}下载{fname}...')# 发送get请求并设置stream=True支持流式传输r = requests.get(url, stream=True, verify=True)with open(fname, 'wb') as f: # 写入模式f.write(r.content)return fname# folder=None是指解压后数据应存放的文件名,如未指定则默认使用去除扩展名后的文件名作为文件夹名
def download_extract(name, folder=None): # @save"""下载并解压zip/tar文件"""# 下载文件,并返回下载的完整路径fnamefname = download(name)# 获取下载文件所在的基本目录base_dir = os.path.dirname(fname)# 从文件名中分离出扩展名exe和数据目录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文件可以被解压缩'# 使用extractall方法将文件解压到基本目录,如果指定了folder参数,则返回base_dir和folder组合的路径# 否则返回去除扩展名后的文件名作为路径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)# @save
DATA_HUB = dict() # 这是一个字典,用来存储数据集的信息。
DATA_URL = 'http://d2l-data.s3-accelerate.amazonaws.com/' # 指向一个存储了多个数据集文件的服务器
访问和读取数据集
import numpy as np
import pandas as pd
import torch
from torch import nn
from d2l import torch as d2l
下载并缓存Kaggle房屋数据集
DATA_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')
使用pandas分别加载包含训练数据和测试数据的两个CSV文件
train_data = pd.read_csv(download('kaggle_house_train'))
test_data = pd.read_csv(download('kaggle_house_test'))
输出:

训练数据集包括1460个样本,每个样本80个特征和1个标签, 而测试数据集包含1459个样本,每个样本80个特征。
print(train_data.shape)
print(test_data.shape)
输出:

查看前四个和最后两个特征,以及相应标签(房价)。
print(train_data.iloc[0:4, [0, 1, 2, 3, -3, -2, -1]])
输出:

在每个样本中,第一个特征是ID, 这有助于模型识别每个训练样本。 虽然这很方便,但它不携带任何用于预测的信息。 因此,在将数据提供给模型之前,(我们将其从数据集中删除)。
# 删除train_data的第一列ID和最后一列房价;删除test_data的第一列索引
all_features = pd.concat((train_data.iloc[:, 1:-1], test_data.iloc[:, 1:]))
# 查看一下
print(all_features)
输出:

总代码
import hashlib
import os
import tarfile
import zipfile
import requests
import pandas as pd# download传递的参数分别是数据集的名称、缓存文件夹的路径
def download(name, cache_dir=os.path.join('..', 'data')): # @save"""下载一个DATA_HUB中的文件,返回本地文件名"""# 检查变量name是否存在于名为DATA_HUB的字典中,如果是异常则给出消息提示assert name in DATA_HUB, f"{name} 不存在于 {DATA_HUB}"# 检查与name相对应的元组并解包赋值给url和sha1_hashurl, sha1_hash = DATA_HUB[name]os.makedirs(cache_dir, exist_ok=True)# 缓存的路径和目标目录,[-1]:url指向文件名fname = os.path.join(cache_dir, url.split('/')[-1])if os.path.exists(fname): # 检查文件是否存在sha1 = hashlib.sha1() # 计算文件的哈希值,初始化哈希对象# with确保文件在使用后正确关闭with open(fname, 'rb') as f: # 读取文件内容while True: # 循环读取文件内容并更新哈希对象data = f.read(1048576) # 读取1MB到dataif not data: # 为真跳出break# 将读取到的数据块更新到哈希对象中sha1.update(data)# 检查计算出的哈希值是否与预期的哈希值匹配if sha1.hexdigest() == sha1_hash:return fname # 命中缓存print(f'正在从{url}下载{fname}...')# 发送get请求并设置stream=True支持流式传输r = requests.get(url, stream=True, verify=True)with open(fname, 'wb') as f: # 写入模式f.write(r.content)return fname# folder=None是指解压后数据应存放的文件名,如未指定则默认使用去除扩展名后的文件名作为文件夹名
def download_extract(name, folder=None): # @save"""下载并解压zip/tar文件"""# 下载文件,并返回下载的完整路径fnamefname = download(name)# 获取下载文件所在的基本目录base_dir = os.path.dirname(fname)# 从文件名中分离出扩展名exe和数据目录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文件可以被解压缩'# 使用extractall方法将文件解压到基本目录,如果指定了folder参数,则返回base_dir和folder组合的路径# 否则返回去除扩展名后的文件名作为路径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)# @save
DATA_HUB = dict() # 这是一个字典,用来存储数据集的信息。
DATA_URL = 'http://d2l-data.s3-accelerate.amazonaws.com/' # 指向一个存储了多个数据集文件的服务器
# 第二个参数:表示数据集文件的哈希值,用哈希值验证文件的完整性
DATA_HUB['kaggle_house_train'] = (DATA_URL + 'kaggle_house_pred_train.csv','585e9cc9370b9160e7921475fbcd7d31219ce')
DATA_HUB['kaggle_house_test'] = (DATA_URL + 'kaggle_house_pred_test.csv', 'fal9780a7b011d9b009e8bff8e99922a8ee2eb90')
# 读取路径指向的csv文件
train_data = pd.read_csv(download('kaggle_house_train'))
test_data = pd.read_csv(download('kaggle_house_test'))print(train_data.shape) # 1460个样本,80个特征,1个标号label
print(test_data.shape) # 测试样本没有标号label
print(train_data.iloc[0:4,[0,1,2,3,-3,-2,-1]]) # 前面四行的某些列特征
输出:

数据预处理
如上所述,我们有各种各样的数据类型。 在开始建模之前,我们需要对数据进行预处理。 首先,我们将所有缺失的值替换为相应特征的平均值。然后,为了将所有特征放在一个共同的尺度上, 我们通过将特征重新缩放到零均值和单位方差来标准化数据:
其中 𝜇 和 𝜎 分别表示均值和标准差。 现在,这些特征具有零均值和单位方差,即
和
直观地说,我们标准化数据有两个原因: 首先,它方便优化。 其次,因为我们不知道哪些特征是相关的, 所以我们不想让惩罚分配给一个特征的系数比分配给其他任何特征的系数更大。
# 若无法获得测试数据,则可根据训练数据计算均值和标准差
# all_features.dtypes 获取每个特征的数据类型
# all_features.dtypes != 'object' 返回一个布尔值的 Series,其中为 True 的位置表示对应的特征不是对象类型(即数值类型)
# .index 提取数值类型特征的索引,并在numeric_features中存储
print(all_features.dtypes) # 可以知道每一列分别为什么类型特征
numeric_features = all_features.dtypes[all_features.dtypes != 'object'].index
print(numeric_features)
# 对all_features中所有数值类型特征进行标准化处理
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)
输出:

接下来,我们处理离散值。 这包括诸如“MSZoning”之类的特征。我们用独热编码替换它们), 例如,“MSZoning”包含值“RL”和“Rm”。 我们将创建两个新的指示器特征“MSZoning_RL”和“MSZoning_RM”,其值为0或1。 根据独热编码,如果“MSZoning”的原始值为“RL”, 则:“MSZoning_RL”为1,“MSZoning_RM”为0。 pandas软件包会自动为我们实现这一点。
# “Dummy_na=True”将“na”(缺失值)视为有效的特征值,并为其创建指示符特征
# 未指定column时,pd.get_dummies函数默认转换所有的分类列,包括MSZoning、SaleType、SaleCondition
# pd.get_dummies每个分类变量都会被转换成多列,每个唯一值对应一列
# 理解意思:某列有五类值,就将此列等价于变成五列,然后对应的列置1,不存在的列置0
all_features = pd.get_dummies(all_features, dummy_na=True)
未改变时的数据特征:
# 这里仅验证看一下特征的形状
print(all_features.shape)
输出:

改变后:
all_features = pd.get_dummies(all_features, dummy_na=True)
print(all_features.shape)
输出:

可以看到此转换会将特征的总数量从79个(去掉ID)增加到331个。
最后,通过values属性,我们可以从pandas格式中提取NumPy格式,并将其转换为张量表示用于训练。
# 获取训练集的行数,即训练样本数量,并将其存储在n_train中
n_train = train_data.shape[0]
# [:n_train].values是选择前n_train作为训练集的特征将数据转换为Numpy数组
train_features = torch.tensor(all_features[:n_train].values, dtype=torch.float32)
test_features = torch.tensor(all_features[n_train:].values, dtype=torch.float32)
# 将SalePrice列单独提取为标签
train_labels = torch.tensor(train_data.SalePrice.values.reshape(-1, 1), dtype=torch.float32)
训练
首先,我们训练一个带有损失平方的线性模型。 显然线性模型很难让我们在竞赛中获胜,但线性模型提供了一种健全性检查,以查看数据中是否存在有意义的信息。 如果我们在这里不能做得比随机猜测更好,那么我们很可能存在数据处理错误。 如果一切顺利,线性模型将作为基线(baseline)模型, 让我们直观地知道最好的模型有超出简单的模型多少。
loss = nn.MSELoss()
in_features = train_features.shape[1]def get_net():net = nn.Sequential(nn.Linear(in_features,1))return net
房价就像股票价格一样,我们关心的是相对数量,而不是绝对数量。因此,我们更关心相对误差,而不是绝对误差 。 例如,如果我们在俄亥俄州农村地区估计一栋房子的价格时,假设我们的预测偏差了10万美元,然而那里一栋典型的房子的价值是12.5万美元,那么模型可能做得很糟糕。另一方面,如果我们在加州豪宅区的预测出现同样的10万美元的偏差,(在那里,房价中位数超过400万美元) 这可能是一个不错的预测。
(解决这个问题的一种方法是用价格预测的对数来衡量差异)。 事实上,这也是比赛中官方用来评价提交质量的误差指标。 即将
转换为
。 这使得预测价格的对数与真实标签价格的对数之间出现以下均方根误差:

# rmse=Root Mean Squared Error,对数均方根误差
def log_rmse(net, features, labels):# 通过神经网络net对输入特征features进行前向传播得到预测值# 然后为了在取对数时进一步稳定该值,用torch.clamp()函数将小于1的值设置为1# 第三个参数:不设置上限,即预测可以无限大clipped_preds = torch.clamp(net(features), 1, float('inf'))rmse = torch.sqrt(loss(torch.log(clipped_preds),torch.log(labels)))# .item() 方法将rmse转换为Python标量返回return rmse.item()
我们的训练函数将借助Adam优化器,Adam优化器的主要吸引力在于它对初始学习率不那么敏感。
# weight_decay权重衰退
def train(net, train_features, train_labels, test_features, test_labels,num_epochs, learning_rate, weight_decay, batch_size):# 用于存储每一轮训练和测试集上的log rmse值train_ls, test_ls = [], []train_iter = d2l.load_array((train_features, train_labels), batch_size)# 这里使用的是Adam优化算法,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() # 更新模型参数# 将log_rmse函数返回的误差值追加到train_ls列表中就记录了每一轮迭代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
K折交叉验证
K折交叉验证有助于模型选择和超参数调整。定义一个函数,在 𝐾 折交叉验证过程中返回第 𝑖 折的数据。具体地说,它选择第 𝑖 个切片作为验证数据,其余部分作为训练数据。注意,这并不是处理数据的最有效方法,如果我们的数据集大得多,会有其他解决办法。
# 四个参数:表示将数据集分为多少个子集、当前折的索引、特征数据集、标签数据集
def get_k_fold_data(k, i, X, y):# 断言确保折数大于1,因为至少两个子集才能进行交叉验证assert k > 1# 每个子集(折)的大小=数据集的总行数除以折数,余数在最后一个子集处理fold_size = X.shape[0] // k# 初始化训练集X_train, y_train = None, Nonefor j in range(k):# idx将原始数据集的索引切片为 (j * fold_size) 到 ((j + 1) * fold_size),获得当前折数据idx = slice(j * fold_size, (j + 1) * fold_size)X_part, y_part = X[idx, :], y[idx]# 当前折的索引 j 与指定用于验证的索引 i 匹配,将该折的数据分配给验证集(X_valid 和 y_valid)if j == i:# 将该折的数据分配给验证集X_valid, y_valid = X_part, y_part# 如不匹配且训练集为空(第一次看到),则将该折的数据分配给训练集(X_train 和 y_train)elif X_train is None:X_train, y_train = X_part, y_part# 如不匹配且训练集不为空,则将该折的数据追加到训练集(X_train 和 y_train)中else:# 表示将X_train, X_part沿着第一个维度拼接起来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
在𝐾折交叉验证中训练𝐾次后,返回训练和验证误差的平均值。
def 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):# 做k次,每次拿到第i折,把数据data拿出来即拿到从训练集和验证集data = get_k_fold_data(k, i, X_train, y_train)# 每次循环都会创建一个新的模型实例,确保每折的评估是独立的net = get_net()# 调用train函数训练模型并返回训练损失列表和验证损失列表train_ls, valid_ls = train(net, *data, num_epochs, learning_rate,weight_decay, batch_size)# 索引[-1]获取最后一个epoch的损失,即当前折的训练损失累加到train_l_sum train_l_sum += train_ls[-1]valid_l_sum += valid_ls[-1]if i == 0: # 如果当前是第i折# 第一个参数:用作x轴数据# 第二个参数:一个列表储存了每一轮训练后的训练损失和验证损失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份,然后执行5次训练和验证过程,每次过程中,4份数据用于训练模型,剩下的一份用于
k, num_epochs, lr, weight_decay, batch_size = 5, 100, 5, 0, 64
# 分别包含每次迭代的训练集和验证集的log rmse值
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}')
我们关心的是平均验证log rmse
总代码
import hashlib
import os
import tarfile
import zipfile
import requests
import pandas as pd
import torch
from torch import nn
from d2l import torch as d2ldef 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)def get_net():net = nn.Sequential(nn.Linear(in_features, 1))return net# rmse=Root Mean Squared Error,对数均方根误差
def log_rmse(net, features, labels):# 通过神经网络net对输入特征features进行前向传播得到预测值# 然后为了在取对数时进一步稳定该值,用torch.clamp()函数将小于1的值设置为1# 第三个参数:不设置上限,即预测可以无限大clipped_preds = torch.clamp(net(features), 1, float('inf'))rmse = torch.sqrt(loss(torch.log(clipped_preds),torch.log(labels)))# .item() 方法将rmse转换为Python标量返回return rmse.item()# weight_decay权重衰退
def train(net, train_features, train_labels, test_features, test_labels,num_epochs, learning_rate, weight_decay, batch_size):# 用于存储每一轮训练和测试集上的log rmse值train_ls, test_ls = [], []train_iter = d2l.load_array((train_features, train_labels), batch_size)# 这里使用的是Adam优化算法,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() # 更新模型参数# 将log_rmse函数返回的误差值追加到train_ls列表中就记录了每一轮迭代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# 四个参数:表示将数据集分为多少个子集、当前折的索引、特征数据集、标签数据集
def get_k_fold_data(k, i, X, y):# 断言确保折数大于1,因为至少两个子集才能进行交叉验证assert k > 1# 每个子集(折)的大小=数据集的总行数除以折数,余数在最后一个子集处理fold_size = X.shape[0] // k# 初始化训练集X_train, y_train = None, Nonefor j in range(k):# idx将原始数据集的索引切片为 (j * fold_size) 到 ((j + 1) * fold_size),获得当前折数据idx = slice(j * fold_size, (j + 1) * fold_size)X_part, y_part = X[idx, :], y[idx]# 当前折的索引 j 与指定用于验证的索引 i 匹配,将该折的数据分配给验证集(X_valid 和 y_valid)if j == i:# 将该折的数据分配给验证集X_valid, y_valid = X_part, y_part# 如不匹配且训练集为空(第一次看到),则将该折的数据分配给训练集(X_train 和 y_train)elif X_train is None:X_train, y_train = X_part, y_part# 如不匹配且训练集不为空,则将该折的数据追加到训练集(X_train 和 y_train)中else:# 表示将X_train, X_part沿着第一个维度拼接起来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):# 做k次,每次拿到第i折,把数据data拿出来即拿到从训练集和验证集data = get_k_fold_data(k, i, X_train, y_train)# 每次循环都会创建一个新的模型实例,确保每折的评估是独立的net = get_net()# 调用train函数训练模型并返回训练损失列表和验证损失列表train_ls, valid_ls = train(net, *data, num_epochs, learning_rate,weight_decay, batch_size)# 索引[-1]获取最后一个epoch的损失,即当前折的训练损失累加到train_l_sumtrain_l_sum += train_ls[-1]valid_l_sum += valid_ls[-1]if i == 0: # 如果当前是第i折# 第一个参数:用作x轴数据# 第二个参数:一个列表储存了每一轮训练后的训练损失和验证损失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# @save
DATA_HUB = dict()
DATA_URL = 'http://d2l-data.s3-accelerate.amazonaws.com/'
DATA_HUB['kaggle_house_train'] = (DATA_URL + 'kaggle_house_pred_train.csv', '585e9cc9370b9160e7921475fbcd7d31219ce')
DATA_HUB['kaggle_house_test'] = (DATA_URL + 'kaggle_house_pred_test.csv', 'fal9780a7b011d9b009e8bff8e99922a8ee2eb90')
train_data = pd.read_csv(download('kaggle_house_train'))
test_data = pd.read_csv(download('kaggle_house_test'))# print(train_data.shape) # 1460个样本,80个特征,1个标号label
# print(test_data.shape) # 测试样本没有标号label
# print(train_data.iloc[0:4,[0,1,2,3,-3,-2,-1]]) # 前面四行的某些列特征
all_features = pd.concat((train_data.iloc[:, 1:-1], test_data.iloc[:, 1:]))
# print(all_features.shape)# 若无法获得测试数据,则可根据训练数据计算均值和标准差
# all_features.dtypes 获取每个特征的数据类型
# all_features.dtypes != 'object' 返回一个布尔值的 Series,其中为 True 的位置表示对应的特征不是对象类型(即数值类型)
# .index 提取数值类型特征的索引,并在numeric_features中存储
# print(all_features.dtypes) # 可以知道每一列分别为什么类型特征
numeric_features = all_features.dtypes[all_features.dtypes != 'object'].index
# print(numeric_features)
# 对all_features中所有数值类型特征进行标准化处理
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)# “Dummy_na=True”将“na”(缺失值)视为有效的特征值,并为其创建指示符特征
# 未指定column时,pd.get_dummies函数默认转换所有的分类列,包括MSZoning、SaleType、SaleCondition
# pd.get_dummies每个分类变量都会被转换成多列,每个唯一值对应一列
# 理解意思:某列有五类值,就将此列等价于变成五列,然后对应的列置1,不存在的列置0
all_features = pd.get_dummies(all_features, dummy_na=True)# 获取训练集的行数,即训练样本数量,并将其存储在n_train中
n_train = train_data.shape[0]
# [:n_train].values是选择前n_train作为训练集的特征将数据转换为Numpy数组
train_features = torch.tensor(all_features[:n_train].values, dtype=torch.float32)
test_features = torch.tensor(all_features[n_train:].values, dtype=torch.float32)
# 将SalePrice列单独提取为标签
train_labels = torch.tensor(train_data.SalePrice.values.reshape(-1, 1), dtype=torch.float32)
loss = nn.MSELoss()
in_features = train_features.shape[1]# 数据集被分成了5份,然后执行5次训练和验证过程,每次过程中,4份数据用于训练模型,剩下的一份用于
k, num_epochs, lr, weight_decay, batch_size = 5, 100, 5, 0, 64
# 分别包含每次迭代的训练集和验证集的log rmse值
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}')
输出:


提交你的Kaggle预测
既然我们知道应该选择什么样的超参数, 我们不妨使用所有数据对其进行训练 (而不是仅使用交叉验证中使用的 1− 1 K \frac 1K K1 的数据)。 然后,我们通过这种方式获得的模型可以应用于测试集。 将预测保存在CSV文件中可以简化将结果上传到Kaggle的过程。
def train_and_pred(train_features, test_features, train_labels, test_data,num_epochs, lr, weight_decay, batch_size):net = get_net()# 返回两个值,一个包含每个epoch训练,log mose的列表,一个未在代码片段中使用的值train_ls, _ = train(net, train_features, train_labels, None, None,num_epochs, lr, weight_decay, batch_size)# 第一个参数和第二个参数:接收一个epoch数组和一个包含训练log rmse的列表作为输入d2l.plot(np.arange(1, num_epochs + 1), [train_ls], xlabel='epoch',ylabel='log rmse', xlim=[1, num_epochs], yscale='log')# 打印最后一个epoch训练log rmse来评估模型的最终训练性能print(f'训练log rmse:{float(train_ls[-1]):f}')# 将训练好的网络模型应用于测试特征preds = net(test_features).detach().numpy()# 将其重新格式化以导出到Kaggle# pd.Series()封装成一个Pandas的Series对象,以确保数据类型与DataFrame的列兼容。test_data['SalePrice'] = pd.Series(preds.reshape(1, -1)[0])submission = pd.concat([test_data['Id'], test_data['SalePrice']], axis=1)# 用于将DataFrame保存为csv文件submission.to_csv('submission.csv', index=False)
如果测试集上的预测与 𝐾 倍交叉验证过程中的预测相似, 那就是时候把它们上传到Kaggle了。 下面的代码将生成一个名为submission.csv的文件。
train_and_pred(train_features, test_features, train_labels, test_data,num_epochs, lr, weight_decay, batch_size)
输出:


import hashlib
import os
import tarfile
import zipfile
import requests
import numpy as np
import pandas as pd
import torch
from torch import nn
from d2l import torch as d2ldef 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)def get_net():net = nn.Sequential(nn.Linear(in_features, 1))return net# rmse=Root Mean Squared Error,对数均方根误差
def log_rmse(net, features, labels):# 通过神经网络net对输入特征features进行前向传播得到预测值# 然后为了在取对数时进一步稳定该值,用torch.clamp()函数将小于1的值设置为1# 第三个参数:不设置上限,即预测可以无限大clipped_preds = torch.clamp(net(features), 1, float('inf'))rmse = torch.sqrt(loss(torch.log(clipped_preds),torch.log(labels)))# .item() 方法将rmse转换为Python标量返回return rmse.item()# weight_decay权重衰退
def train(net, train_features, train_labels, test_features, test_labels,num_epochs, learning_rate, weight_decay, batch_size):# 用于存储每一轮训练和测试集上的log rmse值train_ls, test_ls = [], []train_iter = d2l.load_array((train_features, train_labels), batch_size)# 这里使用的是Adam优化算法,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() # 更新模型参数# 将log_rmse函数返回的误差值追加到train_ls列表中就记录了每一轮迭代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_lsdef train_and_pred(train_features, test_features, train_labels, test_data,num_epochs, lr, weight_decay, batch_size):net = get_net()# 返回两个值,一个包含每个epoch训练,log mose的列表,一个未在代码片段中使用的值train_ls, _ = train(net, train_features, train_labels, None, None,num_epochs, lr, weight_decay, batch_size)# 第一个参数和第二个参数:接收一个epoch数组和一个包含训练log rmse的列表作为输入d2l.plot(np.arange(1, num_epochs + 1), [train_ls], xlabel='epoch',ylabel='log rmse', xlim=[1, num_epochs], yscale='log')# 打印最后一个epoch训练log rmse来评估模型的最终训练性能print(f'训练log rmse:{float(train_ls[-1]):f}')# 将训练好的网络模型应用于测试特征preds = net(test_features).detach().numpy()# 将其重新格式化以导出到Kaggle# pd.Series()封装成一个Pandas的Series对象,以确保数据类型与DataFrame的列兼容。test_data['SalePrice'] = pd.Series(preds.reshape(1, -1)[0])submission = pd.concat([test_data['Id'], test_data['SalePrice']], axis=1)# 用于将DataFrame保存为csv文件submission.to_csv('submission.csv', index=False)# @save
DATA_HUB = dict()
DATA_URL = 'http://d2l-data.s3-accelerate.amazonaws.com/'
DATA_HUB['kaggle_house_train'] = (DATA_URL + 'kaggle_house_pred_train.csv', '585e9cc9370b9160e7921475fbcd7d31219ce')
DATA_HUB['kaggle_house_test'] = (DATA_URL + 'kaggle_house_pred_test.csv', 'fal9780a7b011d9b009e8bff8e99922a8ee2eb90')
train_data = pd.read_csv(download('kaggle_house_train'))
test_data = pd.read_csv(download('kaggle_house_test'))# print(train_data.shape) # 1460个样本,80个特征,1个标号label
# print(test_data.shape) # 测试样本没有标号label
# print(train_data.iloc[0:4,[0,1,2,3,-3,-2,-1]]) # 前面四行的某些列特征
all_features = pd.concat((train_data.iloc[:, 1:-1], test_data.iloc[:, 1:]))
# print(all_features.shape)# 若无法获得测试数据,则可根据训练数据计算均值和标准差
# all_features.dtypes 获取每个特征的数据类型
# all_features.dtypes != 'object' 返回一个布尔值的 Series,其中为 True 的位置表示对应的特征不是对象类型(即数值类型)
# .index 提取数值类型特征的索引,并在numeric_features中存储
# print(all_features.dtypes) # 可以知道每一列分别为什么类型特征
numeric_features = all_features.dtypes[all_features.dtypes != 'object'].index
# print(numeric_features)
# 对all_features中所有数值类型特征进行标准化处理
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)# “Dummy_na=True”将“na”(缺失值)视为有效的特征值,并为其创建指示符特征
# 未指定column时,pd.get_dummies函数默认转换所有的分类列,包括MSZoning、SaleType、SaleCondition
# pd.get_dummies每个分类变量都会被转换成多列,每个唯一值对应一列
# 理解意思:某列有五类值,就将此列等价于变成五列,然后对应的列置1,不存在的列置0
all_features = pd.get_dummies(all_features, dummy_na=True)# 获取训练集的行数,即训练样本数量,并将其存储在n_train中
n_train = train_data.shape[0]
# [:n_train].values是选择前n_train作为训练集的特征将数据转换为Numpy数组
train_features = torch.tensor(all_features[:n_train].values, dtype=torch.float32)
test_features = torch.tensor(all_features[n_train:].values, dtype=torch.float32)
# 将SalePrice列单独提取为标签
train_labels = torch.tensor(train_data.SalePrice.values.reshape(-1, 1), dtype=torch.float32)
loss = nn.MSELoss()
in_features = train_features.shape[1]num_epochs, lr, weight_decay, batch_size = 100, 5, 0, 64
train_and_pred(train_features, test_features, train_labels, test_data,num_epochs, lr, weight_decay, batch_size)
d2l.plt.show()
提交Kaggle
我们可以提交预测到Kaggle上,并查看在测试集上的预测与实际房价(标签)的比较情况。
①登录Kaggle网站,访问房价预测竞赛页面。
②点击“Submit Predictions”按钮。
③点击页面底部虚线框中的“Upload Submission File”按钮,选择要上传的预测文件。
④点击页面底部的“Submission”按钮,即可查看结果。
Kaggle注册链接
Kaggle登录链接
房价预测比赛页面(如下图 所示)的"Data"选项卡下可以找到数据集。我们可以通过下面的网址提交预测,并查看排名:
House Prices - Advanced Regression Techniques




这里是第一次提交(未优化)

1、用平均值替换缺失值总是好主意吗?提示:能构造一个不随机丢失值的情况吗?
用平均值替换缺失值并不总是一个好主意,因为这可能会导致数据失真或者模型表现下降。替代缺失值的方法应该根据数据的特点和缺失值产生的原因来选择。
比如,一个数据集中的某个属性代表的是某种物质的浓度,这种物质在某个特定温度下会分解,因此在这个温度下所有样本的该属性值都是缺失的。在这种情况下,如果直接用平均值替换缺失值,则可能会导致数据严重失真。
2、通过 𝐾 折交叉验证调整超参数,从而提高Kaggle的得分。
import hashlib
import os
import tarfile
import zipfile
import requests
import numpy as np
import pandas as pd
import torch
from torch import nn
from d2l import torch as d2ldef 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)def get_net():net = nn.Sequential(nn.Linear(in_features, 1))return net# rmse=Root Mean Squared Error,对数均方根误差
def log_rmse(net, features, labels):# 通过神经网络net对输入特征features进行前向传播得到预测值# 然后为了在取对数时进一步稳定该值,用torch.clamp()函数将小于1的值设置为1# 第三个参数:不设置上限,即预测可以无限大clipped_preds = torch.clamp(net(features), 1, float('inf'))rmse = torch.sqrt(loss(torch.log(clipped_preds),torch.log(labels)))# .item() 方法将rmse转换为Python标量返回return rmse.item()# weight_decay权重衰退
def train(net, train_features, train_labels, test_features, test_labels,num_epochs, learning_rate, weight_decay, batch_size):# 用于存储每一轮训练和测试集上的log rmse值train_ls, test_ls = [], []train_iter = d2l.load_array((train_features, train_labels), batch_size)# 这里使用的是Adam优化算法,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() # 更新模型参数# 将log_rmse函数返回的误差值追加到train_ls列表中就记录了每一轮迭代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_lsdef train_and_pred(train_features, test_features, train_labels, test_data,num_epochs, lr, weight_decay, batch_size):net = get_net()# 返回两个值,一个包含每个epoch训练,log mose的列表,一个未在代码片段中使用的值train_ls, _ = train(net, train_features, train_labels, None, None,num_epochs, lr, weight_decay, batch_size)# 第一个参数和第二个参数:接收一个epoch数组和一个包含训练log rmse的列表作为输入d2l.plot(np.arange(1, num_epochs + 1), [train_ls], xlabel='epoch',ylabel='log rmse', xlim=[1, num_epochs], yscale='log')# 打印最后一个epoch训练log rmse来评估模型的最终训练性能print(f'训练log rmse:{float(train_ls[-1]):f}')# 将训练好的网络模型应用于测试特征preds = net(test_features).detach().numpy()# 将其重新格式化以导出到Kaggle# pd.Series()封装成一个Pandas的Series对象,以确保数据类型与DataFrame的列兼容。test_data['SalePrice'] = pd.Series(preds.reshape(1, -1)[0])submission = pd.concat([test_data['Id'], test_data['SalePrice']], axis=1)# 用于将DataFrame保存为csv文件submission.to_csv('submission.csv', index=False)# 四个参数:表示将数据集分为多少个子集、当前折的索引、特征数据集、标签数据集
def get_k_fold_data(k, i, X, y):# 断言确保折数大于1,因为至少两个子集才能进行交叉验证assert k > 1# 每个子集(折)的大小=数据集的总行数除以折数,余数在最后一个子集处理fold_size = X.shape[0] // k# 初始化训练集X_train, y_train = None, Nonefor j in range(k):# idx将原始数据集的索引切片为 (j * fold_size) 到 ((j + 1) * fold_size),获得当前折数据idx = slice(j * fold_size, (j + 1) * fold_size)X_part, y_part = X[idx, :], y[idx]# 当前折的索引 j 与指定用于验证的索引 i 匹配,将该折的数据分配给验证集(X_valid 和 y_valid)if j == i:# 将该折的数据分配给验证集X_valid, y_valid = X_part, y_part# 如不匹配且训练集为空(第一次看到),则将该折的数据分配给训练集(X_train 和 y_train)elif X_train is None:X_train, y_train = X_part, y_part# 如不匹配且训练集不为空,则将该折的数据追加到训练集(X_train 和 y_train)中else:# 表示将X_train, X_part沿着第一个维度拼接起来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):# 做k次,每次拿到第i折,把数据data拿出来即拿到从训练集和验证集data = get_k_fold_data(k, i, X_train, y_train)# 每次循环都会创建一个新的模型实例,确保每折的评估是独立的net = get_net()# 调用train函数训练模型并返回训练损失列表和验证损失列表train_ls, valid_ls = train(net, *data, num_epochs, learning_rate,weight_decay, batch_size)# 索引[-1]获取最后一个epoch的损失,即当前折的训练损失累加到train_l_sumtrain_l_sum += train_ls[-1]valid_l_sum += valid_ls[-1]if i == 0: # 如果当前是第i折# 第一个参数:用作x轴数据# 第二个参数:一个列表储存了每一轮训练后的训练损失和验证损失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# @save
DATA_HUB = dict()
DATA_URL = 'http://d2l-data.s3-accelerate.amazonaws.com/'
DATA_HUB['kaggle_house_train'] = (DATA_URL + 'kaggle_house_pred_train.csv', '585e9cc9370b9160e7921475fbcd7d31219ce')
DATA_HUB['kaggle_house_test'] = (DATA_URL + 'kaggle_house_pred_test.csv', 'fal9780a7b011d9b009e8bff8e99922a8ee2eb90')
train_data = pd.read_csv(download('kaggle_house_train'))
test_data = pd.read_csv(download('kaggle_house_test'))# print(train_data.shape) # 1460个样本,80个特征,1个标号label
# print(test_data.shape) # 测试样本没有标号label
# print(train_data.iloc[0:4,[0,1,2,3,-3,-2,-1]]) # 前面四行的某些列特征
all_features = pd.concat((train_data.iloc[:, 1:-1], test_data.iloc[:, 1:]))
# print(all_features.shape)# 若无法获得测试数据,则可根据训练数据计算均值和标准差
# all_features.dtypes 获取每个特征的数据类型
# all_features.dtypes != 'object' 返回一个布尔值的 Series,其中为 True 的位置表示对应的特征不是对象类型(即数值类型)
# .index 提取数值类型特征的索引,并在numeric_features中存储
# print(all_features.dtypes) # 可以知道每一列分别为什么类型特征
numeric_features = all_features.dtypes[all_features.dtypes != 'object'].index
# print(numeric_features)
# 对all_features中所有数值类型特征进行标准化处理
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)# “Dummy_na=True”将“na”(缺失值)视为有效的特征值,并为其创建指示符特征
# 未指定column时,pd.get_dummies函数默认转换所有的分类列,包括MSZoning、SaleType、SaleCondition
# pd.get_dummies每个分类变量都会被转换成多列,每个唯一值对应一列
# 理解意思:某列有五类值,就将此列等价于变成五列,然后对应的列置1,不存在的列置0
all_features = pd.get_dummies(all_features, dummy_na=True)# 获取训练集的行数,即训练样本数量,并将其存储在n_train中
n_train = train_data.shape[0]
# [:n_train].values是选择前n_train作为训练集的特征将数据转换为Numpy数组
train_features = torch.tensor(all_features[:n_train].values, dtype=torch.float32)
test_features = torch.tensor(all_features[n_train:].values, dtype=torch.float32)
# 将SalePrice列单独提取为标签
train_labels = torch.tensor(train_data.SalePrice.values.reshape(-1, 1), dtype=torch.float32)
loss = nn.MSELoss()
in_features = train_features.shape[1]# 数据集被分成了5份,然后执行5次训练和验证过程,每次过程中,4份数据用于训练模型,剩下的一份用于
k, num_epochs, lr, weight_decay, batch_size = 5, 100, 10, 0, 32
# 分别包含每次迭代的训练集和验证集的log rmse值
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}')
train_and_pred(train_features, test_features, train_labels, test_data,num_epochs, lr, weight_decay, batch_size)
d2l.plt.show()



3、通过改进模型(例如,层、权重衰减和dropout)来提高分数。
import hashlib
import os
import tarfile
import zipfile
import requests
import numpy as np
import pandas as pd
import torch
from torch import nn
from d2l import torch as d2ldef 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)def init_weights(m):if type(m) == nn.Linear:nn.init.normal_(m.weight, std=0.01)def get_net():net = nn.Sequential(nn.Flatten(),nn.Linear(in_features, 512),nn.ReLU(),nn.Linear(512, 1))net.apply(init_weights)return net# rmse=Root Mean Squared Error,对数均方根误差
def log_rmse(net, features, labels):# 通过神经网络net对输入特征features进行前向传播得到预测值# 然后为了在取对数时进一步稳定该值,用torch.clamp()函数将小于1的值设置为1# 第三个参数:不设置上限,即预测可以无限大clipped_preds = torch.clamp(net(features), 1, float('inf'))rmse = torch.sqrt(loss(torch.log(clipped_preds),torch.log(labels)))# .item() 方法将rmse转换为Python标量返回return rmse.item()# weight_decay权重衰退
def train(net, train_features, train_labels, test_features, test_labels,num_epochs, learning_rate, weight_decay, batch_size):# 用于存储每一轮训练和测试集上的log rmse值train_ls, test_ls = [], []train_iter = d2l.load_array((train_features, train_labels), batch_size)# 这里使用的是Adam优化算法,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() # 更新模型参数# 将log_rmse函数返回的误差值追加到train_ls列表中就记录了每一轮迭代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_lsdef train_and_pred(train_features, test_features, train_labels, test_data,num_epochs, lr, weight_decay, batch_size):net = get_net()# 返回两个值,一个包含每个epoch训练,log mose的列表,一个未在代码片段中使用的值train_ls, _ = train(net, train_features, train_labels, None, None,num_epochs, lr, weight_decay, batch_size)# 第一个参数和第二个参数:接收一个epoch数组和一个包含训练log rmse的列表作为输入d2l.plot(np.arange(1, num_epochs + 1), [train_ls], xlabel='epoch',ylabel='log rmse', xlim=[1, num_epochs], yscale='log')# 打印最后一个epoch训练log rmse来评估模型的最终训练性能print(f'训练log rmse:{float(train_ls[-1]):f}')# 将训练好的网络模型应用于测试特征preds = net(test_features).detach().numpy()# 将其重新格式化以导出到Kaggle# pd.Series()封装成一个Pandas的Series对象,以确保数据类型与DataFrame的列兼容。test_data['SalePrice'] = pd.Series(preds.reshape(1, -1)[0])submission = pd.concat([test_data['Id'], test_data['SalePrice']], axis=1)# 用于将DataFrame保存为csv文件submission.to_csv('submission.csv', index=False)# 四个参数:表示将数据集分为多少个子集、当前折的索引、特征数据集、标签数据集
def get_k_fold_data(k, i, X, y):# 断言确保折数大于1,因为至少两个子集才能进行交叉验证assert k > 1# 每个子集(折)的大小=数据集的总行数除以折数,余数在最后一个子集处理fold_size = X.shape[0] // k# 初始化训练集X_train, y_train = None, Nonefor j in range(k):# idx将原始数据集的索引切片为 (j * fold_size) 到 ((j + 1) * fold_size),获得当前折数据idx = slice(j * fold_size, (j + 1) * fold_size)X_part, y_part = X[idx, :], y[idx]# 当前折的索引 j 与指定用于验证的索引 i 匹配,将该折的数据分配给验证集(X_valid 和 y_valid)if j == i:# 将该折的数据分配给验证集X_valid, y_valid = X_part, y_part# 如不匹配且训练集为空(第一次看到),则将该折的数据分配给训练集(X_train 和 y_train)elif X_train is None:X_train, y_train = X_part, y_part# 如不匹配且训练集不为空,则将该折的数据追加到训练集(X_train 和 y_train)中else:# 表示将X_train, X_part沿着第一个维度拼接起来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):# 做k次,每次拿到第i折,把数据data拿出来即拿到从训练集和验证集data = get_k_fold_data(k, i, X_train, y_train)# 每次循环都会创建一个新的模型实例,确保每折的评估是独立的net = get_net()# 调用train函数训练模型并返回训练损失列表和验证损失列表train_ls, valid_ls = train(net, *data, num_epochs, learning_rate,weight_decay, batch_size)# 索引[-1]获取最后一个epoch的损失,即当前折的训练损失累加到train_l_sumtrain_l_sum += train_ls[-1]valid_l_sum += valid_ls[-1]if i == 0: # 如果当前是第i折# 第一个参数:用作x轴数据# 第二个参数:一个列表储存了每一轮训练后的训练损失和验证损失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# @save
DATA_HUB = dict()
DATA_URL = 'http://d2l-data.s3-accelerate.amazonaws.com/'
DATA_HUB['kaggle_house_train'] = (DATA_URL + 'kaggle_house_pred_train.csv', '585e9cc9370b9160e7921475fbcd7d31219ce')
DATA_HUB['kaggle_house_test'] = (DATA_URL + 'kaggle_house_pred_test.csv', 'fal9780a7b011d9b009e8bff8e99922a8ee2eb90')
train_data = pd.read_csv(download('kaggle_house_train'))
test_data = pd.read_csv(download('kaggle_house_test'))# print(train_data.shape) # 1460个样本,80个特征,1个标号label
# print(test_data.shape) # 测试样本没有标号label
# print(train_data.iloc[0:4,[0,1,2,3,-3,-2,-1]]) # 前面四行的某些列特征
all_features = pd.concat((train_data.iloc[:, 1:-1], test_data.iloc[:, 1:]))
# print(all_features.shape)# 若无法获得测试数据,则可根据训练数据计算均值和标准差
# all_features.dtypes 获取每个特征的数据类型
# all_features.dtypes != 'object' 返回一个布尔值的 Series,其中为 True 的位置表示对应的特征不是对象类型(即数值类型)
# .index 提取数值类型特征的索引,并在numeric_features中存储
# print(all_features.dtypes) # 可以知道每一列分别为什么类型特征
numeric_features = all_features.dtypes[all_features.dtypes != 'object'].index
# print(numeric_features)
# 对all_features中所有数值类型特征进行标准化处理
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)# “Dummy_na=True”将“na”(缺失值)视为有效的特征值,并为其创建指示符特征
# 未指定column时,pd.get_dummies函数默认转换所有的分类列,包括MSZoning、SaleType、SaleCondition
# pd.get_dummies每个分类变量都会被转换成多列,每个唯一值对应一列
# 理解意思:某列有五类值,就将此列等价于变成五列,然后对应的列置1,不存在的列置0
all_features = pd.get_dummies(all_features, dummy_na=True)# 获取训练集的行数,即训练样本数量,并将其存储在n_train中
n_train = train_data.shape[0]
# [:n_train].values是选择前n_train作为训练集的特征将数据转换为Numpy数组
train_features = torch.tensor(all_features[:n_train].values, dtype=torch.float32)
test_features = torch.tensor(all_features[n_train:].values, dtype=torch.float32)
# 将SalePrice列单独提取为标签
train_labels = torch.tensor(train_data.SalePrice.values.reshape(-1, 1), dtype=torch.float32)
loss = nn.MSELoss()
in_features = train_features.shape[1]# 数据集被分成了5份,然后执行5次训练和验证过程,每次过程中,4份数据用于训练模型,剩下的一份用于
k, num_epochs, lr, weight_decay, batch_size = 5, 100, 0.01, 300, 32
# 分别包含每次迭代的训练集和验证集的log rmse值
train_l, valid_l = k_fold(k, train_features, train_labels, num_epochs, lr,weight_decay, batch_size)train_and_pred(train_features, test_features, train_labels, test_data,num_epochs, lr, weight_decay, batch_size)print(f'{k}-折验证: 平均训练log rmse: {float(train_l):f}, 'f'平均验证log rmse: {float(valid_l):f}')
d2l.plt.show()



十行代码:
# 预测
import pandas as pd
from autogluon.tabular import TabularDataset, TabularPredictor# 训练
train_data = TabularDataset('./data/California house price/house-prices-advanced-regression-techniques/train.csv')id, label = 'Id', 'SalePrice'
predictor = TabularPredictor(label=label).fit(train_data.drop(columns=[id]))test_data = TabularDataset('./data/California house price/house-prices-advanced-regression-techniques/test.csv')
preds = predictor.predict(test_data.drop(columns=[id]))
submission = pd.DataFrame({id: test_data[id], label: preds})
submission.to_csv('./kaggle_submission/submission_4.csv', index=False)
后面两个代码均为测试,发现并没有那么好。
import hashlib
import os
import tarfile
import zipfile
import requests
import numpy as np
import pandas as pd
import torch
from torch import nn
from d2l import torch as d2ldef 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)def init_weights(m):if isinstance(m, nn.Linear):nn.init.normal_(m.weight, std=0.01)def get_net():net = nn.Sequential(nn.Flatten(),nn.Linear(in_features, 512),nn.ReLU(),nn.Dropout(p=0.5), # 添加 Dropout 层nn.Linear(512, 256),nn.ReLU(),nn.Dropout(p=0.5), # 添加 Dropout 层nn.Linear(256, 128),nn.ReLU(),nn.Dropout(p=0.5), # 添加 Dropout 层nn.Linear(128, 1))net.apply(init_weights)return netdef log_rmse(net, features, labels):clipped_preds = torch.clamp(net(features), 1, float('inf'))rmse = torch.sqrt(loss(torch.log(clipped_preds),torch.log(labels)))return rmse.item()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)scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=10, gamma=0.7)for epoch in range(num_epochs):net.train() # 确保模型处于训练模式for X, y in train_iter:optimizer.zero_grad()l = loss(net(X), y)l.backward()optimizer.step()scheduler.step() # 更新学习率net.eval() # 切换到评估模式with torch.no_grad():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_lsdef 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}')net.eval() # 切换到评估模式with torch.no_grad():preds = net(test_features).detach().numpy()test_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)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# @save
DATA_HUB = dict()
DATA_URL = 'http://d2l-data.s3-accelerate.amazonaws.com/'
DATA_HUB['kaggle_house_train'] = (DATA_URL + 'kaggle_house_pred_train.csv', '585e9cc9370b9160e7921475fbcd7d31219ce')
DATA_HUB['kaggle_house_test'] = (DATA_URL + 'kaggle_house_pred_test.csv', 'fal9780a7b011d9b009e8bff8e99922a8ee2eb90')
train_data = pd.read_csv(download('kaggle_house_train'))
test_data = pd.read_csv(download('kaggle_house_test'))all_features = pd.concat((train_data.iloc[:, 1:-1], test_data.iloc[:, 1:]))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()))
all_features[numeric_features] = all_features[numeric_features].fillna(0)all_features = pd.get_dummies(all_features, dummy_na=True)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)
loss = nn.MSELoss()
in_features = train_features.shape[1]k, num_epochs, lr, weight_decay, batch_size = 5, 100, 0.01, 300, 32
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}')
train_and_pred(train_features, test_features, train_labels, test_data,num_epochs, lr, weight_decay, batch_size)
d2l.plt.show()
输出:


import hashlib
import os
import tarfile
import zipfile
import requests
import numpy as np
import pandas as pd
import torch
from torch import nn
from d2l import torch as d2l# 数据下载和提取功能
def download(name, cache_dir=os.path.join('..', 'data')):"""下载一个DATA_HUB中的文件,返回本地文件名"""if name not in DATA_HUB:raise ValueError(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:for chunk in iter(lambda: f.read(1048576), b''):sha1.update(chunk)if sha1.hexdigest() == sha1_hash:return fnameprint(f'正在从 {url} 下载 {fname}...')response = requests.get(url, stream=True)response.raise_for_status()with open(fname, 'wb') as f:f.write(response.content)return fnamedef download_extract(name, folder=None):"""下载并解压zip/tar文件"""fname = download(name)base_dir = os.path.dirname(fname)ext = os.path.splitext(fname)[1]if ext == '.zip':with zipfile.ZipFile(fname, 'r') as zip_ref:zip_ref.extractall(base_dir)elif ext in ('.tar', '.gz'):with tarfile.open(fname, 'r') as tar_ref:tar_ref.extractall(base_dir)else:raise ValueError('仅支持zip和tar文件的解压缩')return os.path.join(base_dir, folder) if folder else base_dir# 初始化权重
def init_weights(m):if isinstance(m, nn.Linear):nn.init.normal_(m.weight, std=0.01)# 创建网络
def get_net():net = nn.Sequential(nn.Flatten(),nn.Linear(in_features, 1024), # 增加神经元数量nn.ReLU(),nn.Dropout(0.3), # 调整 Dropout 率nn.Linear(1024, 512), # 增加神经元数量nn.ReLU(),nn.Dropout(0.3), # 调整 Dropout 率nn.Linear(512, 256),nn.ReLU(),nn.Dropout(0.3), # 调整 Dropout 率nn.Linear(256, 1))net.apply(init_weights)return net# 计算对数均方根误差
def log_rmse(net, features, labels):clipped_preds = torch.clamp(net(features), 1, float('inf'))rmse = torch.sqrt(loss(torch.log(clipped_preds), torch.log(labels)))return rmse.item()# 训练模型
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)scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=num_epochs)for epoch in range(num_epochs):net.train()for X, y in train_iter:optimizer.zero_grad()l = loss(net(X), y)l.backward()optimizer.step()scheduler.step()net.eval()with torch.no_grad():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# 训练并预测
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:{train_ls[-1]:f}')net.eval()with torch.no_grad():preds = net(test_features).detach().numpy()test_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)# K折交叉验证数据获取
def get_k_fold_data(k, i, X, y):assert k > 1, 'k必须大于1'fold_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], dim=0)y_train = torch.cat([y_train, y_part], dim=0)return X_train, y_train, X_valid, y_valid# K折交叉验证
def 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: {train_ls[-1]:.6f}, 验证log rmse: {valid_ls[-1]:.6f}')return train_l_sum / k, valid_l_sum / k# 数据准备
DATA_HUB = {'kaggle_house_train': ('http://d2l-data.s3-accelerate.amazonaws.com/kaggle_house_pred_train.csv', '585e9cc9370b9160e7921475fbcd7d31219ce'),'kaggle_house_test': ('http://d2l-data.s3-accelerate.amazonaws.com/kaggle_house_pred_test.csv','fal9780a7b011d9b009e8bff8e99922a8ee2eb90')
}
train_data = pd.read_csv(download('kaggle_house_train'))
test_data = pd.read_csv(download('kaggle_house_test'))all_features = pd.concat([train_data.iloc[:, 1:-1], test_data.iloc[:, 1:]])
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()).fillna(0)
all_features = pd.get_dummies(all_features, dummy_na=True)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)
loss = nn.MSELoss()
in_features = train_features.shape[1]# 设置训练参数
k, num_epochs, lr, weight_decay, batch_size = 5, 100, 0.01, 0, 32# 执行K折交叉验证
train_l, valid_l = k_fold(k, train_features, train_labels, num_epochs, lr, weight_decay, batch_size)
print(f'{k}-折验证: 平均训练log rmse: {train_l:.6f}, 平均验证log rmse: {valid_l:.6f}')# 训练模型并生成预测
train_and_pred(train_features, test_features, train_labels, test_data, num_epochs, lr, weight_decay, batch_size)
d2l.plt.tight_layout() # 调整子图参数,使之填充整个图像区域
d2l.plt.show()
输出:


4、如果我们没有像本节所做的那样标准化连续的数值特征,会发生什么?
可能导致模型训练不稳定、性能下降、泛化能力差:未标准化的特征可能具有不同的尺度,这可能导致某些特征在模型训练过程中权重过大或过小,使得模型的收敛速度变慢,甚至无法收敛,标准化可以使得以确保所有特征对模型的影响是均衡的,从而提高算法的性能、收敛速度以及泛化能力。
可能导致数值问题:如果数据的特征值范围非常广泛,可能会导致数值溢出或者精度问题。标准化可以减少这些问题的发生,确保计算的稳定性和准确性。
可能导致特征重要性误判:未标准化的特征可能会导致对特征重要性的误判。模型可能会错误地认为某些特征对目标变量的影响更大,而实际上这只是因为该特征的值范围较大而已。
相关文章:
深度学习--------------Kaggle房价预测
目录 下载和缓存数据集访问和读取数据集总代码 数据预处理训练K折交叉验证模型选择总代码提交你的Kaggle预测提交Kaggle 下载和缓存数据集 import hashlib import os import tarfile import zipfile import requests# download传递的参数分别是数据集的名称、缓存文件夹的路径…...
cpio 命令
前言 cpio(Copy In and Out)是一种在类 Unix 操作系统中处理归档文件的多功能工具。与 tar 不同,cpio 有其独特的优势和使用场景,特别是在与其他命令结合使用时。本文将带你了解 cpio 的基础知识、用法及实际示例。 什么是 cpio…...
TreeMap自定义排序
我们都知道TreeMap可以根据key按字典升序排序。但在某些场景下,我们需要自定义排序规则,为了代码优雅一些,我们也希望在stream中groupingBy时自定义排序规则,就可以参考本文的实现。 1. 使用TreeMap默认的排序规则(按…...
我的CSDN 512天创作纪念日-20240807
机缘 在 2023 年 3 月 13 日,我撰写了第一篇技术博客《软考高级-系统分析师-案例分析-系统维护与设计模式》。那一天,我决定将自己的实战项目经验和学习心得记录下来,与更多志同道合的朋友分享。成为一名专业 IT 作者的梦想,促使我…...
微服务-实现nacos的集群和Gateway网关的实现、认证校验、解决跨域
1. nacos的集群模式 1.1 分析 nacos在企业中的使用100%都是集群模式。需要掌握nacos集群的搭建 nacos的数据存放在derby本地磁盘中,nacos集群模式会导致数据库数据不一致,使用加一层思想,修改nacos的数据库,使用mysql数据库&…...
数据库中的约束,聚合函数以及联合查询
目录 数据库中的约束 not null unique default primary key foreign key 表的设计 聚合函数(查询) 分组 联表查询(多表查询) 内连接 外连接 左外连接 右外连接 自连接 子查询 合并查询 数据库中的约束 为了保证…...
【AI大模型】Ollama+OpenWebUI+llama3本地大模型
本地部署大模型 0.引言1.部署安装1.1部署工具1.2 概念介绍1.3 ollama安装后的基本使用1.4 大模型权重下载1.4.1 ollama在线下载1.4.2 huggingFace下载大模型权重及如何使用ollama进行调用 2.带有UI界面的使用3.参考 0.引言 (1)目的 本教程主要关于开源A…...
习题20240807
文章目录 题目 1: 泛型类题目 2: 泛型方法题目 3: 泛型接口题目 4: 泛型约束题目 5: 泛型集合题目6:题目7:题目8:题目9: 题目 1: 泛型类 编写一个泛型类 Box,它能够存储一个类型为 T 的值,并提供方法 SetI…...
src挖掘-记一次有趣的逻辑漏洞分享
漏洞挖掘-记一次有趣的逻辑漏洞挖掘 前言简述1、信息收集2、找功能点3、挖掘漏洞案例一:任意用户注册漏洞案例二-垂直越权导致管理员密码重置获得管理员后台权限漏洞总结 前言 此文章是小白的学习笔记,请不要利用文章内相关知识点进行非法渗透ÿ…...
【C++】STL | list (链表)详解及重要函数的实现
目录 前言 总代码 ListNode类框架的建立 (成员与模板) list类的框架 普通构造 与 empty_init(适合不同类型构造函数的小函数) list的迭代器 引子 operator、operator--(前置与后置) operator 与 operator! operator* 与 …...
警惕智能手机的“隐形眼”:如何保护我们的数字隐私堡垒
随着智能手机深入我们生活的方方面面,它变得无所不在,甚至无所不知。 但你是否意识到,你的手机可能正在悄无声息地“监听”你的一举一动? 从你的搜索习惯到日常对话,手机的个性化推荐系统正不断收集你的数据。 本文…...
人工智能算法工程师(高级)课程12-自然语言处理之NLP的语言模型-ELMo,transformer,BERT与代码详解
大家好,我是微学AI,今天给大家介绍一下人工智能算法工程师(高级)课程12-自然语言处理之NLP的语言模型-ELMo,transformer,BERT与代码详解。本课程面向高级人工智能算法工程师,深入讲解自然语言处理(NLP)中的关键语言模型技术,包括了EMLo和transformer架构。此外,课程还详细…...
PicGo + gitee 免费搭建个人图床
目录 1 图床概念2 使用gitee和PicGo搭建图床流程2.1 下载安装PicGo工具 3 图片上传错误处理3.1 PicGo客户端提示404错误信息图片上传失败3.2 PicGo客户端提示400错误信息图片上传失败 1 图床概念 "图床"是一个网络术语,它指的是一种用于存储和托管图片…...
组合数的低复杂度运算
题源 题目 F. 预期中位数 每次测试的时间限制:3 秒 每次测试的内存限制:256 兆字节 Arul 有一个长度为 n 的二进制数组* a。 他将取该数组中所有长度为 k(k 为奇数)的子序列并找到它们的中位数。 所有这些值的总和是多少…...
小型并网式光伏气象站:光伏电站的智能守护者
小型并网式光伏气象站以其独特的功能和优势,成为了电站高效运行的智能守护者。小型并网式光伏气象站通过精准的数据采集与分析,为光伏电站的运维管理提供了强有力的支持。 小型并网式光伏气象站能够实时监测并记录光伏电站周围环境的多种气象参数&#x…...
JavaScript 中的回调函数(callback)
JavaScript 中的回调函数(callback) JavaScript 中的回调函数(callback)是一个传递给另一个函数作为参数的函数,并且这个传递的函数可以在其他函数内部被调用执行。回调函数是异步编程的一个核心概念,特别…...
计算机毕业设计hadoop+spark+hive漫画推荐系统 动漫视频推荐系统 漫画分析可视化大屏 漫画爬虫 漫画推荐系统 漫画爬虫 知识图谱 大数据
HadoopSparkHive漫画推荐系统详细开题报告 一、引言 随着互联网技术的飞速发展,动漫和漫画产业的数据量急剧增长。用户面临着海量漫画作品的选择难题,如何从这些数据中高效地提取有价值的信息,为用户推荐符合其喜好的漫画作品,成…...
解决pycharm日志总是弹出“无法运行Git,未安装Git”的问题
需求分析 我电脑中安装了git,但是打开pycharm,右下角总是弹出 无法运行Git,未安装Git的日志。 解决方法 首先打开pycharm,按照以下路径,依次点击。 file -----settings-----version control -----Git----Git path(选择自己下载…...
threejs 节点材质系统 绑定attribute
新的 节点材质系统 绑定属性及使用 非常方便 不必重复声明 以instances为例 import {instancedBufferAttribute,instancedDynamicBufferAttribute,} from "three/tsl";声明一个 InstancedBufferAttribute 使用 instancedBufferAttribute包装后就可以在shader中直接使…...
Rabbitmq的几种工作模式
工具类 public class RabbitMQConnection {public static Connection getConnection() throws Exception{//1.创建connectionFactoryConnectionFactory connectionFactory new ConnectionFactory();//2.配置HostconnectionFactory.setHost("127.0.0.1");//3.设置Po…...
零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?
一、核心优势:专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发,是一款收费低廉但功能全面的Windows NAS工具,主打“无学习成本部署” 。与其他NAS软件相比,其优势在于: 无需硬件改造:将任意W…...
visual studio 2022更改主题为深色
visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中,选择 环境 -> 常规 ,将其中的颜色主题改成深色 点击确定,更改完成...
MODBUS TCP转CANopen 技术赋能高效协同作业
在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...
【HTML-16】深入理解HTML中的块元素与行内元素
HTML元素根据其显示特性可以分为两大类:块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...
Pinocchio 库详解及其在足式机器人上的应用
Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...
基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解
JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用,结合SQLite数据库实现联系人管理功能,并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能,同时可以最小化到系统…...
免费PDF转图片工具
免费PDF转图片工具 一款简单易用的PDF转图片工具,可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件,也不需要在线上传文件,保护您的隐私。 工具截图 主要特点 🚀 快速转换:本地转换,无需等待上…...
AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机
这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机,因为在使用过程中发现 Airsim 对外部监控相机的描述模糊,而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置,最后在源码示例中找到了,所以感…...
PostgreSQL——环境搭建
一、Linux # 安装 PostgreSQL 15 仓库 sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-$(rpm -E %{rhel})-x86_64/pgdg-redhat-repo-latest.noarch.rpm# 安装之前先确认是否已经存在PostgreSQL rpm -qa | grep postgres# 如果存在࿰…...
BLEU评分:机器翻译质量评估的黄金标准
BLEU评分:机器翻译质量评估的黄金标准 1. 引言 在自然语言处理(NLP)领域,衡量一个机器翻译模型的性能至关重要。BLEU (Bilingual Evaluation Understudy) 作为一种自动化评估指标,自2002年由IBM的Kishore Papineni等人提出以来,…...
