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防止因为这个房价的定位影响结果)
文章图片
我们需要提交的形式是csv格式下,房子的Id和其销售价格
文章图片
二、数据分析及处理 我这里因为只是作为一个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 |
可以看到数据训练集包含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开始,自己修改一下
文章图片
提交结果 将csv文件提交
最后得分是0.15877,作为一个baseline来说还行了
文章图片
总结 【Kaggle|飞桨AI Studio之加州房价预测——机器学习的Hello world】后面根据前人大佬的一些数据处理来做一些改进
推荐阅读
- android|android studio中ndk的使用
- Android|Android JNI之静态注册(android studio)
- Android|Android Studio 的 Browse Repositories 下载不了插件
- c/c++|有感 Visual Studio 2015 RTM 简介 - 八年后回归 Dot Net,终于迎来了 Mvc 时代,盼走了 Web 窗体时代...
- 360|360 将停止 StartCom 数字证书业务;微软的 Visual Studio Tools for AI 现已提供使用
- Android|Android 进阶之旅 | android studio freeline的使用
- Android|Android Studio 插件 - GsonFormat
- Keras|将Pytorch模型迁移到android端(android studio)【未实现】
- 规范你的代码:AndroidStudio|规范你的代码:AndroidStudio 一键生成MVP模板代码
- ACDSee|ACDSee Photo Studio 5——数字图像处理软件