如下是Coursera上的How to Win a Data Science Competition: Learn from Top Kagglers课程笔记。python
均值编码是一种很是强大的技术,它有不少名字,例如:likelihood encoding、target encoding,但这里咱们叫它均值编码。咱们举一个二分类任务的例子。dom
feature | feature_label | feature_mean | target | |
---|---|---|---|---|
0 | Moscow | 1 | 0.4 | 0 |
1 | Moscow | 1 | 0.4 | 1 |
2 | Moscow | 1 | 0.4 | 1 |
3 | Moscow | 1 | 0.4 | 0 |
4 | Moscow | 1 | 0.4 | 0 |
5 | Tver | 2 | 0.8 | 1 |
6 | Tver | 2 | 0.8 | 1 |
7 | Tver | 2 | 0.8 | 1 |
8 | Tver | 2 | 0.8 | 0 |
9 | Klin | 0 | 0.0 | 0 |
10 | klin | 0 | 0.0 | 0 |
11 | Tver | 2 | 1 | 1 |
咱们想对feature
变量进行编码,最直接、经常使用的方式就是label encoding
,这就是第二列数据。
平均编码以不一样的方式去完成这个任务,它用每一个城市自身对应的目标均值来进行编码。例如,对于Moscow
,咱们有五行,三个0和两个1。 因此咱们用2除以5或0.4对它进行编码。用一样的方法处理其余城市。ide
如今了解一下细节。当咱们的数据集很是大,包含数百个不一样的城市,让咱们试着比较一下。咱们绘制了0,1 class的直方图。
oop
在label encoding
的状况下,咱们获得的图看起来没有任何逻辑顺序。
学习
可是当咱们使用mean encoding
对目标进行编码时,类看起来更加可分了,像是被排序过。ui
通常来讲,模型对复杂、非线性的特征目标越依赖,均值编码
越有效。例如树模型的深度有限,能够用平均编码来补偿它,能够用它的短板来得到更好的分数。编码
以上只是一个例子,传递的是一种思想,实际上能够作不少相似的操做。3d
Goods-number of ones in a group,
Bads-number of zeroscode
构造Mean encoding
的例子orm
means= X_tr.groupby(col).target.mean() train_new[col+'_mean_target'] = train_new[col].map(means) val_new[col+'_mean_target'] = val_new[col].map(means)
将它运用到模型中,出现了严重的过拟合,可是为何呢?
feature | feature_label | feature_mean | target | |
---|---|---|---|---|
8 | Tver | 2 | 0.8 | 0 |
9 | Klin | 0 | 0.0 | 0 |
feature | feature_label | feature_mean | target | |
---|---|---|---|---|
10 | klin | 0 | 0.0 | 0 |
11 | Tver | 2 | 1 | 1 |
When they are categorized, it's pretty common to get results like in an example, target 0 in train and target 1 in validation. Mean encodings turns into a perfect feature for such categories. That's why we immediately get very good scores on train and fail hardly on validation.
在上一节,咱们意识到平均编码不能按原样使用,须要对训练数据进行某种正规化。如今咱们将实施四种不一样的正则化方法。
一般作四到五折的交叉验证就能获得不错的结果,无序调整此数字。
代码例子
这个方法看起来已经彻底避免了目标变量的泄露,但事实并不是如此。
这里咱们经过留一法
对Moscow
进行编码
feature | feature_mean | target | |
---|---|---|---|
0 | Moscow | 0.50 | 0 |
1 | Moscow | 0.25 | 1 |
2 | Moscow | 0.25 | 1 |
3 | Moscow | 0.50 | 0 |
4 | Moscow | 0.50 | 0 |
对于第一行,咱们获得0.5,由于有两个1和 其他行中有两个0。 一样,对于第二行,咱们获得0.25,依此类推。 但仔细观察,全部结果和由此产生的特征。 它完美地分割数据,具备等于或等的特征的行 大于0.5的目标为0,其他行的目标为1。 咱们没有明确使用目标变量,但咱们的编码是有偏置的。
目标变量的泄露效果对于KFold scheme
仍然是有效的,只是效果温和了点。
在实践中,若是您有足够的数据并使用四或五折,编码将经过这种正规化策略正常工做。 只是要当心并使用正确的验证。
$$\frac{mean(target)nrows + globalmeanalpha}{nrows+alpha}$$
它具备控制正则化量的超参数alpha。 当alpha为零时,咱们没有正则化,而且当alpha接近无穷大时,一切都变成了globalmean。
在某种意义上,alpha等于咱们能够信任的类别大小。也可使用其余一些公式,基本上任何惩罚编码类别的东西均可以被认为是smoothing
。
经过添加噪声,会下降训练数据的编码质量。这种方法很不稳定,很难使它工做。主要问题在于咱们须要添加的噪声量。
太多的噪声会把这个特征变成垃圾,虽然噪声过小意味着更正规化。你须要努力地微调它。
这种方法一般与LOO正则化一块儿使用。若是你没有不少时间,它可能不是最好选择。
代码例子
cumsum = df_tr.groupby(col)['target'].cumsum() - df_tr['target'] cumcnt = df_tr.groupby(col).cumcount() train_new[col + '_mean_target'] = cusum/cumcnt
cumsum存储目标变量的累计和,直到给定行,cumcnt存储累积计数。该方法引入的目标变量的泄漏量最少,惟一的缺点是特征质量不均匀。但这不是什么大不了的事,咱们能够从不一样的数据排列计算编码的平均模型。
它被用于CatBoost库中,证实了它在分类数据集上表现很是出色。
Mean encoding
User_id | APPS | Target |
---|---|---|
10 | APP1;APP2;APP3 | 0 |
11 | APP4;APP1 | 1 |
12 | APP2 | 1 |
100 | APP3;APP9 | 0 |
如今考虑一个例子,基于用在智能手机上已装的APP,预测它是否会安装,这是一个二分类任务。从表中数据可知,每一个用户可能有多个应用程序,每一个应用程序由多个用户使用,所以这是多对多的关系。而麻烦在于,如何从多对多的关系中提取均值。
User_id | APP_id | Target |
---|---|---|
10 | APP1 | 0 |
10 | APP2 | 0 |
10 | APP3 | 0 |
11 | APP4 | 1 |
11 | APP1 | 1 |
把原始数据转为长数据表示,如上表。使用此表,咱们能够天然地计算APP的均值编码
。可是如何将其映射回用户呢?
每一个用户都有许多APP,但不都是“APP1,APP2,APP3”。所以咱们用向量表示(0.1,0.2,0.1),咱们还能够从向量中收集各类统计数据,好比均值、标准差、最大最小值等等。
一方面,这是一种限制,另外一方面,它容许咱们只作一些复杂的特征。考虑一个例子:
Day | User | Spend | Amount | Prev_user | Prev_spend_avg |
---|---|---|---|---|---|
1 | 101 | FOOD | 2.0 | 0.0 | 0.0 |
1 | 101 | GAS | 4.0 | 0.0 | 0.0 |
1 | 102 | FOOD | 3.0 | 0.0 | 0.0 |
2 | 101 | GAS | 4.0 | 6.0 | 4.0 |
2 | 101 | TV | 8.0 | 6.0 | 0.0 |
2 | 102 | FOOD | 2.0 | 3.0 | 2.5 |
咱们须要预测用户会为哪一个类别花钱。 咱们有两天的时间,两个用户, 和三个支出类别。 一些好的特征是用户在前一天消费总额,全部用户在给定类别中花费的平均金额。 所以,在第1天,用户101花费6美圆,用户102花费$3。 所以,咱们认为这些数字是第2天的将来值。 一样,能够按类别划分平均金额。
咱们拥有的数据越多,能够创造的特征就越复杂。
在实践中,一般须要编码数字特征以及进行特征组合。要对数字特征进行编码,咱们只须要对其进行分区,而后将其视为分类。咱们以没有进行任何编码的原始特征和决策树模型为例。
如何为数字特征分组?
若是数字特征有不少分裂点,则表示它于目标有一些复杂的依赖,而且试图去编码它。此外这些精确的分裂点可用于对特征进行分类,因此经过分析模型结构,咱们既能够识别这些可疑的数字特征,又能够找到很好的方法去给它分组。
如何挑选特征组合?
先看决策树中如何提取交互特征。参照上图,若是两个特征在相邻的节点中,则这两个特征在相互做用。考虑到这点,咱们能够遍历模型中的全部树,计算每一个特征组合出现的次数。最多见的组合可能值得进行均值编码。
例如,若是咱们发现feature1
和feature2
这一对特征最多见,咱们能够在数据中链接这些特征,这意味编码产生交互。