数据挖掘

2020-03-23  本文已影响0人  一技破万法

预测指标

分类常见的评估指标:
对于二类分类器/分类算法,评价指标主要有accuracy, [Precision,Recall,F-score,Pr曲线],ROC-AUC曲线。
对于多类分类器/分类算法,评价指标主要有accuracy, [宏平均和微平均,F-score]。
回归预测类常见的评估指标:
平均绝对误差(Mean Absolute Error, MAE):
MAE = \dfrac{1}{N}\sum_{i=1}^{N}|y_i - \hat{y}_i| \tag 1
均方误差(Mean Squared Error, MSE):
MSE = \dfrac{1}{N}\sum_{i=1}^{N}(y_i - \hat{y}_i)^2 \tag 2
R-Square(R2):

残差平方和:
SS_{res} = \sum (y_i - \bar{y}_i)^2 \tag 3
总平均值:
SS_{tot} = \sum (y_i - \bar{y}_i)^2 \tag 4
R2表达式:
R^2 = 1-\dfrac{SS_{res}}{SS_{tot}} = 1 - \dfrac{\sum(y_i - \hat{y}_i)^2}{(y_i - \bar{y})^2} \tag 5
R2用于度量因变量的变异中可由自变量解释部分所占的比例,取值范围是 0~1,R2越接近1,表明回归平方和占总平方和的比例越大,回归线与各观测点越接近,用x的变化来解释y值变化的部分就越多,回归的拟合程度就越好。所以R2也称为拟合优度(Goodness of Fit)的统计量。

代码示例

数据读取pandas
import pandas as pd
import numpy as np

## 1) 载入训练集和测试集;
path = './datalab/231784/'
Train_data = pd.read_csv(path+'used_car_train_20200313.csv', sep=' ')
Test_data = pd.read_csv(path+'used_car_testA_20200313.csv', sep=' ')

print('Train data shape:',Train_data.shape)
print('TestA data shape:',Test_data.shape)
Train_data.head()
分类指标评价计算
## accuracy
import numpy as np
from sklearn.metrics import accuracy_score
y_pred = [0, 1, 0, 1]
y_true = [0, 1, 1, 1]
print('ACC:',accuracy_score(y_true, y_pred))
## Precision,Recall,F1-score
from sklearn import metrics
y_pred = [0, 1, 0, 0]
y_true = [0, 1, 0, 1]
print('Precision',metrics.precision_score(y_true, y_pred))
print('Recall',metrics.recall_score(y_true, y_pred))
print('F1-score:',metrics.f1_score(y_true, y_pred))
## AUC
import numpy as np
from sklearn.metrics import roc_auc_score
y_true = np.array([0, 0, 1, 1])
y_scores = np.array([0.1, 0.4, 0.35, 0.8])
print('AUC socre:',roc_auc_score(y_true, y_scores))

结果如下:

ACC: 0.75
Precision 1.0
Recall 0.5
F1-score: 0.6666666666666666
AUC socre: 0.75
回归指标评价计算
# coding=utf-8
import numpy as np
from sklearn import metrics

# MAPE需要自己实现
def mape(y_true, y_pred):
    return np.mean(np.abs((y_pred - y_true) / y_true))

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])

# MSE
print('MSE:',metrics.mean_squared_error(y_true, y_pred))
# RMSE
print('RMSE:',np.sqrt(metrics.mean_squared_error(y_true, y_pred)))
# MAE
print('MAE:',metrics.mean_absolute_error(y_true, y_pred))
# MAPE
print('MAPE:',mape(y_true, y_pred))
## R2-score
from sklearn.metrics import r2_score
y_true = [3, -0.5, 2, 7]
y_pred = [2.5, 0.0, 2, 8]
print('R2-score:',r2_score(y_true, y_pred))

测试结果

MSE: 0.2871428571428571
RMSE: 0.5358571238146014
MAE: 0.4142857142857143
MAPE: 0.1461904761904762
R2-score:0.948608137045

数据分析

EDA-数据探索性分析

  1. 载入各种数据科学以及可视化库:
    *数据科学库 pandas、numpy、scipy;
    *可视化库 matplotlib、seabon;
    *其他;
  2. 载入数据:
    *载入训练集和测试集;
    *简略观察数据(head()+shape);
  3. 数据总览:
    *通过describe()来熟悉数据的相关统计量
    *通过info()来熟悉数据类型
  4. 判断数据缺失和异常
    *查看每列的存在nan情况
    *异常值检测
  5. 了解预测值的分布
    *总体分布概况(无界约翰逊分布等)
    *查看skewness and kurtosis
    *查看预测值的具体频数
  6. 特征分为类别特征和数字特征,并对类别特征查看unique分布
  7. 数字特征分析
    *相关性分析
    *查看几个特征得 偏度和峰值
    *每个数字特征得分布可视化
    *数字特征相互之间的关系可视化
    *多变量互相回归关系可视化
  8. 类型特征分析
    *unique分布
    *类别特征箱形图可视化
    *类别特征的小提琴图可视化
    *类别特征的柱形图可视化类别
    *特征的每个类别频数可视化(count_plot)
  9. 用pandas_profiling生成数据报告

代码示例

载入各种数据科学以及可视化库
import warnings
warnings.filterwarnings('ignore')

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import missingno as msno
载入数据
## 1) 载入训练集和测试集;
path = './datalab/231784/'
Train_data = pd.read_csv(path+'used_car_train_20200313.csv', sep=' ')
Test_data = pd.read_csv(path+'used_car_testA_20200313.csv', sep=' ')
## 2) 简略观察数据(head()+shape)
Train_data.head(n=7).append(Train_data.tail())#pandas里面的tail函数,就是添加最后几行,默认n等于5
print(Train_data.shape)

执行结果:

        SaleID    name   regDate  model  brand  ...      v_10      v_11      v_12      v_13      v_14
0            0     736  20040402   30.0      6  ... -2.881803  2.804097 -2.420821  0.795292  0.914762
1            1    2262  20030301   40.0      1  ... -4.900482  2.096338 -1.030483 -1.722674  0.245522
2            2   14874  20040403  115.0     15  ... -4.846749  1.803559  1.565330 -0.832687 -0.229963
3            3   71865  19960908  109.0     10  ... -4.509599  1.285940 -0.501868 -2.438353 -0.478699
4            4  111080  20120103  110.0      5  ... -1.896240  0.910783  0.931110  2.834518  1.923482
5            5  137642  20090602   24.0     10  ...  1.885526 -2.721943  2.457660 -0.286973  0.206573
6            6    2402  19990411   13.0      4  ... -4.902200  1.610616 -0.834605 -1.996117 -0.103180
149995  149995  163978  20000607  121.0     10  ...  1.988114 -2.983973  0.589167 -1.304370 -0.302592
149996  149996  184535  20091102  116.0     11  ...  1.839166 -2.774615  2.553994  0.924196 -0.272160
149997  149997  147587  20101003   60.0     11  ...  2.439812 -1.630677  2.290197  1.891922  0.414931
149998  149998   45907  20060312   34.0     10  ...  2.075380 -2.633719  1.414937  0.431981 -1.659014
149999  149999  177672  19990204   19.0     28  ...  1.978453 -3.179913  0.031724 -1.483350 -0.342674

[12 rows x 31 columns]
(150000, 31)

养成看数据集的head()习惯以及shape,确保了解数据集的组成。

总览数据概况

describe函数可以描述每一列的个数count、平均值mean、方差std、最小值min、中位数25%、50%、75%、以及最大值max。通过这个表格可以掌握数据的大概的范围以及异常值的判断。

Train_data.describe()

运行结果:

              SaleID           name       regDate          model  ...           v_11           v_12           v_13           v_14
count  150000.000000  150000.000000  1.500000e+05  149999.000000  ...  150000.000000  150000.000000  150000.000000  150000.000000
mean    74999.500000   68349.172873  2.003417e+07      47.129021  ...       0.009035       0.004813       0.000313      -0.000688
std     43301.414527   61103.875095  5.364988e+04      49.536040  ...       3.286071       2.517478       1.288988       1.038685
min         0.000000       0.000000  1.991000e+07       0.000000  ...      -5.558207      -9.639552      -4.153899      -6.546556
25%     37499.750000   11156.000000  1.999091e+07      10.000000  ...      -1.951543      -1.871846      -1.057789      -0.437034
50%     74999.500000   51638.000000  2.003091e+07      30.000000  ...      -0.358053      -0.130753      -0.036245       0.141246
75%    112499.250000  118841.250000  2.007111e+07      66.000000  ...       1.255022       1.776933       0.942813       0.680378
max    149999.000000  196812.000000  2.015121e+07     247.000000  ...      18.819042      13.847792      11.147669       8.658418

[8 rows x 30 columns]

info函数可以了解数据每列的type,有助于了解是否存在除了nan以外的特殊符号异常。

Train_data.info()

运行结果:

---  ------             --------------   -----  
 0   SaleID             150000 non-null  int64  
 1   name               150000 non-null  int64  
 2   regDate            150000 non-null  int64  
 3   model              149999 non-null  float64
 4   brand              150000 non-null  int64  
 5   bodyType           145494 non-null  float64
 6   fuelType           141320 non-null  float64
 7   gearbox            144019 non-null  float64
 8   power              150000 non-null  int64  
 9   kilometer          150000 non-null  float64
 10  notRepairedDamage  150000 non-null  object 
 11  regionCode         150000 non-null  int64  
 12  seller             150000 non-null  int64  
 13  offerType          150000 non-null  int64  
 14  creatDate          150000 non-null  int64  
 15  price              150000 non-null  int64  
 16  v_0                150000 non-null  float64
 17  v_1                150000 non-null  float64
 18  v_2                150000 non-null  float64
 19  v_3                150000 non-null  float64
 20  v_4                150000 non-null  float64
 21  v_5                150000 non-null  float64
 22  v_6                150000 non-null  float64
 23  v_7                150000 non-null  float64
 24  v_8                150000 non-null  float64
 25  v_9                150000 non-null  float64
 26  v_10               150000 non-null  float64
 27  v_11               150000 non-null  float64
 28  v_12               150000 non-null  float64
 29  v_13               150000 non-null  float64
 30  v_14               150000 non-null  float64
dtypes: float64(20), int64(10), object(1)
memory usage: 35.5+ MB
判断数据缺失和异常
## 1) 查看每列的存在nan情况
print(Train_data.isnull().sum())
# nan可视化
missing = Train_data.isnull().sum()
missing = missing[missing > 0]
missing.sort_values(inplace=True)
missing.plot.bar()
msno.matrix(Train_data.sample(250))
plt.show()

运行结果:

SaleID                  0
name                    0
regDate                 0
model                   1
brand                   0
bodyType             4506
fuelType             8680
gearbox              5981
power                   0
kilometer               0
notRepairedDamage       0
regionCode              0
seller                  0
offerType               0
creatDate               0
price                   0
v_0                     0
v_1                     0
v_2                     0
v_3                     0
v_4                     0
v_5                     0
v_6                     0
v_7                     0
v_8                     0
v_9                     0
v_10                    0
v_11                    0
v_12                    0
v_13                    0
v_14                    0
dtype: int64
nan可视化

[图片上传失败...(image-52e663-1585054900291)]

bar

通过以上nan可视化可以很直观地了解哪些列存在缺省值,主要的目的在于nan存在的个数是否真的很大,如果很小的话一般选择填充,如果使用lgb等树模型可以直接空缺,让树自己去优化,但如果nan存在的过多、可以考虑删掉。
在上面查看异常值缺省时,除了notRepairedDamage为object类型其他都为数字,下面我们将这一项里面的不同的值显示一下:

print(Train_data['notRepairedDamage'].value_counts())

显示结果:

0.0    111361
-       24324
1.0     14315
Name: notRepairedDamage, dtype: int64

其中’_‘也是缺省值,这里我们先替换成nan

Train_data['notRepairedDamage'].replace('_', np.nan, inplace = True)
print(Train_data['notRepairedDamage'].value_counts())
print(Train_data.isnull().sum())#判断缺省值

删除特征倾斜严重的类别

del Train_data['seller']
del Train_date['offerType']
了解预测值的分布
print(Train_date['price'].value_counts())
## 1) 总体分布概况(无界约翰逊分布等)
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)

结果如下:

500      2337
1500     2158
1200     1922
1000     1850
2500     1821
         ... 
25321       1
8886        1
8801        1
37920       1
8188        1
Name: price, Length: 3763, dtype: int64

[图片上传失败...(image-ac795-1585054900291)]
价格不服从正态分布,所以在进行回归之前,它必须进行转换。

对于线性回归模型,当因变量

## 2) 查看skewness and kurtosis
plt.figure(1)
sns.distplot(Train_data['price']);
print("Skewness: %f" % Train_data['price'].skew())
print("Kurtosis: %f" % Train_data['price'].kurt())
plt.figure(2)
sns.distplot(Train_data.skew(),color='blue',axlabel ='Skewness')
plt.figure(3)
sns.distplot(Train_data.kurt(),color='orange',axlabel ='Kurtness')
plt.show()

#运行结果
Skewness: 3.346487
Kurtosis: 18.995183
image

skewness表示偏度,描述的是总体取值分布的对称性,是由三阶中心距计算出来的。
kurtosis表示峰度,描述的是数据分布顶的尖锐程度,是由四阶标准距计算出来的

## 3) 查看预测值的具体频数
plt.hist(Train_data['price'], orientation = 'vertical',histtype = 'bar', color ='red')
plt.show()

[图片上传失败...(image-e2da3e-1585054900291)]
查看频数,大于20000的值极少,然后将它进行log变换试一下。

# log变换 z之后的分布较均匀,可以进行log变换进行预测,这也是预测问题常用的trick
plt.hist(np.log(Train_data['price']), orientation = 'vertical',histtype = 'bar', color ='red') 
plt.show()

image
特征分为类别特征和数字特征,并对类别特征查看unique分布

数据类型:

name - 汽车编码
regDate - 汽车注册时间
model - 车型编码
brand - 品牌
bodyType - 车身类型
fuelType - 燃油类型
gearbox - 变速箱
power - 汽车功率
kilometer - 汽车行驶公里
notRepairedDamage - 汽车有尚未修复的损坏
regionCode - 看车地区编码
seller - 销售方 【以删】
offerType - 报价类型 【以删】
creatDate - 广告发布时间
price - 汽车价格
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'【匿名特征,包含v0-14在内15个匿名特征】
# 分离label即预测值
Y_train = Train_data['price']
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, Train_data[cat_fea].nunique()))
    print(Train_data[cat_fea].value_counts())


结果示例:
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
数字特征分析
numeric_features.append('price')
print(numeric_features)
## 1) 相关性分析
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)
plt.show()
del price_numeric['price']
## 2) 查看几个特征得 偏度和峰值
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())  
         )
## 3) 每个数字特征得分布可视化
f = pd.melt(Train_data, value_vars=numeric_features)#melt进行格式转换
g = sns.FacetGrid(f, col="variable",  col_wrap=2, sharex=False, sharey=False)# FacetFrid 多图共放初始化
g = g.map(sns.distplot, "value")#map应用上一行数据
## 4) 数字特征相互之间的关系可视化
sns.set()
columns = ['price', 'v_12', 'v_8' , 'v_0', 'power', 'v_5',  'v_2', 'v_6', 'v_1', 'v_14']
sns.pairplot(Train_data[columns],size = 2 ,kind ='scatter',diag_kind='kde')#使用kde查看匿名特征相对分布
plt.show()
print(Train_data.columns)#打印索引
print(y_train)

运行结果:
[图片上传失败...(image-d1fce-1585054900291)]

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

Index(['SaleID', 'name', 'regDate', 'model', 'brand', 'bodyType', 'fuelType',
       'gearbox', 'power', 'kilometer', 'notRepairedDamage', 'regionCode',
       'creatDate', 'price', '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'],
      dtype='object')
      
0          1850
1          3600
2          6222
3          2400
          ...  
149997     7500
149998     4999
149999     4700
Name: price, Length: 150000, dtype: int64

图片太大就不放了

多变量关系可视化
## 5) 多变量互相回归关系可视化
fig, ((ax1, ax2), (ax3, ax4), (ax5, ax6), (ax7, ax8), (ax9, ax10)) = plt.subplots(nrows=5, ncols=2, figsize=(24, 20))#分成5*2个格子,每个格子的内容由下所示
# ['v_12', 'v_8' , 'v_0', 'power', 'v_5',  'v_2', 'v_6', 'v_1', 'v_14']
v_12_scatter_plot = pd.concat([Y_train,Train_data['v_12']],axis = 1)
sns.regplot(x='v_12',y = 'price', data = v_12_scatter_plot,scatter= True, fit_reg=True, ax=ax1)#使用函数regplot回归分析绘图,通过date绘制出回归分析线

v_8_scatter_plot = pd.concat([Y_train,Train_data['v_8']],axis = 1)
sns.regplot(x='v_8',y = 'price',data = v_8_scatter_plot,scatter= True, fit_reg=True, ax=ax2)

v_0_scatter_plot = pd.concat([Y_train,Train_data['v_0']],axis = 1)
sns.regplot(x='v_0',y = 'price',data = v_0_scatter_plot,scatter= True, fit_reg=True, ax=ax3)

power_scatter_plot = pd.concat([Y_train,Train_data['power']],axis = 1)
sns.regplot(x='power',y = 'price',data = power_scatter_plot,scatter= True, fit_reg=True, ax=ax4)

v_5_scatter_plot = pd.concat([Y_train,Train_data['v_5']],axis = 1)
sns.regplot(x='v_5',y = 'price',data = v_5_scatter_plot,scatter= True, fit_reg=True, ax=ax5)

v_2_scatter_plot = pd.concat([Y_train,Train_data['v_2']],axis = 1)
sns.regplot(x='v_2',y = 'price',data = v_2_scatter_plot,scatter= True, fit_reg=True, ax=ax6)

v_6_scatter_plot = pd.concat([Y_train,Train_data['v_6']],axis = 1)
sns.regplot(x='v_6',y = 'price',data = v_6_scatter_plot,scatter= True, fit_reg=True, ax=ax7)

v_1_scatter_plot = pd.concat([Y_train,Train_data['v_1']],axis = 1)
sns.regplot(x='v_1',y = 'price',data = v_1_scatter_plot,scatter= True, fit_reg=True, ax=ax8)

v_14_scatter_plot = pd.concat([Y_train,Train_data['v_14']],axis = 1)
sns.regplot(x='v_14',y = 'price',data = v_14_scatter_plot,scatter= True, fit_reg=True, ax=ax9)

v_13_scatter_plot = pd.concat([Y_train,Train_data['v_13']],axis = 1)
sns.regplot(x='v_13',y = 'price',data = v_13_scatter_plot,scatter= True, fit_reg=True, ax=ax10)
类别特征分析
## 1) unique分布
for fea in categorical_features:
    print(Train_data[fea].nunique())#返回唯一值的个数
print(categorical_features)

#运行结果:
99662
248
40
8
7
2
3
7905
['name', 'model', 'brand', 'bodyType', 'fuelType', 'gearbox', 'notRepairedDamage', 'regionCode']


## 2) 类别特征箱形图可视化

# 因为 name和 regionCode的类别太稀疏了,这里我们把不稀疏的几类画一下
categorical_features = ['model',
 'brand',
 'bodyType',
 'fuelType',
 'gearbox',
 'notRepairedDamage']
for c in categorical_features:
    Train_data[c] = Train_data[c].astype('category')#转化为category类型
    if Train_data[c].isnull().any():
        Train_data[c] = Train_data[c].cat.add_categories(['MISSING'])
        Train_data[c] = Train_data[c].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")



后续再记!!!

上一篇下一篇

猜你喜欢

热点阅读