Kaggle|飞桨AI Studio之加州房价预测——机器学习的Hello world




飞桨AI Studio之加州房子预测——机器学习的Hello world
目录
飞桨AI Studio之加州房子预测(上)——机器学习的Hello world
前言
一、比赛分析
二、数据分析及处理
导入库
读取数据
数据预处理
网络定义
RMSE定义
训练函数
超参数定义和训练
生成提交文件
提交结果
总结



前言 房价预测这个比赛,我个人认为是比MNIST更加适合新手入门的一个项目,而且Kaggle上有现成的比赛,可以通过这个平台去检验自己的一些成果。
这个比赛主要还是锻炼对于数据处理的能力,对于搭建模型没有什么特别大的需求,比较适合新手。
我这里只是使用了飞浆的平台,但比赛还是在Kaggle上比的,具体网址如下。
House Prices - Advanced Regression Techniquesw
我以下的所有代码都是在飞浆的AI Studio中运行的
notebook链接



一、比赛分析 简单的说,比赛提供了有关一些加州房子的信息,其中包括其买入价格,房子的修建情况等79项信息,其中的信息有数值信息也有包含字符的信息,我们需要根据这些信息去预测test数据集中得到房价。
在这个房价预测中,我们的评价指标是RMSE,且数据采用的是log形式(因为房价差距会很大,取log防止因为这个房价的定位影响结果)
Kaggle|飞桨AI Studio之加州房价预测——机器学习的Hello world
文章图片

我们需要提交的形式是csv格式下,房子的Id和其销售价格
Kaggle|飞桨AI Studio之加州房价预测——机器学习的Hello world
文章图片





二、数据分析及处理 我这里因为只是作为一个baseline,主要是对数据做一个可视化和将其简单的处理使其可以训练。
导入库

import pandas as pd import numpy as np import paddle import paddle.nn as nn import paddle.nn.functional as F import paddle.optimizer as optimizer import matplotlib.pyplot as plt

读取数据
# 读取文件 train_path = '/home/aistudio/data/data109189/train.csv' test_path = '/home/aistudio/data/data109189/test.csv' train_dataset = pd.read_csv(train_path) test_dataset = pd.read_csv(test_path) print(train_dataset.shape) print(test_dataset.shape) train_dataset.head()""" (1460, 81) (1459, 80) """


Id MSSubClass MSZoning LotFrontage LotArea Street Alley LotShape LandContour Utilities ... PoolArea PoolQC Fence MiscFeature MiscVal MoSold YrSold SaleType SaleCondition SalePrice
0 1 60 RL 65.0 8450 Pave NaN Reg Lvl AllPub ... 0 NaN NaN NaN 0 2 2008 WD Normal 208500
1 2 20 RL 80.0 9600 Pave NaN Reg Lvl AllPub ... 0 NaN NaN NaN 0 5 2007 WD Normal 181500
2 3 60 RL 68.0 11250 Pave NaN IR1 Lvl AllPub ... 0 NaN NaN NaN 0 9 2008 WD Normal 223500
3 4 70 RL 60.0 9550 Pave NaN IR1 Lvl AllPub ... 0 NaN NaN NaN 0 2 2006 WD Abnorml 140000
4 5 60 RL 84.0 14260 Pave NaN IR1 Lvl AllPub ... 0 NaN NaN NaN 0 12 2008 WD Normal 250000
5 rows × 81 columns
可以看到数据训练集包含1460个,其中除去ID和saleprice有79个特征。
测试集和1459个,不包含saleprice这一栏故有80列。
其中特征包含数字,文本,还有许多数据丢失。
数据预处理 这里数据的预处理主要是针对将数值数据作归一化,将字符数据做one-hot编码,对缺失数据进行处理和划分训练集和验证集
这里说一下,为什么要把训练集和测试集的特征放到一起处理
一是因为做one-hot编码时,训练集中的字符信息测试集不一定有,不一起处理,会导致总的特征数不一样。
二是因为一起处理更加方便
# 先把训练集的label取出来 train_label = train_dataset['SalePrice'] # 合并一下测试集和训练集的信息 train_test_data = https://www.it610.com/article/pd.concat([train_dataset.iloc[:, 1:-1], test_dataset.iloc[:, 1:]]) # 获取数值特征 numeric_features = train_test_data.dtypes[train_test_data.dtypes !='object'].index # 均一化所有数值特征 train_test_data[numeric_features] = train_test_data[numeric_features].apply(lambda x: (x - x.mean())/ (x.std()) ) # 将所有丢失的数据变为0,因为上一步整个数据已经变为均值是0了,对整体没有影响 train_test_data[numeric_features] = train_test_data[numeric_features].fillna(0) # 将非数值的特征转为one-hot编码 train_test_data = https://www.it610.com/article/pd.get_dummies(train_test_data, dummy_na=True) # 再把训练集和测试集重新划分出来 train_num = train_dataset.shape[0] train_dataset = train_test_data[: train_num] test_dataset = train_test_data[train_num: ] print(train_dataset.shape) print(test_dataset.shape) # 简单划分一下训练集和验证集 num_train = round(1460*0.8) training_data = np.array(train_dataset.iloc[0: num_train]) training_label = np.array(train_label.iloc[0: num_train]) val_data = np.array(train_dataset.iloc[num_train: ]) val_label = np.array(train_label.iloc[num_train: ])""" 处理完后,特征变成331个 (1460, 331) (1459, 331) """

我这里因为后面训练直接把训练和验证集写在一个函数里的关系,所以要做一下合并
# 增加一个维度方便拼接 training_label = training_label[None] val_label = val_label[None] training_data = https://www.it610.com/article/np.concatenate((training_data, training_label.T), axis=1) val_data = np.concatenate((val_data, val_label.T), axis=1) dataloader = {'train':training_data, 'val':val_data}

网络定义 这里简单的使用一个单全连接网络作为一个线性回归模型
class Net(nn.Layer):# self代表类的实例自身 def __init__(self): # 初始化父类中的一些参数 super(Net, self).__init__()# 定义一层全连接层,输入维度是331,输出维度是1 self.fc1 = nn.Linear(in_features=331, out_features=1024) # 网络的前向计算 def forward(self, inputs): x = self.fc1(inputs) return x

RMSE定义 没有现成的定义RMSE,手写一个
def log_rmse(preds, labels): # 为了在取对数时进?步稳定该值,将?于1的值设置为1 preds = paddle.fluid.layers.clip(preds, 1, float('inf')) # 同时取log preds = paddle.log(preds) labels = paddle.log(labels) # 做MSE loss = F.square_error_cost(preds, label=labels) loss = loss.mean() # 取sqrt rmse = paddle.sqrt(loss) return rmse.item()

训练函数 比较普通的训练函数,把训练和验证放的一起了
def train_model(modle, epoch_num, dataloader, batch_size, opt): # 记录最小的损失 min_loss = 0 # 用来画图,分别记录 total_loss = {"train": [], "val": []} for epoch in range(epoch_num): # 输出格式 print('Epoch {}/{}'.format(epoch, epoch_num - 1)) print('-' * 10) # 选择训练模式或者测试模式 for phase in ['train', 'val']: if phase == 'train': model.train()# Set model to training mode else: model.eval()# Set model to evaluate mode # 随机打乱对于数据 np.random.shuffle(dataloader[phase]) mini_batches = [dataloader[phase][k:k+batch_size] for k in range(0, len(dataloader[phase]), batch_size)] running_loss = 0 for index, mini_batch in enumerate(mini_batches): mini_batch = np.array(mini_batch).astype('float32') x = mini_batch[:, :-1] y = mini_batch[:, -1:]# 转换成paddle格式 x = paddle.to_tensor(x) y = paddle.to_tensor(y) # 前行传播 preds = modle(x) # 计算损失 loss = F.square_error_cost(preds, label=y) avg_loss = loss.mean() train_ls = log_rmse(preds, y) running_loss += train_ls# 反向传播 avg_loss.backward() # 梯度更新 opt.step() # 梯度请0 opt.clear_grad() running_loss = running_loss / index total_loss[phase].append(running_loss) print('{} Loss: {:.4f}'.format(phase, running_loss))plt.figure() epoch = np.arange(epoch_num) for phase in ['train', 'val']: plt.plot(epoch, total_loss[phase], label=phase) plt.show()

超参数定义和训练
# 定义超参数 model = Net() model.train() loss = nn.MSELoss() opt = optimizer.SGD(learning_rate=0.01, parameters=model.parameters()) epoch_num = 100 batch_size = 64train_model(model, epoch_num , dataloader, batch_size , opt)

生成提交文件
# 提交测试集预测和生产kaggle提交文件csv test_dataset = np.array(test_dataset).astype('float32') test_dataset = paddle.to_tensor(test_dataset) test_preds = model(test_dataset).detach().numpy() test_sub = {'Id':None, 'SalePrice':None} test_sub['SalePrice'] = pd.Series(test_preds.reshape(1, -1)[0]) test_sub['SalePrice'].to_csv('submission.csv')

这里生成完之后,将表头改为Id和SalePrices,Id序号要求从1461开始,自己修改一下
Kaggle|飞桨AI Studio之加州房价预测——机器学习的Hello world
文章图片

提交结果 将csv文件提交
最后得分是0.15877,作为一个baseline来说还行了
Kaggle|飞桨AI Studio之加州房价预测——机器学习的Hello world
文章图片





总结 【Kaggle|飞桨AI Studio之加州房价预测——机器学习的Hello world】后面根据前人大佬的一些数据处理来做一些改进

    推荐阅读