二手车交易价格预测
数据来源:
该数据来自某交易平台的二手车交易记录,总数据量超过40w,包含31列变量信息,其中15列为匿名变量。为了保证比赛的公平性,将会从中抽取15万条作为训练集,5万条作为测试集,同时会对name、model、brand和regionCode等信息进行脱敏。
该项目数据来自阿里天池,数据链接:https://tianchi.aliyun.com/competition/entrance/231784/information。
字段列表:
SaleID : 交易ID,唯一编码
name : 汽车交易名称,已脱敏
regDate : 汽车注册日期,例如20160101,2016年01月01日
model : 车型编码,已脱敏
brand : 汽车品牌,已脱敏
bodyType : 车身类型:豪华轿车:0,微型车:1,厢型车:2,大巴车:3,敞篷车:4,双门汽车:5,商务车:6,搅拌车:7
fuelType : 燃油类型:汽油:0,柴油:1,液化石油气:2,天然气:3,混合动力:4,其他:5,电动:6
gearbox : 变速箱:手动:0,自动:1
power : 发动机功率:范围 [ 0, 600 ]
kilometer : 汽车已行驶公里,单位万km
notRepairedDamage : 汽车有尚未修复的损坏:是:0,否:1
regionCode : 地区编码,已脱敏
seller : 销售方:个体:0,非个体:1
offerType : 报价类型:提供:0,请求:1
creatDate : 汽车上线时间,即开始售卖时间
price : 二手车交易价格(预测目标)
v系列特征 : 匿名特征,包含v0-14在内15个匿名特征
import warnings
warnings.filterwarnings('ignore')
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from scipy import stats
%matplotlib inline
#导入训练集数据
Train_data = pd.read_csv(r'./car_train_0110.csv',sep=' ')
Test_data = pd.read_csv(r'./car_testA_0110.csv',sep=' ')
print('Train data shape:',Train_data.shape)
print('TestA data shape:',Test_data.shape)
Train data shape: (250000, 40)
TestA data shape: (50000, 39)
Train_data.head()
SaleID | name | regDate | model | brand | bodyType | fuelType | gearbox | power | kilometer | ... | v_14 | v_15 | v_16 | v_17 | v_18 | v_19 | v_20 | v_21 | v_22 | v_23 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 134890 | 734 | 20160002 | 13.0 | 9 | NaN | 0.0 | 1.0 | 0 | 15.0 | ... | 0.092139 | 0.000000 | 18.763832 | -1.512063 | -1.008718 | -12.100623 | -0.947052 | 9.077297 | 0.581214 | 3.945923 |
1 | 306648 | 196973 | 20080307 | 72.0 | 9 | 7.0 | 5.0 | 1.0 | 173 | 15.0 | ... | 0.001070 | 0.122335 | -5.685612 | -0.489963 | -2.223693 | -0.226865 | -0.658246 | -3.949621 | 4.593618 | -1.145653 |
2 | 340675 | 25347 | 20020312 | 18.0 | 12 | 3.0 | 0.0 | 1.0 | 50 | 12.5 | ... | 0.064410 | 0.003345 | -3.295700 | 1.816499 | 3.554439 | -0.683675 | 0.971495 | 2.625318 | -0.851922 | -1.246135 |
3 | 57332 | 5382 | 20000611 | 38.0 | 8 | 7.0 | 0.0 | 1.0 | 54 | 15.0 | ... | 0.069231 | 0.000000 | -3.405521 | 1.497826 | 4.782636 | 0.039101 | 1.227646 | 3.040629 | -0.801854 | -1.251894 |
4 | 265235 | 173174 | 20030109 | 87.0 | 0 | 5.0 | 5.0 | 1.0 | 131 | 3.0 | ... | 0.000099 | 0.001655 | -4.475429 | 0.124138 | 1.364567 | -0.319848 | -1.131568 | -3.303424 | -1.998466 | -1.279368 |
5 rows × 40 columns
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))
#计算精度
ACC: 0.75
acc: 0.75
分类准确率分数
是指所有分类正确的百分比。分类准确率这一衡量分类器的标准比较容易理解,但是它不能告诉你响应值的潜在分布,并且它也不能告诉你分类器犯错的类型。
sklearn.metrics.accuracy_score(y_true, y_pred, normalize=True, sample_weight=None)
normalize:默认值为True,返回正确分类的比例;如果为False,返回正确分类的样本数
from sklearn import metrics
y_pred = [0, 1, 0, 1]
y_true = [0, 1, 1, 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))
Precision 1.0
recall: 0.6666666666666666
f1-score 0.8
函数原型
sklearn.metrics.precision_score(y_true, y_pred, labels=None, pos_label=1, average=’binary’, sample_weight=None)
函数注释
计算精度
精度P r e c i s i o n = T P ( T P + F P ) Precision = \frac{TP}{(TP+FP)}Precision=
(TP+FP)
TP
。其中TP是真正例,FP是假正例。精度直观地表示分类器标记正例的能力。
最佳值为1,最差值为0
重要参数
参数名 含义 类型
y_true 正确值 1维矩阵
y_pred 预测值 1维矩阵
average 计算类型 字符串,‘binary’(默认)、‘micro’、‘macro’、‘weighted’、‘samples’
sample_weight 样本比重 n维矩阵(n=样本类数)
参数average
选项 含义
binary 二分类
micro 统计全局TP和FP来计算
macro 计算每个标签的未加权均值(不考虑不平衡)
weighted 计算每个标签等等加权均值(考虑不平衡)
samples 计算每个实例找出其均值
返回值
precision,float或float矩阵
## 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))
AUC socre: 0.75
为什么使用ROC曲线
既然已经这么多评价标准,为什么还要使用ROC和AUC呢?因为ROC曲线有个很好的特性:当测试集中的正负样本的分布变化的时候,ROC曲线能够保持不变。
在实际的数据集中经常会出现类不平衡(class imbalance)现象,即负样本比正样本多很多(或者相反),而且测试数据中的正负样本的分布也可能随着时间变化。下图是ROC曲线和Precision-Recall曲线的对比:
AUC的含义
有点绕,解释一下:首先AUC值是一个概率值,当你随机挑选一个正样本以及一个负样本,当前的分类算法根据计算得到的Score值将这个正样本排在负样本前面的概率,就是AUC值。当然,AUC值越大,当前的分类算法越有可能将正样本排在负样本前面,即能够更好的分类。
用AUC判断分类器(预测模型)优劣的标准:
AUC = 1 是完美分类器,采用这个预测模型时,存在至少一个阈值能得出完美预测。绝大多数预测的场合,不存在完美分类器。
0.5 < AUC < 1,优于随机猜测。这个分类器(模型)妥善设定阈值的话,能有预测价值。
AUC < 0.5,比随机猜测还差;但只要总是反预测而行,就优于随机猜测
# 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))
MSE: 0.2871428571428571
RMSE: 0.5358571238146014
MAE: 0.4142857142857143
MAPE: 0.1461904761904762
MAE 平均绝对值误差(也称L1损失)
平均绝对误差(MAE)是另一种用于回归模型的损失函数。MAE是目标值和预测值之差的绝对值之和。其只衡量了预测值误差的平均模长,而不考虑方向,取值范围也是从0到正无穷(如果考虑方向,则是残差/误差的总和——平均偏差(MBE))。
SMAPE
对称平均绝对百分比误差(Symmetric Mean Absolute Percentage Error)
MAPE平均绝对百分比误差(Mean Absolute Percentage Error)
范围[0,+∞),MAPE 为0%表示完美模型,MAPE 大于 100 %则表示劣质模型。
可以看到,MAPE跟MAE很像,就是多了个分母。
注意点:当真实值有数据等于0时,存在分母0除问题,该公式不可用!
## 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))
R2-score: 0.9486081370449679
R2_score = 1,达到最大值。即分子为 0 ,意味着样本中预测值和真实值完全相等,没有任何误差。也就是说我们建立的模型完美拟合了所有真实数据,是效果最好的模型,R2_score 值也达到了最大。但通常模型不会这么完美,总会有误差存在,当误差很小的时候,分子小于分母,模型会趋近 1,仍然是好的模型,随着误差越来越大,R2_score 也会离最大值 1 越来越远,直到出现第 2 中情况。
R2_score = 0。此时分子等于分母,样本的每项预测值都等于均值。也就是说我们辛苦训练出来的模型和前面说的均值模型完全一样,还不如不训练,直接让模型的预测值全去均值。当误差越来越大的时候就出现了第三种情况。
R2_score < 0 :分子大于分母,训练模型产生的误差比使用均值产生的还要大,也就是训练模型反而不如直接去均值效果好。出现这种情况,通常是模型本身不是线性关系的,而我们误使用了线性模型,导致误差很大。