【機器學習入門與實踐】資料探勘-二手車價格交易預測(含EDA探索、特徵工程、特徵最佳化、模型融合等)

✨汀、發表於2023-04-13

【機器學習入門與實踐】資料探勘-二手車價格交易預測(含EDA探索、特徵工程、特徵最佳化、模型融合等)

note:專案連結以及碼源見文末

1.賽題簡介

瞭解賽題

  • 賽題概況

  • 資料概況

  • 預測指標

  • 分析賽題

  • 資料讀取pandas

  • 分類指標評價計算示例

  • 迴歸指標評價計算示例

EDA探索

  • 載入各種資料科學以及視覺化庫
  • 載入資料
  • 總覽資料概況
  • 判斷資料缺失和異常
  • 瞭解預測值的分佈
  • 特徵分為類別特徵和數字特徵,並對類別特徵檢視unique分佈
  • 數字特徵分析
  • 類別特徵分析
  • 用pandas_profiling生成資料包告

特徵工程

  • 匯入資料
  • 刪除異常值
  • 特徵構造
  • 特徵篩選

建模調參,相關原理介紹與推薦

  • 線性迴歸模型
  • 決策樹模型
  • GBDT模型
  • XGBoost模型
  • LightGBM模型
  • 推薦教材
  • 讀取資料
  • 線性迴歸 & 五折交叉驗證 & 模擬真實業務情況
  • 多種模型對比
  • 模型調參

模型融合

  • 迴歸\分類機率-融合
  • 分類模型融合
  • 一些其它方法
  • 本賽題示例

1.1 資料說明

比賽要求參賽選手根據給定的資料集,建立模型,二手汽車的交易價格。

來自 Ebay Kleinanzeigen 報廢的二手車,數量超過 370,000,包含 20 列變數資訊,為了保證
比賽的公平性,將會從中抽取 10 萬條作為訓練集,5 萬條作為測試集 A,5 萬條作為測試集
B。同時會對名稱、車輛型別、變速箱、model、燃油型別、品牌、公里數、價格等資訊進行
脫敏。

一般而言,對於資料在比賽介面都有對應的資料概況介紹(匿名特徵除外),說明列的性質特徵。瞭解列的性質會有助於我們對於資料的理解和後續分析。
Tip:匿名特徵,就是未告知資料列所屬的性質的特徵列。

train.csv

  • 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'(根據汽車的評論、標籤等大量資訊得到的embedding向量)【人工構造 匿名特徵】
     

數字全都脫敏處理,都為label encoding形式,即數字形式

1.2預測指標

本賽題的評價標準為MAE(Mean Absolute Error):

$$
MAE=\frac{\sum_{i=1}^{n}\left|y_{i}-\hat{y}{i}\right|}{n}
$$
其中$y
$代表第$i$個樣本的真實值,其中$\hat{y}_{i}$代表第$i$個樣本的預測值。

一般問題評價指標說明:

什麼是評估指標:

評估指標即是我們對於一個模型效果的數值型量化。(有點類似與對於一個商品評價打分,而這是針對於模型效果和理想效果之間的一個打分)

一般來說分類和迴歸問題的評價指標有如下一些形式:

分類演算法常見的評估指標如下:

  • 對於二類分類器/分類演算法,評價指標主要有accuracy, [Precision,Recall,F-score,Pr曲線],ROC-AUC曲線。
  • 對於多類分類器/分類演算法,評價指標主要有accuracy, [宏平均和微平均,F-score]。

對於迴歸預測類常見的評估指標如下:

  • 平均絕對誤差(Mean Absolute Error,MAE),均方誤差(Mean Squared Error,MSE),平均絕對百分誤差(Mean Absolute Percentage Error,MAPE),均方根誤差(Root Mean Squared Error), R2(R-Square)

平均絕對誤差
平均絕對誤差(Mean Absolute Error,MAE):平均絕對誤差,其能更好地反映預測值與真實值誤差的實際情況,其計算公式如下:
$$
MAE=\frac{1}{N} \sum_{i=1}^{N}\left|y_{i}-\hat{y}_{i}\right|
$$

均方誤差
均方誤差(Mean Squared Error,MSE),均方誤差,其計算公式為:
$$
MSE=\frac{1}{N} \sum_{i=1}{N}\left(y_{i}-\hat{y}_{i}\right)
$$

R2(R-Square)的公式為
殘差平方和:
$$
SS_{res}=\sum\left(y_{i}-\hat{y}{i}\right)^{2}
$$
總平均值:
$$
SS
=\sum\left(y_{i}-\overline{y}_{i}\right)^{2}
$$

其中$\overline{y}$表示$y$的平均值
得到$R^2$表示式為:
$$
R{2}=1-\frac{SS_{res}}{SS_{tot}}=1-\frac{\sum\left(y_{i}-\hat{y}_{i}\right){2}}{\sum\left(y_{i}-\overline{y}\right)^{2}}
$$
$R^2$用於度量因變數的變異中可由自變數解釋部分所佔的比例,取值範圍是 0~1,$R2$越接近1,表明迴歸平方和佔總平方和的比例越大,迴歸線與各觀測點越接近,用x的變化來解釋y值變化的部分就越多,迴歸的擬合程度就越好。所以$R2$也稱為擬合優度(Goodness of Fit)的統計量。

$y_{i}$表示真實值,$\hat{y}{i}$表示預測值,$\overline{y}$表示樣本均值。得分越高擬合效果越好。

1.3分析賽題

  1. 此題為傳統的資料探勘問題,透過資料科學以及機器學習深度學習的辦法來進行建模得到結果。
  2. 此題是一個典型的迴歸問題。
  3. 主要應用xgb、lgb、catboost,以及pandas、numpy、matplotlib、seabon、sklearn、keras等等資料探勘常用庫或者框架來進行資料探勘任務。

2.資料探索

# 下載資料
!wget http://tianchi-media.oss-cn-beijing.aliyuncs.com/dragonball/DM/data.zip
# 解壓下載好的資料
!unzip data.zip
# 匯入函式工具
## 基礎工具
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.filterwarnings('ignore')
%matplotlib inline

## 模型預測的
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.1 資料讀取

## 透過Pandas對於資料進行讀取 (pandas是一個很友好的資料讀取函式庫)
Train_data = pd.read_csv('/home/aistudio/dataset/used_car_train_20200313.csv', sep=' ')
TestA_data = pd.read_csv('/home/aistudio/dataset/used_car_testA_20200313.csv', sep=' ')

## 輸出資料的大小資訊
print('Train data shape:',Train_data.shape)
print('TestA data shape:',TestA_data.shape)
Train data shape: (150000, 31)
TestA data shape: (50000, 30)

2.2 資料簡要瀏覽

## 透過.head() 簡要瀏覽讀取資料的形式
Train_data.head()
SaleID name regDate model brand bodyType fuelType gearbox power kilometer ... v_5 v_6 v_7 v_8 v_9 v_10 v_11 v_12 v_13 v_14
0 0 736 20040402 30.0 6 1.0 0.0 0.0 60 12.5 ... 0.235676 0.101988 0.129549 0.022816 0.097462 -2.881803 2.804097 -2.420821 0.795292 0.914762
1 1 2262 20030301 40.0 1 2.0 0.0 0.0 0 15.0 ... 0.264777 0.121004 0.135731 0.026597 0.020582 -4.900482 2.096338 -1.030483 -1.722674 0.245522
2 2 14874 20040403 115.0 15 1.0 0.0 0.0 163 12.5 ... 0.251410 0.114912 0.165147 0.062173 0.027075 -4.846749 1.803559 1.565330 -0.832687 -0.229963
3 3 71865 19960908 109.0 10 0.0 0.0 1.0 193 15.0 ... 0.274293 0.110300 0.121964 0.033395 0.000000 -4.509599 1.285940 -0.501868 -2.438353 -0.478699
4 4 111080 20120103 110.0 5 1.0 0.0 0.0 68 5.0 ... 0.228036 0.073205 0.091880 0.078819 0.121534 -1.896240 0.910783 0.931110 2.834518 1.923482

5 rows × 31 columns

2.3 資料資訊檢視

## 透過 .info() 簡要可以看到對應一些資料列名,以及NAN缺失資訊
Train_data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 150000 entries, 0 to 149999
Data columns (total 31 columns):
 #   Column             Non-Null Count   Dtype  
---  ------             --------------   -----  
 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
## 透過 .columns 檢視列名
Train_data.columns
Index(['SaleID', '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'],
      dtype='object')
TestA_data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 50000 entries, 0 to 49999
Data columns (total 30 columns):
 #   Column             Non-Null Count  Dtype  
---  ------             --------------  -----  
 0   SaleID             50000 non-null  int64  
 1   name               50000 non-null  int64  
 2   regDate            50000 non-null  int64  
 3   model              50000 non-null  float64
 4   brand              50000 non-null  int64  
 5   bodyType           48587 non-null  float64
 6   fuelType           47107 non-null  float64
 7   gearbox            48090 non-null  float64
 8   power              50000 non-null  int64  
 9   kilometer          50000 non-null  float64
 10  notRepairedDamage  50000 non-null  object 
 11  regionCode         50000 non-null  int64  
 12  seller             50000 non-null  int64  
 13  offerType          50000 non-null  int64  
 14  creatDate          50000 non-null  int64  
 15  v_0                50000 non-null  float64
 16  v_1                50000 non-null  float64
 17  v_2                50000 non-null  float64
 18  v_3                50000 non-null  float64
 19  v_4                50000 non-null  float64
 20  v_5                50000 non-null  float64
 21  v_6                50000 non-null  float64
 22  v_7                50000 non-null  float64
 23  v_8                50000 non-null  float64
 24  v_9                50000 non-null  float64
 25  v_10               50000 non-null  float64
 26  v_11               50000 non-null  float64
 27  v_12               50000 non-null  float64
 28  v_13               50000 non-null  float64
 29  v_14               50000 non-null  float64
dtypes: float64(20), int64(9), object(1)
memory usage: 11.4+ MB

2.4 資料統計資訊瀏覽

## 透過 .describe() 可以檢視數值特徵列的一些統計資訊
Train_data.describe()
SaleID name regDate model brand bodyType fuelType gearbox power kilometer ... v_5 v_6 v_7 v_8 v_9 v_10 v_11 v_12 v_13 v_14
count 150000.000000 150000.000000 1.500000e+05 149999.000000 150000.000000 145494.000000 141320.000000 144019.000000 150000.000000 150000.000000 ... 150000.000000 150000.000000 150000.000000 150000.000000 150000.000000 150000.000000 150000.000000 150000.000000 150000.000000 150000.000000
mean 74999.500000 68349.172873 2.003417e+07 47.129021 8.052733 1.792369 0.375842 0.224943 119.316547 12.597160 ... 0.248204 0.044923 0.124692 0.058144 0.061996 -0.001000 0.009035 0.004813 0.000313 -0.000688
std 43301.414527 61103.875095 5.364988e+04 49.536040 7.864956 1.760640 0.548677 0.417546 177.168419 3.919576 ... 0.045804 0.051743 0.201410 0.029186 0.035692 3.772386 3.286071 2.517478 1.288988 1.038685
min 0.000000 0.000000 1.991000e+07 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.500000 ... 0.000000 0.000000 0.000000 0.000000 0.000000 -9.168192 -5.558207 -9.639552 -4.153899 -6.546556
25% 37499.750000 11156.000000 1.999091e+07 10.000000 1.000000 0.000000 0.000000 0.000000 75.000000 12.500000 ... 0.243615 0.000038 0.062474 0.035334 0.033930 -3.722303 -1.951543 -1.871846 -1.057789 -0.437034
50% 74999.500000 51638.000000 2.003091e+07 30.000000 6.000000 1.000000 0.000000 0.000000 110.000000 15.000000 ... 0.257798 0.000812 0.095866 0.057014 0.058484 1.624076 -0.358053 -0.130753 -0.036245 0.141246
75% 112499.250000 118841.250000 2.007111e+07 66.000000 13.000000 3.000000 1.000000 0.000000 150.000000 15.000000 ... 0.265297 0.102009 0.125243 0.079382 0.087491 2.844357 1.255022 1.776933 0.942813 0.680378
max 149999.000000 196812.000000 2.015121e+07 247.000000 39.000000 7.000000 6.000000 1.000000 19312.000000 15.000000 ... 0.291838 0.151420 1.404936 0.160791 0.222787 12.357011 18.819042 13.847792 11.147669 8.658418

8 rows × 30 columns

TestA_data.describe()
SaleID name regDate model brand bodyType fuelType gearbox power kilometer ... v_5 v_6 v_7 v_8 v_9 v_10 v_11 v_12 v_13 v_14
count 50000.000000 50000.000000 5.000000e+04 50000.000000 50000.000000 48587.000000 47107.000000 48090.000000 50000.000000 50000.000000 ... 50000.000000 50000.000000 50000.000000 50000.000000 50000.000000 50000.000000 50000.000000 50000.000000 50000.000000 50000.000000
mean 174999.500000 68542.223280 2.003393e+07 46.844520 8.056240 1.782185 0.373405 0.224350 119.883620 12.595580 ... 0.248669 0.045021 0.122744 0.057997 0.062000 -0.017855 -0.013742 -0.013554 -0.003147 0.001516
std 14433.901067 61052.808133 5.368870e+04 49.469548 7.819477 1.760736 0.546442 0.417158 185.097387 3.908979 ... 0.044601 0.051766 0.195972 0.029211 0.035653 3.747985 3.231258 2.515962 1.286597 1.027360
min 150000.000000 0.000000 1.991000e+07 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.500000 ... 0.000000 0.000000 0.000000 0.000000 0.000000 -9.160049 -5.411964 -8.916949 -4.123333 -6.112667
25% 162499.750000 11203.500000 1.999091e+07 10.000000 1.000000 0.000000 0.000000 0.000000 75.000000 12.500000 ... 0.243762 0.000044 0.062644 0.035084 0.033714 -3.700121 -1.971325 -1.876703 -1.060428 -0.437920
50% 174999.500000 52248.500000 2.003091e+07 29.000000 6.000000 1.000000 0.000000 0.000000 109.000000 15.000000 ... 0.257877 0.000815 0.095828 0.057084 0.058764 1.613212 -0.355843 -0.142779 -0.035956 0.138799
75% 187499.250000 118856.500000 2.007110e+07 65.000000 13.000000 3.000000 1.000000 0.000000 150.000000 15.000000 ... 0.265328 0.102025 0.125438 0.079077 0.087489 2.832708 1.262914 1.764335 0.941469 0.681163
max 199999.000000 196805.000000 2.015121e+07 246.000000 39.000000 7.000000 6.000000 1.000000 20000.000000 15.000000 ... 0.291618 0.153265 1.358813 0.156355 0.214775 12.338872 18.856218 12.950498 5.913273 2.624622

8 rows × 29 columns

3.資料分析

#### 1) 提取數值型別特徵列名
numerical_cols = Train_data.select_dtypes(exclude = 'object').columns
print(numerical_cols)
Index(['SaleID', 'name', 'regDate', 'model', 'brand', 'bodyType', 'fuelType',
       'gearbox', 'power', 'kilometer', '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'],
      dtype='object')
categorical_cols = Train_data.select_dtypes(include = 'object').columns
print(categorical_cols)
Index(['notRepairedDamage'], dtype='object')
#### 2) 構建訓練和測試樣本
## 選擇特徵列
feature_cols = [col for col in numerical_cols if col not in ['SaleID','name','regDate','creatDate','price','model','brand','regionCode','seller']]
feature_cols = [col for col in feature_cols if 'Type' not in col]

## 提前特徵列,標籤列構造訓練樣本和測試樣本
X_data = Train_data[feature_cols]
Y_data = Train_data['price']

X_test  = TestA_data[feature_cols]

print('X train shape:',X_data.shape)
print('X test shape:',X_test.shape)
X train shape: (150000, 18)
X test shape: (50000, 18)
## 定義了一個統計函式,方便後續資訊統計
def Sta_inf(data):
    print('_min',np.min(data))
    print('_max:',np.max(data))
    print('_mean',np.mean(data))
    print('_ptp',np.ptp(data))
    print('_std',np.std(data))
    print('_var',np.var(data))
#### 3) 統計標籤的基本分佈資訊
print('Sta of label:')
Sta_inf(Y_data)
Sta of label:
_min 11
_max: 99999
_mean 5923.327333333334
_ptp 99988
_std 7501.973469876635
_var 56279605.942732885
## 繪製標籤的統計圖,檢視標籤分佈
plt.hist(Y_data)
plt.show()
plt.close()

#### 4) 預設值用-1填補
X_data = X_data.fillna(-1)
X_test = X_test.fillna(-1)

4. 模型訓練與預測(特徵工程、模型融合)

4.1 利用xgb進行五折交叉驗證檢視模型的引數效果

## xgb-Model
xgr = xgb.XGBRegressor(n_estimators=120, learning_rate=0.1, gamma=0, subsample=0.8,\
        colsample_bytree=0.9, max_depth=7) #,objective ='reg:squarederror'

scores_train = []
scores = []

## 5折交叉驗證方式
sk=StratifiedKFold(n_splits=5,shuffle=True,random_state=0)
for train_ind,val_ind in sk.split(X_data,Y_data):
    
    train_x=X_data.iloc[train_ind].values
    train_y=Y_data.iloc[train_ind]
    val_x=X_data.iloc[val_ind].values
    val_y=Y_data.iloc[val_ind]
    
    xgr.fit(train_x,train_y)
    pred_train_xgb=xgr.predict(train_x)
    pred_xgb=xgr.predict(val_x)
    
    score_train = mean_absolute_error(train_y,pred_train_xgb)
    scores_train.append(score_train)
    score = mean_absolute_error(val_y,pred_xgb)
    scores.append(score)

print('Train mae:',np.mean(score_train))
print('Val mae',np.mean(scores))

4.2 定義xgb和lgb模型函式

def build_model_xgb(x_train,y_train):
    model = xgb.XGBRegressor(n_estimators=150, learning_rate=0.1, gamma=0, subsample=0.8,\
        colsample_bytree=0.9, max_depth=7) #, objective ='reg:squarederror'
    model.fit(x_train, y_train)
    return model

def build_model_lgb(x_train,y_train):
    estimator = lgb.LGBMRegressor(num_leaves=127,n_estimators = 150)
    param_grid = {
        'learning_rate': [0.01, 0.05, 0.1, 0.2],
    }
    gbm = GridSearchCV(estimator, param_grid)
    gbm.fit(x_train, y_train)
    return gbm

4.3 切分資料集(Train,Val)進行模型訓練,評價和預測

## Split data with val
x_train,x_val,y_train,y_val = train_test_split(X_data,Y_data,test_size=0.3)
print('Train lgb...')
model_lgb = build_model_lgb(x_train,y_train)
val_lgb = model_lgb.predict(x_val)
MAE_lgb = mean_absolute_error(y_val,val_lgb)
print('MAE of val with lgb:',MAE_lgb)

print('Predict lgb...')
model_lgb_pre = build_model_lgb(X_data,Y_data)
subA_lgb = model_lgb_pre.predict(X_test)
print('Sta of Predict lgb:')
Sta_inf(subA_lgb)
print('Train xgb...')
model_xgb = build_model_xgb(x_train,y_train)
val_xgb = model_xgb.predict(x_val)
MAE_xgb = mean_absolute_error(y_val,val_xgb)
print('MAE of val with xgb:',MAE_xgb)

print('Predict xgb...')
model_xgb_pre = build_model_xgb(X_data,Y_data)
subA_xgb = model_xgb_pre.predict(X_test)
print('Sta of Predict xgb:')
Sta_inf(subA_xgb)

4.4進行兩模型的結果加權融合

## 這裡我們採取了簡單的加權融合的方式
val_Weighted = (1-MAE_lgb/(MAE_xgb+MAE_lgb))*val_lgb+(1-MAE_xgb/(MAE_xgb+MAE_lgb))*val_xgb
val_Weighted[val_Weighted<0]=10 # 由於我們發現預測的最小值有負數,而真實情況下,price為負是不存在的,由此我們進行對應的後修正
print('MAE of val with Weighted ensemble:',mean_absolute_error(y_val,val_Weighted))
sub_Weighted = (1-MAE_lgb/(MAE_xgb+MAE_lgb))*subA_lgb+(1-MAE_xgb/(MAE_xgb+MAE_lgb))*subA_xgb

## 檢視預測值的統計進行
plt.hist(Y_data)
plt.show()
plt.close()

4.5.輸出結果

sub = pd.DataFrame()
sub['SaleID'] = TestA_data.SaleID
sub['price'] = sub_Weighted
sub.to_csv('./sub_Weighted.csv',index=False)
sub.head()

5. 專案詳細展開

因篇幅內容限制,將原學習專案拆解成多個notebook方便學習,只需一鍵fork。

5.1 資料分析詳解

  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生成資料包告

5.2 特徵工程

  1. 異常處理:
    • 透過箱線圖(或 3-Sigma)分析刪除異常值;
    • BOX-COX 轉換(處理有偏分佈);
    • 長尾截斷;
  2. 特徵歸一化/標準化:
    • 標準化(轉換為標準正態分佈);
    • 歸一化(抓換到 [0,1] 區間);
    • 針對冪律分佈,可以採用公式: $log(\frac{1+x}{1+median})$
  3. 資料分桶:
    • 等頻分桶;
    • 等距分桶;
    • Best-KS 分桶(類似利用基尼指數進行二分類);
    • 卡方分桶;
  4. 缺失值處理:
    • 不處理(針對類似 XGBoost 等樹模型);
    • 刪除(缺失資料太多);
    • 插值補全,包括均值/中位數/眾數/建模預測/多重插補/壓縮感知補全/矩陣補全等;
    • 分箱,缺失值一個箱;
  5. 特徵構造:
    • 構造統計量特徵,報告計數、求和、比例、標準差等;
    • 時間特徵,包括相對時間和絕對時間,節假日,雙休日等;
    • 地理資訊,包括分箱,分佈編碼等方法;
    • 非線性變換,包括 log/ 平方/ 根號等;
    • 特徵組合,特徵交叉;
    • 仁者見仁,智者見智。
  6. 特徵篩選
    • 過濾式(filter):先對資料進行特徵選擇,然後在訓練學習器,常見的方法有 Relief/方差選擇發/相關係數法/卡方檢驗法/互資訊法;
    • 包裹式(wrapper):直接把最終將要使用的學習器的效能作為特徵子集的評價準則,常見方法有 LVM(Las Vegas Wrapper) ;
    • 嵌入式(embedding):結合過濾式和包裹式,學習器訓練過程中自動進行了特徵選擇,常見的有 lasso 迴歸;
  7. 降維
    • PCA/ LDA/ ICA;
    • 特徵選擇也是一種降維。

5.3 模型最佳化

  1. 線性迴歸模型:
    • 線性迴歸對於特徵的要求;
    • 處理長尾分佈;
    • 理解線性迴歸模型;
  2. 模型效能驗證:
    • 評價函式與目標函式;
    • 交叉驗證方法;
    • 留一驗證方法;
    • 針對時間序列問題的驗證;
    • 繪製學習率曲線;
    • 繪製驗證曲線;
  3. 嵌入式特徵選擇:
    • Lasso迴歸;
    • Ridge迴歸;
    • 決策樹;
  4. 模型對比:
    • 常用線性模型;
    • 常用非線性模型;
  5. 模型調參:
    • 貪心調參方法;
    • 網格調參方法;
    • 貝葉斯調參方法;

5.4模型融合

  1. 簡單加權融合:

    • 迴歸(分類機率):算術平均融合(Arithmetic mean),幾何平均融合(Geometric mean);
    • 分類:投票(Voting)
    • 綜合:排序融合(Rank averaging),log融合
  2. stacking/blending:

    • 構建多層模型,並利用預測結果再擬合預測。
  3. boosting/bagging(在xgboost,Adaboost,GBDT中已經用到):

    • 多樹的提升方法

    訓練:

預測:

6.總結

二手車預測專案是非常經典專案,資料探勘實踐(二手車價格預測)的內容來自 Datawhale與天池聯合發起的,現在透過整理和調整讓更多對機器學習感興趣可以上手實戰一下

因篇幅內容限制,將原學習專案拆解成多個notebook方便學習,只需一鍵fork。

專案連結:

一鍵fork直接執行,所有專案碼源都在裡面

https://www.heywhale.com/mw/project/64367e0a2a3d6dc93d22054f

機器學習資料探勘專欄:
https://www.heywhale.com/home/column/64141d6b1c8c8b518ba97dcc

參考連結:

https://github.com/datawhalechina/team-learning-data-mining/tree/master/SecondHandCarPriceForecast

相關文章