基于简单神经网络模型的房价预测案例
1. 案例介绍
本文展示的是基于简单神经网络模型的房价预测案例,在经过数据集获取、模型构建、模型训练与验证和模型评估后,完成本次的案例演示。
2.数据源
数据来源于公开的房价数据集,使用的House Prices数据集,大家可以动手尝试。
数据集:https://www.kaggle.com/c/house-prices-advanced-regression-techniques

3. 导入所需模块
# 导入所需模块
import torch
import torch.nn as nn
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from torch.utils.data import TensorDataset,DataLoader,Dataset
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler,OneHotEncoder
from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
from sklearn.impute import SimpleImputer
4. 数据处理与包装
在数据处理与包装过程中,我们使用Pipeline管道操作,流水线式的对数据进行批处理。具体对数据分为数值型和类别型进行分别处理,构建管道Pipeline和列转换器ColumnTransformer,对数值型数据:缺失值填充和标准化;对类别型数据:缺失值填充和one-hot编码。
# 1. 处理数据,返回tensor数据集
def create_dataset():
# 1.读取数据
data = pd.read_csv(r"G:\learning video\07_深度学习核心\4.视频\day10\house_prices.csv")
# print(data)
# 2. 提取特征和标签
data.drop(['Id'],axis=1,inplace=True)
x = data.drop(['SalePrice'],axis=1)
y = data['SalePrice']
# 3.划分数据集
x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.25,random_state=12)
# 4.特征工程
# 4.1 筛选两类数据,数值型和类别型
numerical_data = x.select_dtypes(exclude=['object']).columns
categorical_data = x.select_dtypes(include=['object']).columns
# 4.2 构建两类Pipeline
numerical_transform = Pipeline(steps=[
("fiLLnan",SimpleImputer(strategy='mean')),
('Std',StandardScaler())
])
categorical_transform = Pipeline(steps=[
('fillnan',SimpleImputer(strategy='constant',fill_value='nan')),
('one_hot',OneHotEncoder(handle_unknown='ignore'))
])
# 4.3 构造列转换器
transform = ColumnTransformer(
transformers=[
('num',numerical_transform,numerical_data),
('cat',categorical_transform,categorical_data)
])
# 4.4 开始列转换
x_train = pd.DataFrame(transform.fit_transform(x_train).toarray(),columns=transform.get_feature_names_out())
x_test = pd.DataFrame(transform.transform(x_test).toarray(),columns=transform.get_feature_names_out())
# 5 转换为tensor数据集
train_dataset = TensorDataset((torch.tensor(x_train.values,dtype=torch.float)),torch.tensor(y_train.values,dtype=torch.float))
test_dataset = TensorDataset((torch.tensor(x_test.values,dtype=torch.float)),torch.tensor(y_test.values,dtype=torch.float))
return train_dataset,test_dataset,x_train.shape[1]
# 得到数据集
train_dataset,test_dataset,shape = create_dataset()
5. 模型构建
在模型构建方面,我搭建了一个简单的神经网络模型,利用用到了线性层Linear、批量标准化BatchNorm、激活函数Relu以及正则化项随机失活DropOut。
# 构建模型
model = nn.Sequential(
nn.Linear(shape,128), # 随机数种子不同,输入features不要写死
nn.BatchNorm1d(128),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(128,1)
)
6. 模型训练与验证
在模型训练与验证过程中,损失函数:自定义了一个log_loss,即对均方根误差取对数,这更加符合损失的度量。优化器:选用了Adam,可以更换不同的优化器尝试。模型训练与验证流程:我采取了一轮训练一轮验证的模式,不断在验证集上测试,防止在训练集上过拟合。
# 定义损失函数衡量
def loss(y_pred,y_true):
y_pred.squeeze_() # 压缩tensor,[[1]] --- [1]
y_pred = torch.clamp(y_pred,1,float('inf')) # 限制预测范围,避免不合理的情况
loss = nn.MSELoss()
loss_value = torch.sqrt(loss(torch.log(y_pred),torch.log(y_true)))
return loss_value
# 模型训练和预测
def model_train_test(model,train_dataset,test_dataset,device,lr,epoch,batch_size):
# 1. 参数初始化
# 1.1 遍历sequential,选择合适的参数进行初始化
def init_weights_bias(m):
if isinstance(m, nn.Linear):
# 找“下一个”非 Linear 的激活
nn.init.kaiming_uniform_(m.weight)
if m.bias is not None:
nn.init.zeros_(m.bias)
model.apply(init_weights_bias) # 模型参数初始化
model.to(device) # 指定平台
# 2 定义优化器
optimizer = torch.optim.Adam(model.parameters(),lr=lr)
train_loss = []
test_loss = []
# 训练与测试
for i in range(0,epoch):
# 开启训练模式
model.train()
total_loss = 0 # 每个epoch的sum(loss)
train_data = DataLoader(train_dataset, batch_size=batch_size, shuffle=True) # 加载数据
for batch_count,(X,y) in enumerate(train_data):
X = X.to(device)
y = y.to(device)
y_pred = model(X) # 前向传播
loss_value = loss(y_pred,y) # 计算损失
total_loss += loss_value.item() # 累加loss
loss_value.backward() # 反向传播
optimizer.step() # 参数更新
optimizer.zero_grad() # 梯度清零
# 打印进度条
print(f"\repoch{i+1:0>3}[{'=' * 50 * int((batch_count+1) / len(train_data)):<50}]",end='')
loss_epoch = total_loss / len(train_data)
train_loss.append(loss_epoch)
# 开启测试模式
model.eval()
total_loss_test = 0 # 每个epoch的sum(loss)
test_data = DataLoader(test_dataset, batch_size=batch_size, shuffle=True) # 加载数据
with torch.no_grad():
for X,y in test_data:
X = X.to(device)
y = y.to(device)
y_pred_test = model(X) # 前向传播
loss_value_test = loss(y_pred_test,y) # 计算损失
total_loss_test += loss_value_test.item() # 累加loss
loss_epoch_test = total_loss_test / len(test_data)
test_loss.append(loss_epoch_test)
print(f"第{i+1}轮epoch训练,train_loss_mean:,{loss_epoch:.6f},test_loss_mean,{loss_epoch_test:.6f}")
return train_loss,test_loss
7. 模型评估
device = 'cuda' if torch.cuda.is_available() else 'cpu' # 指定平台
train_dataset,test_dataset,shape = create_dataset()
train_loss,test_loss = model_train_test(model,train_dataset,test_dataset,device,lr=0.01,epoch=200,batch_size=10)
# 可视化结果
plt.plot(train_loss,'r',label='train loss')
plt.plot(test_loss,'y',label='test loss')
plt.legend()
plt.show()
模型效果
8. 总结
在这个简单的回归案例中,我使用了公开的房价数据集进行训练与验证,整体模型的架构比较简单:搭建了简单的神经网络模型,配合了一些标准化和正则化方法,后续过程是一轮训练一轮验证,统计每个轮次的平均损失,并对模型效果进行评估,大家可以动手试试。
鲲鹏昇腾开发者社区是面向全社会开放的“联接全球计算开发者,聚合华为+生态”的社区,内容涵盖鲲鹏、昇腾资源,帮助开发者快速获取所需的知识、经验、软件、工具、算力,支撑开发者易学、好用、成功,成为核心开发者。
更多推荐


所有评论(0)