这个实战是阿里天池数据比赛上的一个题目,虽然以该题目为背景但将从机器学习过程的通解层面进行分析。
零基础入门数据挖掘 - 二手车交易价格预测
本文将从下面五个方面完整总结完成这个题目的过程
1、赛题理解
2、数据分析
3、特征工程
4、建模调参
5、模型融合
针对一个传统的机器学习,首先应该明确是分类还是回归问题,明确针对该问题的评价标准。
# coding=utf-8
import numpy as np
from sklearn import metrics
from sklearn.metrics import r2_score
# 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
print('R2-score:',r2_score(y_true, y_pred))
import numpy as np
from sklearn.metrics import accuracy_score
from sklearn.metrics import roc_auc_score
from sklearn import metrics
## accuracy
y_pred = [0, 1, 0, 1]
y_true = [0, 1, 1, 1]
print('ACC:',accuracy_score(y_true, y_pred))
## Precision,Recall,F1-score
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
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))
将特征分为数字特征和类别特征两类
a=Train_data.head(5) #浏览前5行
b=Train_data.info() #类型
c=Train_data.describe() #数字特征
print(a,b,c)
某些数据包含‘-’表示nan,其info类型为object,应首先将其替换为nan,
再用删除填充等方法解决
# nan可视化
missing = Train_data.isnull().sum()
print(missing)
missing = missing[missing > 0]
missing.sort_values(inplace=True)
missing.plot.bar()
plt.show()
# 可视化看下缺省值
msno.matrix(Train_data.sample(250))
plt.show()
msno.bar(Train_data.sample(1000))
plt.show()
有时需要对y进行变换使其更加适合模型,如对数变化
plt.hist(Train_data['price'], orientation='vertical', histtype='bar', color='red')
plt.show()
类别特征偏斜过大如10000个1一个0的一列特征,几乎可认为该特征无总用可以删除,数字特征偏峰度过大的可以通过对数等方法解决
# 类别特征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())
# 数字特征偏峰度
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())
)
def reduce_mem_usage(df):
""" iterate through all the columns of a dataframe and modify the data type
to reduce memory usage.
"""
start_mem = df.memory_usage().sum()
print('Memory usage of dataframe is {:.2f} B'.format(start_mem))
for col in df.columns:
col_type = df[col].dtype
if col_type != object:
c_min = df[col].min()
c_max = df[col].max()
if str(col_type)[:3] == 'int':
if c_min > np.iinfo(np.int8).min and c_max < np.iinfo(np.int8).max:
df[col] = df[col].astype(np.int8)
elif c_min > np.iinfo(np.int16).min and c_max < np.iinfo(np.int16).max:
df[col] = df[col].astype(np.int16)
elif c_min > np.iinfo(np.int32).min and c_max < np.iinfo(np.int32).max:
df[col] = df[col].astype(np.int32)
elif c_min > np.iinfo(np.int64).min and c_max < np.iinfo(np.int64).max:
df[col] = df[col].astype(np.int64)
else:
if c_min > np.finfo(np.float16).min and c_max < np.finfo(np.float16).max:
df[col] = df[col].astype(np.float16)
elif c_min > np.finfo(np.float32).min and c_max < np.finfo(np.float32).max:
df[col] = df[col].astype(np.float32)
else:
df[col] = df[col].astype(np.float64)
else:
df[col] = df[col].astype('category')
end_mem = df.memory_usage().sum()
print('Memory usage after optimization is: {:.2f} B'.format(end_mem))
print('Decreased by {:.1f}%'.format(100 * (start_mem - end_mem) / start_mem))
return df
思维风暴般的选择关联度大切不至于过拟合欠拟合的特征尤为重要
常见的特征工程包括:
1、异常处理:
通过箱线图(或 3-Sigma)分析删除异常值;
BOX-COX 转换(处理有偏分布);
2、长尾截断;
特征归一化/标准化:
标准化(转换为标准正态分布);
归一化(抓换到 [0,1] 区间);
3、数据分桶:
等频分桶;
等距分桶;
Best-KS 分桶(类似利用基尼指数进行二分类);
卡方分桶;
4、缺失值处理:
不处理(针对类似 XGBoost 等树模型);
删除(缺失数据太多);
插值补全,包括均值/中位数/众数/建模预测/多重插补/压缩感知补全/矩阵补全等;
分箱,缺失值一个箱;
5、特征构造:
构造统计量特征,报告计数、求和、比例、标准差等;
时间特征,包括相对时间和绝对时间,节假日,双休日等;
地理信息,包括分箱,分布编码等方法;
非线性变换,包括 log/ 平方/ 根号等;
特征组合,特征交叉;
仁者见仁,智者见智。
6、特征筛选
过滤式(filter):先对数据进行特征选择,然后在训练学习器,常见的方法有 Relief/方差选择发/相关系数法/卡方检验法/互信息法;
包裹式(wrapper):直接把最终将要使用的学习器的性能作为特征子集的评价准则,常见方法有 LVM(Las Vegas Wrapper) ;
嵌入式(embedding):结合过滤式和包裹式,学习器训练过程中自动进行了特征选择,常见的有 lasso 回归;
7、降维
PCA/ LDA/ ICA;
特征选择也是一种降维
可以使用sklearn中一些常用机器学习模型或者配合nn模型
from sklearn.model_selection import train_test_split,cross_val_score
from sklearn.linear_model import LinearRegression
from sklearn.ensemble import RandomForestRegressor
from sklearn.ensemble import GradientBoostingRegressor
from lightgbm.sklearn import LGBMRegressor
train_X,test_X,train_y,test_y = train_test_split(train_X_all,train_y_all,test_size=0.3,random_state=3)
models = [LinearRegression(),
RandomForestRegressor(30),
GradientBoostingRegressor(),
LGBMRegressor(n_estimators = 100)]
result=[]
for model in models:
model_name = str(model).split('(')[0]
model.fit(X=train_X, y=train_y)
result.append(model.predict(test_X))
scores = cross_val_score(model, X=train_X, y=train_y, verbose=0, cv = 5)
print(model_name,':',scores)
print(model_name + ' is finished')
df=pd.DataFrame(result)
在此介绍了三种常用的调参方法如下:
贪心算法
网格调参
贝叶斯调参
模型融合是比赛后期一个重要的环节,大体来说有如下的类型方式。
简单加权融合:
回归(分类概率):算术平均融合(Arithmetic mean),几何平均融合(Geometric mean);
分类:投票(Voting)
综合:排序融合(Rank averaging),log融合
stacking/blending:
构建多层模型,并利用预测结果再拟合预测。
boosting/bagging(在xgboost,Adaboost,GBDT中已经用到):
多树的提升方法