文章目录

  • 1 项目简介
  • 2 项目分析
    • 2.1 数据分析(EDA)
    • 2.2 难点分析
    • 2.3 可行性方案分析
  • 3 方案设计
    • 3.1 特征工程
    • 3.2 模型构建与训练
  • 4 结果分析
  • 5 源码链接

1 项目简介

赛题以预测二手车的交易价格为任务,数据来自某交易平台的二手车交易记录,总数据量超过40w,包含31列变量信息,其中15列为匿名变量。从中抽取15万条作为训练集,5万条作为测试集,同时对name、model、brand和regionCode等信息进行脱敏。评价标准为MAE。详情请看天池。

特征表如下所示。

2 项目分析

2.1 数据分析(EDA)

EDA是数据挖掘最基础也是最重要的一步,通过统计量分析,关联度分析等方法分析数据特征,挖掘与预测值强相关的特征,处理无用值、缺失值与异常值。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.filterwarnings('ignore')# 载入数据
train_data=pd.read_csv('../data/used_car_train_20200313.csv',sep=' ')
test_data=pd.read_csv('../data/used_car_testB_20200421.csv',sep=' ')## 简略观察数据(head()+tail()+shape)
train_data.head().append(train_data.tail())
train_data.shape
test_data.head().append(train_data.tail())
test_data.shape# describe()熟悉数据的相关统计量
train_data.describe()
test_data.describe()# info()熟悉数据类型
train_data.info()
test_data.info()# isnull().sum()查看每列nan
train_data.isnull().sum()
test_data.isnull().sum()# value_counts()查看异常值
train_data['notRepairedDamage'].value_counts()
train_data['notRepairedDamage'].replace('-',np.nan,inplace=True) # 缺失值先换为nan
train_data['notRepairedDamage'].value_counts()
train_data.isnull().sum()
test_data['notRepairedDamage'].value_counts()
test_data['notRepairedDamage'].replace('-',np.nan,inplace=True)
test_data['notRepairedDamage'].value_counts()
test_data.isnull().sum()# 删除无用值
del train_data['seller']
del test_data['seller']
del train_data['offerType']
del test_data['offerType']# 了解预测值的分布
train_data['price']
train_data['price'].value_counts()# 总体分布概况
import scipy.stats as st
y=train_data['price']
plt.figure(1)
plt.title('johnson su')
sns.distplot(y,kde=False,fit=st.johnsonsu)
plt.figure(2)
plt.title('normal')
sns.distplot(y,kde=False,fit=st.norm)
plt.figure(3)
plt.title('log normal')
sns.distplot(y,kde=False,fit=st.lognorm)# 查看偏度与峰值
sns.distplot(train_data['price'])
print('skewness:%f'%train_data['price'].skew())
print('kurtosis:%f'%train_data['price'].kurt())sns.distplot(train_data.skew(),color='blue',axlabel='skewness')
sns.distplot(train_data.kurt(),color='orange',axlabel='kurtosis')# 对数变换
plt.hist(np.log(train_data['price']),orientation='vertical',histtype='bar',color='red')
plt.show()# 下面的方法适用于没有进行特征编码的数据,这里不适用,需要人为根据实际含义来区分
# 数字特征
# numeric_features = train_data.select_dtypes(include=[np.number])
# numeric_features.columns
# 类型特征
# categorical_features = train_data.select_dtypes(include=[np.object])
# categorical_features.columns
numeric_features=['power','kilometer','v_0','v_1', 'v_2', 'v_3', 'v_4', 'v_5', 'v_6', 'v_7', 'v_8', 'v_9', 'v_10', 'v_11', 'v_12', 'v_13','v_14']
categorical_features=['name', 'model', 'brand', 'bodyType', 'fuelType', 'gearbox', 'notRepairedDamage', 'regionCode']# 数字特征分析
numeric_features.append('price')
numeric_features
# 与预测值的相关性分析
price_numeric=train_data[numeric_features]
correlation=price_numeric.corr()
print(correlation['price'].sort_values(ascending=False),'\n')
# 与预测值的相关性可视化
f,ax=plt.subplots(figsize=(7,7))
plt.title('correlation of numeric features with price',y=1,size=16)
sns.heatmap(correlation,square=True,vmax=0.8)
del price_numeric['price']
# 查看数字特征的偏度与峰值
for col in numeric_features:print('{:15}'.format(col),'skewness:{:05.2f}'.format(train_data[col].skew()),'  ','kurtosis:{:06.2f}'.format(train_data[col].kurt()))
# 数字特征的分布可视化
f=pd.melt(train_data,value_vars=numeric_features)
g=sns.FacetGrid(f,col='variable',col_wrap=2,sharex=False,sharey=False)
g=g.map(sns.distplot,'value')# 类别特征分析
# nunique分布
for feat in categorical_features:print('{}特征有{}不同的值'.format(feat,train_data[feat].nunique()))
# 类别特征的分布可视化,name与regionCode太稀疏可以不画
categorical_features=['model','brand','bodyType','fuelType','gearbox','notRepairedDamage']
# 类型转换,填充缺失值
for col in categorical_features:train_data[col]=train_data[col].astype('category')if train_data[col].isnull().any():train_data[col]=train_data[col].cat.add_categories(['MISSING'])train_data[col]=train_data[col].fillna('MISSING')def boxplot(x,y,**kwargs):sns.boxplot(x=x,y=y)x=plt.xticks(rotation=90)f=pd.melt(train_data,id_vars='price',value_vars=categorical_features)
g=sns.FacetGrid(f,col='variable',col_wrap=2,sharex=False,sharey=False,size=5)
g=g.map(boxplot,'value','price')

2.2 难点分析

  1. 利用EDA挖掘构造强相关特征
  2. 训练出融合的模型

2.3 可行性方案分析

  1. 只采用NN模型,可省略特征工程;
  2. 采用ML单模型,如xgb,lgb等,特征工程是关键;
  3. 采用模型融合

3 方案设计

3.1 特征工程

  1. 时间类特征:获取年、月等特征;
  2. 类别特征:先进行分桶,再进行特征交叉,得到其统计量数据以及峰值与偏度,构造更多特征;
  3. 匿名特征:由EDA可知,14个匿名特征分布均匀,可以保留,进行特征组合,构造更多的特征,尤其是与预测值强相关的匿名特征。
def feature_engineering(data, train_data):# 时间类特征data['regDate'] = data['regDate'].apply(date_process)data['creatDate'] = data['creatDate'].apply(date_process)data['regDate_year'] = data['regDate'].dt.yeardata['regDate_month'] = data['regDate'].dt.monthdata['regDate_day'] = data['regDate'].dt.daydata['creatDate_year'] = data['creatDate'].dt.yeardata['creatDate_month'] = data['creatDate'].dt.monthdata['creatDate_day'] = data['creatDate'].dt.daydata['car_age_day'] = (data['creatDate'] - data['regDate']).dt.daysdata['car_age_year'] = round(data['car_age_day'] / 365, 1)# 地区类特征data['regionCode_count'] = data.groupby(['regionCode'])['SaleID'].transform('count')data['city'] = data['regionCode'].apply(lambda x: str(x)[:2])# 可分类特征,进行分桶bin = [i * 10 for i in range(31)]data['power_bin'] = pd.cut(data['power'], bin, labels=False)tong = data[['power_bin', 'power']].head()bin = [i * 10 for i in range(24)]data['model_bin'] = pd.cut(data['model'], bin, labels=False)tong = data[['model_bin', 'model']].head()# 可分类特征组合,与目标特征price组合data = feature_merge(data, train_data, 'regionCode')data = feature_merge(data, train_data, 'brand')data = feature_merge(data, train_data, 'model')data = feature_merge(data, train_data, 'kilometer')data = feature_merge(data, train_data, 'bodyType')data = feature_merge(data, train_data, 'fuelType')# 其他可分类特征组合feat1 = 'regionCode'train_gb = data.groupby(feat1)infos_dic = {}for key, value in train_gb:info_dic = {}value = value[value['car_age_day'] > 0]info_dic[feat1 + '_days_max'] = value.car_age_day.max()info_dic[feat1 + '_days_min'] = value.car_age_day.min()info_dic[feat1 + '_days_mean'] = value.car_age_day.mean()info_dic[feat1 + '_days_std'] = value.car_age_day.std()info_dic[feat1 + '_days_sum'] = value.car_age_day.sum()info_dic[feat1 + '_days_median'] = value.car_age_day.median()infos_dic[key] = info_dicdf = pd.DataFrame(infos_dic).T.reset_index().rename(columns={"index": feat1})data = data.merge(df, how='left', on=feat1)train_gb = data.groupby(feat1)infos_dic = {}for key, value in train_gb:info_dic = {}value = value[value['power'] > 0]info_dic[feat1 + '_days_max'] = value.power.max()info_dic[feat1 + '_days_min'] = value.power.min()info_dic[feat1 + '_days_mean'] = value.power.mean()info_dic[feat1 + '_days_std'] = value.power.std()info_dic[feat1 + '_days_sum'] = value.power.sum()info_dic[feat1 + '_days_median'] = value.power.median()infos_dic[key] = info_dicdf = pd.DataFrame(infos_dic).T.reset_index().rename(columns={"index": feat1})data = data.merge(df, how='left', on=feat1)# 匿名特征组合feat2 = 'v_3'train_gb = data.groupby(feat1)infos_dic = {}for key, value in train_gb:info_dic = {}value = value[value[feat2] > -10000000]info_dic[feat1 + '_' + feat2 + '_max'] = value.v_3.max()info_dic[feat1 + '_' + feat2 + '_min'] = value.v_3.min()info_dic[feat1 + '_' + feat2 + '_mean'] = value.v_3.mean()info_dic[feat1 + '_' + feat2 + '_std'] = value.v_3.std()info_dic[feat1 + '_' + feat2 + '_sum'] = value.v_3.sum()info_dic[feat1 + '_' + feat2 + '_median'] = value.v_3.median()infos_dic[key] = info_dicdf = pd.DataFrame(infos_dic).T.reset_index().rename(columns={'index': feat1})data = data.merge(df, how='left', on=feat1)feat3 = 'v_0'train_gb = data.groupby(feat1)infos_dic = {}for key, value in train_gb:info_dic = {}value = value[value[feat3] > -10000000]info_dic[feat1 + '_' + feat3 + '_max'] = value.v_0.max()info_dic[feat1 + '_' + feat3 + '_min'] = value.v_0.min()info_dic[feat1 + '_' + feat3 + '_mean'] = value.v_0.mean()info_dic[feat1 + '_' + feat3 + '_std'] = value.v_0.std()info_dic[feat1 + '_' + feat3 + '_sum'] = value.v_0.sum()info_dic[feat1 + '_' + feat3 + '_median'] = value.v_0.median()infos_dic[key] = info_dicdf = pd.DataFrame(infos_dic).T.reset_index().rename(columns={'index': feat1})data = data.merge(df, how='left', on=feat1)# 特征交叉,针对匿名特征及重要性高的可分类特征for i in range(15):for j in range(15):data['new' + str(i) + '*' + str(j)] = data['v_' + str(i)] * data['v_' + str(j)]for i in range(15):for j in range(15):data['new' + str(i) + '+' + str(j)] = data['v_' + str(i)] + data['v_' + str(j)]for i in range(15):data['new' + str(i) + '*power'] = data['v_' + str(i)] * data['power']for i in range(15):data['new' + str(i) + '*day'] = data['v_' + str(i)] * data['car_age_day']for i in range(15):data['new' + str(i) + '*year'] = data['v_' + str(i)] * data['car_age_year']return data

3.2 模型构建与训练

本项目最终选择lgb+catb+nn。采用正则化,早停法,10折交叉验证等方法防止过拟合,训练模型。

def final_model(x_train_tree, x_test_tree, y_train_tree, x_train_nn, x_test_nn, y_train_nn):# lgbm模型predictions_lgbm, oof_lgbm = lgbm_model(x_train_tree, x_test_tree, y_train_tree)# catb模型predictions_catb, oof_catb = catb_model(x_train_tree, x_test_tree, y_train_tree)# 树模型stackpredictions_tree, oof_tree = stack_model(predictions_lgbm, predictions_catb, oof_lgbm, oof_catb, y_train_tree)# nn模型predictions_nn, oof_nn = nn_model(x_train_nn, x_test_nn, y_train_nn)# nn模型+树模型stackpredictions = (predictions_tree + predictions_nn) / 2oof = (oof_tree + oof_nn) / 2point = mean_absolute_error(oof, np.expm1(y_train_nn))print("final model mae:{:<8.8f}".format(point))return predictions

4 结果分析

线上MAE为405.67,与SOTA有一定差距,个人认为可以从特征工程做优化,挖掘更多强相关的特征。

5 源码链接

Github

【竞赛项目详解】二手车交易价格预测(附源码)相关推荐

  1. 基于ssm二手车交易管理系统毕业设计-附源码151159

    摘  要 随着社会的发展,社会的各行各业都在利用信息时代的优势.计算机的优势和普及使得各种信息系统的开发成为必需. 二手车交易管理系统,主要的模块包括用户.卖家.管理员,用户功能包括:首页.个人资料. ...

  2. jsp+ssm二手车交易管理系统 毕业设计-附源码151159

     基于ssm二手车交易管理系统 摘  要 随着社会的发展,社会的各行各业都在利用信息时代的优势.计算机的优势和普及使得各种信息系统的开发成为必需. 二手车交易管理系统,主要的模块包括用户.卖家.管理员 ...

  3. 2023新版图文详解SpringBoot整合SSM框架(附源码)

    版权声明 本文原创作者:谷哥的小弟 作者博客地址:http://blog.csdn.net/lfdfhl 教程概述 本教程以图文形式详细讲解SpringBoot整合SSM框架的流程以及具体步骤及其注意 ...

  4. 【Python机器学习】聚类算法任务,评价指标SC、DBI、ZQ等系数详解和实战演示(附源码 图文解释)

    需要源码和数据集请点赞关注收藏后评论区留言私信~~~ 一.聚类任务 设样本集S={x_1,x_2,-,x_m}包含m个未标记样本,样本x_i=(x_i^(1),x_i^(2),-,x_i^(n))是一 ...

  5. 【算法竞赛学习】二手车交易价格预测-Baseline

    二手车交易价格预测-Baseline Baseline-v1.0 版 Tip:这是一个最初始baseline版本,抛砖引玉,为大家提供一个基本Baseline和一个竞赛流程的基本介绍,欢迎大家多多交流 ...

  6. 【算法竞赛学习】二手车交易价格预测-Task1赛题理解

    二手车交易价格预测-Task1 赛题理解 一. 赛题理解 Tip:此部分为零基础入门数据挖掘的 Task1 赛题理解 部分,为大家入门数据挖掘比赛提供一个基本的赛题入门讲解,欢迎后续大家多多交流. 赛 ...

  7. 【算法竞赛学习】二手车交易价格预测-Task5模型融合

    二手车交易价格预测-Task5 模型融合 五.模型融合 Tip:此部分为零基础入门数据挖掘的 Task5 模型融合 部分,带你来了解各种模型结果的融合方式,在比赛的攻坚时刻冲刺Top,欢迎大家后续多多 ...

  8. 【算法竞赛学习】二手车交易价格预测-Task4建模调参

    二手车交易价格预测-Task4 建模调参 四.建模与调参 Tip:此部分为零基础入门数据挖掘的 Task4 建模调参 部分,带你来了解各种模型以及模型的评价和调参策略,欢迎大家后续多多交流. 赛题:零 ...

  9. 【算法竞赛学习】二手车交易价格预测-Task3特征工程

    二手车交易价格预测-Task3 特征工程 三. 特征工程目标 Tip:此部分为零基础入门数据挖掘的 Task3 特征工程部分,带你来了解各种特征工程以及分析方法,欢迎大家后续多多交流. 赛题:零基础入 ...

最新文章

  1. iOS 本地时间与GMT时间相互转换
  2. python实现八皇后问题(百练OJ:2754:八皇后)
  3. 误删了公司数据库,但我还是活下来了
  4. Aix vmstat命令解析
  5. @keyframes关键帧动画(animation)
  6. Django Signal 代码布局
  7. C语言中的面向对象2
  8. sap模块介绍_一分钟掌握SAP小知识-系统基本操作
  9. java json 图片_图片路径存储且item的json化
  10. 翻译:响应式编程或反应式编程 RxSwift和RxCocoa 从入门到精通 Reactive programming
  11. MQL5 COOKBOOK - 以 MQL5 编写的多币种 EA,利用限价订单工作
  12. R语言从github安装recharts包
  13. 2022-2028全球虚拟现实游戏头戴设备行业调研及趋势分析报告
  14. CoolWeather地区无法加载
  15. 树莓派设置自动连接无线网络
  16. UEFI启动视频详解:启动分析+N项操作实例
  17. 移动端图片剪裁工具cropperjs
  18. spoolsv病毒的清除
  19. 同创伟业王维:行业泡沫期易诞生伟大公司
  20. Python:王老先生有块地

热门文章

  1. csv转为utf8编码_中文的csv文件的编码改成utf8的方法
  2. 如何将屏幕截图从Nintendo Switch传输到计算机
  3. underflow, overflow, approximation and rounding error
  4. 什么样的员工容易被提拔为管理者,他们有哪些共同特质?
  5. MS coco数据集下载链接
  6. 【location】将url参数转换为对象的形式
  7. 对于多组数据输入输出的基础题目
  8. 树莓派-1、上手及资源
  9. vue二级路由和重定向问题
  10. 实现两直角坐标系转换