Datawhale &天池二手车交易价格预测— Task1 赛题理解 +Task2 数据分析

Datawhale &天池 二手车交易价格预测— Task1 赛题理解 +Task2 数据分析

1 赛题理解

二手车交易价格预测是Datawhale与天池联合发起的0基础入门系列赛事第一场 —— 零基础入门数据挖掘之二手车交易价格预测大赛。

1.1 比赛目的

赛题以二手车市场为背景,要求选手预测二手汽车的交易价格,这是一个典型的回归问题。通过这道赛题来引导大家走进AI数据竞赛的世界,主要针对于于竞赛新人进行自我练习、自我提高。

赛题目的是从已知15万条二手汽车的交易价格信息(每条二手车信息包含31项变量信息),想解决测试集对应二手汽车的交易价格预测。

1.2 相关评价指标

评价标准为MAE(Mean Absolute Error),即平均绝对值误差,它表示预测值和观测值之间绝对误差的平均值。这是一种常见的评价指标。
在这里插入图片描述
事实上,MAE越小,说明模型预测得越准确。在训练模型时可以借助sklearn中已有的MAE评测来检验自己模型对测试集拟合的效果,源代码如下:

# coding=utf-8
import numpy as np
#调用sklearn中的MAE
from sklearn import metrics
#定义自己编写的MAE评价指标
def test_mae(y_true, y_pred):
    mae_value = np.mean(np.abs(y_pred - y_true))
    return mae_value
#下面分别测试自己编写的MAE评价指标和sklearn的MAE评价指标
y_true = np.array([1.0, 5.0, 4.0, 3.0, 2.0, 5.0, -3.0])
y_pred = np.array([1.0, 4.5, 3.8, 3.2, 3.0, 4.8, -2.2])
print('test_MAE:',test_mae(y_true, y_pred))
print('sklearn_MAE:',metrics.mean_absolute_error(y_true, y_pred))
#test_MAE: 0.4142857142857143
#sklearn_MAE: 0.4142857142857143

2 数据分析

赛题以预测二手车的交易价格为任务,数据集报名后可见并可下载,该数据来自某交易平台的二手车交易记录,总数据量超过40w,包含31列变量信息,其中15列为匿名变量。为了保证比赛的公平性,将会从中抽取15万条作为训练集,5万条作为测试集A,5万条作为测试集B,同时会对name、model、brand和regionCode等信息进行脱敏。

2.1 EDA简介

EDA是指对已有的数据(尤其是调查或观察得来的原始数据)在尽量少的先验假定下进行探索,通过作图、制表、方程拟合、计算特征量等手段探索数据的结构和规律的一种数据分析方法。特别是当我们面对各种杂乱的“脏数据”,往往不知所措,不知道从哪里开始了解目前拿到手上的数据时,探索性数据分析就非常有效。探索性数据分析是美国统计学家John Tukey在20世纪60年代提出的。
EDA的价值主要在于熟悉数据集,了解数据集,对数据集进行验证来确定所获得数据集可以用于接下来的机器学习或者深度学习使用。
当了解了数据集之后,下一步就是要去了解变量间的相互关系以及变量与预测值之间的存在关系。
引导数据科学从业者进行数据处理以及特征工程的步骤,使数据集的结构和特征集让接下来的预测问题更加可靠。
通过完成对于数据的探索性分析,并对于数据进行一些图表或者文字总结并打卡。

2.2 主要工作

2.2.1 导入相关函数工具箱

## 基础工具
import numpy as np
import pandas as pd
import warnings
import matplotlib
import matplotlib.pyplot as plt
import seaborn as sns
from scipy.special import jn
from IPython.display import display, clear_output
import time
## 导入warnings包,利用过滤器来实现忽略警告语句。
warnings.filterwarnings('ignore')

## 模型预测的
from sklearn import linear_model
from sklearn import preprocessing
from sklearn.svm import SVR
from sklearn.ensemble import RandomForestRegressor,GradientBoostingRegressor
## 数据降维处理的
from sklearn.decomposition import PCA,FastICA,FactorAnalysis,SparsePCA
import lightgbm as lgb
import xgboost as xgb
## 参数搜索和评价的
from sklearn.model_selection import GridSearchCV,cross_val_score,StratifiedKFold,train_test_split
from sklearn.metrics import mean_squared_error, mean_absolute_error

2.2.2 读取数据(csv文件,训练数据和测试数据)

## 通过Pandas对于数据进行读取 (pandas是一个很友好的数据读取函数库)
Traindata = pd.read_csv('datalab/231784/used_car_train_20200313.csv', sep=' ')
Testdata = pd.read_csv('datalab/231784/used_car_testA_20200313.csv', sep=' ')
## 输出数据的大小信息
print('Train data shape:',Traindata.shape)
print('Test data shape:',Testdata.shape)

Train data shape: (150000, 31)
Test data shape: (50000, 30)

2.2.3 数据简要浏览

## 通过.head() 简要浏览读取数据的形式
Traindata.head()

在这里插入图片描述

## 通过 .info() 简要可以看到对应一些数据列名,以及NAN缺失信息
Traindata.info()

在这里插入图片描述

## 通过 .columns 查看列名
Traindata.columns

在这里插入图片描述

Testdata.info()

在这里插入图片描述
2.2.4 相关字符对应含义
在这里插入图片描述
2.2.5 观察数据概况

## 通过 .describe() 可以查看数值特征列的一些统计信息
Traindata.describe()

在这里插入图片描述

Testdata.describe()

在这里插入图片描述

#观察除匿名特征外的数据概况
Traindata.describe().iloc[:,:15]

发现表格中offerType特征中数据全为0,很可能是一项无用的特征。seller中均值很小,而且第三分位点和最大值不同,说明存在一定数据倾斜。power中出现异常值在这里插入图片描述
2.2.6 判断数据缺失—查看每列的存在nan情况

Traindata.isnull().sum()

在这里插入图片描述

Testdata.isnull().sum()

在这里插入图片描述
2.2.7 可视化

missing = Traindata.isnull().sum()
missing = missing[missing > 0]#筛选出有缺失值的数据行
missing.sort_values(inplace=True)#排序
missing.plot.bar()#柱状图

在这里插入图片描述
通过以下代码可以很直观的了解哪些列存在 “nan”, 并可以把nan的个数打印,主要的目的在于 nan存在的个数是否真的很大,如果很小一般选择填充,但如果nan存在的过多、可以考虑删掉。

import missingno as msno
msno.matrix(Traindata.sample(250))#可看到每个变量的缺失情况

在这里插入图片描述

msno.bar(Traindata)#条形图可以更直观的看出每个变量缺失的比例和数量情况

在这里插入图片描述
测试数据同理

missing = Testdata.isnull().sum()
missing = missing[missing > 0]#筛选出有缺失值的数据行
missing.sort_values(inplace=True)#排序
missing.plot.bar()#柱状图

在这里插入图片描述

msno.matrix(Testdata.sample(250))#可看到每个变量的缺失情况

在这里插入图片描述

msno.bar(Testdata)#条形图可以更直观的看出每个变量缺失的比例和数量情况

在这里插入图片描述
2.2.8 判断数据异常
由info方法输出数据类型中发现除了notRepairedDamage 为object类型,其他都为数字,这里把这列的的不同值显示。

Traindata['notRepairedDamage'].value_counts()

在这里插入图片描述

Testdata['notRepairedDamage'].value_counts()

在这里插入图片描述
由于‘ - ’为空缺值,很多模型对nan有直接的处理,可以将‘ - ’替换成nan

Traindata['notRepairedDamage'].replace('-', np.nan, inplace=True)
Testdata['notRepairedDamage'].replace('-', np.nan, inplace=True)
Traindata["seller"].value_counts()

0 149999
1 1
Name: seller, dtype: int64

Traindata["offerType"].value_counts()

0 150000
Name: offerType, dtype: int64
由于两个类别特征严重倾斜,一般不会对预测有什么帮助,故删掉

del Traindata["seller"]
del Traindata["offerType"]
del Testdata["seller"]
del Testdata["offerType"]

2.2.9 了解预测值的分布
1)总体分布概况(无界约翰逊分布等)

import scipy.stats as st
y = Traindata['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)

在这里插入图片描述
由于价格不服从正态分布,因此在进行回归之前,它必须进行转换。虽然对数变换做得很好,但最佳拟合是无界约翰逊分布
2)查看数据的偏度和峰度

sns.distplot(Traindata['price']);
print("Skewness: %f" % Traindata['price'].skew())
print("Kurtosis: %f" % Traindata['price'].kurt())

在这里插入图片描述
Skewness > 0 ,正偏差数值较大,为正偏或右偏。长尾巴拖在右边,数据右端有较多的极端值。Kurtosis>0 比正态分布的高峰更加陡峭——尖顶峰。
3)查看预测值的具体频数

plt.hist(Traindata['price'], orientation = 'vertical',histtype = 'bar', color ='red')
plt.show()

在这里插入图片描述
查看频数, 发现大于20000得值极少,即将这些当作特殊得值(异常值)直接用填充或者删掉。
4) log变换之后的分布较均匀,可以进行log变换进行预测

plt.hist(np.log(Traindata['price']), orientation = 'vertical',histtype = 'bar', color ='red') 
plt.show()

在这里插入图片描述
2.2.10 特征分为类别特征和数字特征
对类别特征查看unique分布

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']
# 特征nunique分布
for cat_fea in categorical_features:
    print(cat_fea + "的特征分布如下:")
    print("{}特征有个{}不同的值".format(cat_fea, Traindata[cat_fea].nunique()))
    print(Traindata[cat_fea].value_counts())

name的特征分布如下:
name特征有个99662不同的值
708 282
387 282
55 280
1541 263
203 233
53 221
713 217
290 197
1186 184
911 182
2044 176
1513 160
1180 158
631 157
893 153
2765 147
473 141
1139 137
1108 132
444 129
306 127
2866 123
2402 116
533 114
1479 113
422 113
4635 110
725 110
964 109
1373 104

89083 1
95230 1
164864 1
173060 1
179207 1
181256 1
185354 1
25564 1
19417 1
189324 1
162719 1
191373 1
193422 1
136082 1
140180 1
144278 1
146327 1
148376 1
158621 1
1404 1
15319 1
46022 1
64463 1
976 1
3025 1
5074 1
7123 1
11221 1
13270 1
174485 1
Name: name, Length: 99662, dtype: int64
model的特征分布如下:
model特征有个248不同的值
0.0 11762
19.0 9573
4.0 8445
1.0 6038
29.0 5186
48.0 5052
40.0 4502
26.0 4496
8.0 4391
31.0 3827
13.0 3762
17.0 3121
65.0 2730
49.0 2608
46.0 2454
30.0 2342
44.0 2195
5.0 2063
10.0 2004
21.0 1872
73.0 1789
11.0 1775
23.0 1696
22.0 1524
69.0 1522
63.0 1469
7.0 1460
16.0 1349
88.0 1309
66.0 1250

141.0 37
133.0 35
216.0 30
202.0 28
151.0 26
226.0 26
231.0 23
234.0 23
233.0 20
198.0 18
224.0 18
227.0 17
237.0 17
220.0 16
230.0 16
239.0 14
223.0 13
236.0 11
241.0 10
232.0 10
229.0 10
235.0 7
246.0 7
243.0 4
244.0 3
245.0 2
209.0 2
240.0 2
242.0 2
247.0 1
Name: model, Length: 248, dtype: int64
brand的特征分布如下:
brand特征有个40不同的值
0 31480
4 16737
14 16089
10 14249
1 13794
6 10217
9 7306
5 4665
13 3817
11 2945
3 2461
7 2361
16 2223
8 2077
25 2064
27 2053
21 1547
15 1458
19 1388
20 1236
12 1109
22 1085
26 966
30 940
17 913
24 772
28 649
32 592
29 406
37 333
2 321
31 318
18 316
36 228
34 227
33 218
23 186
35 180
38 65
39 9
Name: brand, dtype: int64
bodyType的特征分布如下:
bodyType特征有个8不同的值
0.0 41420
1.0 35272
2.0 30324
3.0 13491
4.0 9609
5.0 7607
6.0 6482
7.0 1289
Name: bodyType, dtype: int64
fuelType的特征分布如下:
fuelType特征有个7不同的值
0.0 91656
1.0 46991
2.0 2212
3.0 262
4.0 118
5.0 45
6.0 36
Name: fuelType, dtype: int64
gearbox的特征分布如下:
gearbox特征有个2不同的值
0.0 111623
1.0 32396
Name: gearbox, dtype: int64
notRepairedDamage的特征分布如下:
notRepairedDamage特征有个2不同的值
0.0 111361
1.0 14315
Name: notRepairedDamage, dtype: int64
regionCode的特征分布如下:
regionCode特征有个7905不同的值
419 369
764 258
125 137
176 136
462 134
428 132
24 130
1184 130
122 129
828 126
70 125
827 120
207 118
1222 117
2418 117
85 116
2615 115
2222 113
759 112
188 111
1757 110
1157 109
2401 107
1069 107
3545 107
424 107
272 107
451 106
450 105
129 105

6324 1
7372 1
7500 1
8107 1
2453 1
7942 1
5135 1
6760 1
8070 1
7220 1
8041 1
8012 1
5965 1
823 1
7401 1
8106 1
5224 1
8117 1
7507 1
7989 1
6505 1
6377 1
8042 1
7763 1
7786 1
6414 1
7063 1
4239 1
5931 1
7267 1
Name: regionCode, Length: 7905, dtype: int64

2.2.11 数字特征分析
1)相关性分析

numeric_features.append('price')
price_numeric = Traindata[numeric_features]
correlation = price_numeric.corr()
print(correlation['price'].sort_values(ascending = False),'\n')#输出各个变量与价格的相关性

price 1.000000
v_12 0.692823
v_8 0.685798
v_0 0.628397
power 0.219834
v_5 0.164317
v_2 0.085322
v_6 0.068970
v_1 0.060914
v_14 0.035911
v_13 -0.013993
v_7 -0.053024
v_4 -0.147085
v_9 -0.206205
v_10 -0.246175
v_11 -0.275320
kilometer -0.440519
v_3 -0.730946
Name: price, dtype: float64

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)

在这里插入图片描述

2)查看几个特征的偏度和峰值

for col in numeric_features:
    print('{:15}'.format(col), 
          'Skewness: {:05.2f}'.format(Traindata[col].skew()) , 
          '   ' ,
          'Kurtosis: {:06.2f}'.format(Traindata[col].kurt())  
         )

power Skewness: 65.86 Kurtosis: 5733.45
kilometer Skewness: -1.53 Kurtosis: 001.14
v_0 Skewness: -1.32 Kurtosis: 003.99
v_1 Skewness: 00.36 Kurtosis: -01.75
v_2 Skewness: 04.84 Kurtosis: 023.86
v_3 Skewness: 00.11 Kurtosis: -00.42
v_4 Skewness: 00.37 Kurtosis: -00.20
v_5 Skewness: -4.74 Kurtosis: 022.93
v_6 Skewness: 00.37 Kurtosis: -01.74
v_7 Skewness: 05.13 Kurtosis: 025.85
v_8 Skewness: 00.20 Kurtosis: -00.64
v_9 Skewness: 00.42 Kurtosis: -00.32
v_10 Skewness: 00.03 Kurtosis: -00.58
v_11 Skewness: 03.03 Kurtosis: 012.57
v_12 Skewness: 00.37 Kurtosis: 000.27
v_13 Skewness: 00.27 Kurtosis: -00.44
v_14 Skewness: -1.19 Kurtosis: 002.39
price Skewness: 03.35 Kurtosis: 019.00

3)每个数字特征分布可视化

f = pd.melt(Traindata, value_vars=numeric_features)
g = sns.FacetGrid(f, col="variable",  col_wrap=2, sharex=False, sharey=False)
g = g.map(sns.distplot, "value")

在这里插入图片描述
从 上图中可以看出匿名特征相对分布均匀。
4)数字特征相互之间的关系可视化

sns.set()
columns = ['price', 'v_12', 'v_8' , 'v_0', 'power', 'v_5',  'v_2', 'v_6', 'v_1', 'v_14']
sns.pairplot(Traindata[columns],size = 2 ,kind ='scatter',diag_kind='kde')
plt.show()

在这里插入图片描述
测试数据同理

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值