赛题说明
规则概述
1.线上比赛要求参赛选手根据给定的数据集,建立模型,预测房屋租金。
2.数据集中的数据类别包括租赁房源、小区、二手房、配套、新房、土地、人口、客户、真实租金等。
3.平台提供的数据包括训练集、预测试集(Test A)、正式测试集(Test B),详见数据集说明。
4.参赛选手需要将预测的结果按照测试集ID顺序输出,以便平台对提交模型的结果进行验证。每天每个参赛者最多可以提交2次。
模型评分标准
S
c
o
r
e
=
1
−
∑
i
=
1
m
(
y
−
y
^
)
∑
i
=
1
m
(
y
−
y
‾
)
Score = 1-\dfrac{\sum_{i=1}^m{(y-\hat {y})}}{\sum_{i=1}^m{(y-\overline {y})}}
Score=1−∑i=1m(y−y)∑i=1m(y−y^)
Score值越大,拟合效果越好
线上赛数据发放与结果提交
1.训练数据Train_data和预测试集Test A将在赛事开始时开放,Train_data供参赛选手训练模型;预测试集Test A只供参赛选手熟悉提交流程,Test A的预测结果不计入正式成绩。
2.正式测试数据Test B在赛事规定的时间开放,仅供模型验证使用,禁止调整测试数据Test B的顺序及任何其他形式的修改。参赛选手需要在赛事结束前提交模型、代码以及预测结果。平台将及时更新结果排名,取最好成绩作为客观成绩,每人每天有2次提交机会。
比赛要求
- 赛选手可以根据模型需求,筛选适当的数据维度。
- 参赛选手可以根据模型需求,自行清洗训练数据。
- 不得使用提供的数据集之外的数据训练模型。
- 不得将自行手工标注的结果运用于训练和测试。
- 参赛选手需要同时提交说明文档、预测结果、训练和预测代码、模型(参数集),详见结果提交要求
- 参赛选手所提交程序应可在Linux/windows环境顺利运行。建议(不强制)使用Python 2.7或Python3.6作为首选编程环境,使用Anaconda 3 * 搭建软件环境。不限制第三方软件包使用,但须获得合法授权和软件拷贝,以确保主办方可以复现程序运行过程。
- 参赛选手的提交作品需要可完整复现训练和预测过程,主办方不会做任何代码修改,如无法复现的,视作无效提交。
复赛晋级与综合评审
根据模型有效提交的得分,前10名选手可以晋级复赛。晋级复赛的选手需要通过PPT展示进行线下答辩,PPT展示主要包括数据清洗规则、模型创新、算法实现、结果分析等。
数据集字段说明
- 对于小区信息中,关于city、region、plate三者的关系:city>region>plate
- 土地数据中,土地楼板面积是指在土地上建筑的房屋总面积
赛题分析
认识数据
- 了解比赛的背景
- 分类问题还是回归问题
- 熟悉比赛的评分函数
对比赛数据做EDA
- 数据分析
- 分类问题还是回归问题
- 缺失值分析
- 特征值分析
- 是否有单调特征列(单调的特征列很大可能是时间)
- 特征nunique分布
- 出现在测试集中的community,但是在训练集中数量较少
- 统计特征值出现频次大于100的特征
- Label分布
- 不同的特征值的样本的label的分布
#coding:utf-8
#导入warnings包,利用过滤器来实现忽略警告语句。
import warnings
warnings.filterwarnings('ignore')
# GBDT
from sklearn.ensemble import GradientBoostingRegressor
# XGBoost
import xgboost as xgb
# LightGBM
import lightgbm as lgb
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
#载入数据
data_train = pd.read_csv('./train_data.csv')
data_train['Type'] = 'Train'
data_test = pd.read_csv('./test_a.csv')
data_test['Type'] = 'Test'
data_all = pd.concat([data_train, data_test], ignore_index=True)
总体情况一览
# 总体情况
print(data_train.info())
print(data_train.describe())
data_train.head()
输出:
分类特征和连续型特征
#根据特征含义和特征一览,大致可以判断出数值型和类别型特征如下
categorical_feas = ['rentType', 'houseType', 'houseFloor', 'region', 'plate', 'houseToward', 'houseDecoration',
'communityName','city','region','plate','buildYear']
numerical_feas=['ID','area','totalFloor','saleSecHouseNum','subwayStationNum',
'busStationNum','interSchoolNum','schoolNum','privateSchoolNum','hospitalNum',
'drugStoreNum','gymNum','bankNum','shopNum','parkNum','mallNum','superMarketNum',
'totalTradeMoney','totalTradeArea','tradeMeanPrice','tradeSecNum','totalNewTradeMoney',
'totalNewTradeArea','tradeNewMeanPrice','tradeNewNum','remainNewNum','supplyNewNum',
'supplyLandNum','supplyLandArea','tradeLandNum','tradeLandArea','landTotalPrice',
'landMeanPrice','totalWorkers','newWorkers','residentPopulation','pv','uv','lookNum']
缺失值分析
# 缺失值分析
def missing_values(df):
alldata_na = pd.DataFrame(df.isnull().sum(), columns={'missingNum'})
alldata_na['existNum'] = len(df) - alldata_na['missingNum']
alldata_na['sum'] = len(df)
alldata_na['missingRatio'] = alldata_na['missingNum']/len(df)*100
alldata_na['dtype'] = df.dtypes
#ascending:默认True升序排列;False降序排列
alldata_na = alldata_na[alldata_na['missingNum']>0].reset_index().sort_values(by=['missingNum','index'],ascending=[False,True])
alldata_na.set_index('index',inplace=True)
return alldata_na
missing_values(data_train)
输出:
说明:仅有pv、uv存在缺失值,后面再探究会发现缺失的都是属于同一个plate,可能是官方直接删除了该plate的pv、uv
单调特征列分析
#是否有单调特征列(单调的特征列很大可能是时间)
def incresing(vals):
cnt = 0
len_ = len(vals)
for i in range(len_-1):
if vals[i+1] > vals[i]:
cnt += 1
return cnt
fea_cols = [col for col in data_train.columns]
for col in fea_cols:
cnt = incresing(data_train[col].values)
if cnt / data_train.shape[0] >= 0.55:
print('单调特征:',col)
print('单调特征值个数:', cnt)
print('单调特征值比例:', cnt / data_train.shape[0])
输出:
特征nunique分布
# 特征nunique分布
for feature in categorical_feas:
print(feature + "的特征分布如下:")
print(data_train[feature].value_counts())
if feature != 'communityName': # communityName值太多,暂且不看图表
plt.hist(data_all[feature], bins=3)
plt.show()
输出:
communityName特征:
print(data_train['communityName'].value_counts())
print(data_test['communityName'].value_counts())
输出:
统计特征值频次大于100的特征
# 统计特征值出现频次大于100的特征
for feature in categorical_feas:
df_value_counts = pd.DataFrame(data_train[feature].value_counts())
df_value_counts = df_value_counts.reset_index()
df_value_counts.columns = [feature, 'counts'] # change column names
print(df_value_counts[df_value_counts['counts'] >= 100])
输出:
Label分布
# Labe 分布
fig,axes = plt.subplots(2,3,figsize=(20,5))
fig.set_size_inches(20,12)
sns.distplot(data_train['tradeMoney'],ax=axes[0][0])
sns.distplot(data_train[(data_train['tradeMoney']<=20000)]['tradeMoney'],ax=axes[0][1])
sns.distplot(data_train[(data_train['tradeMoney']>20000)&(data_train['tradeMoney']<=50000)]['tradeMoney'],ax=axes[0][2])
sns.distplot(data_train[(data_train['tradeMoney']>50000)&(data_train['tradeMoney']<=100000)]['tradeMoney'],ax=axes[1][0])
sns.distplot(data_train[(data_train['tradeMoney']>100000)]['tradeMoney'],ax=axes[1][1])
输出: