high-cardinality categorical attributes,从字面上理解,即对于某个category特征,不同值的数量非常多,这里暂且把它叫做高数量类别属性。反之,即低数量类别属性(low-cardinality)

对于低数量类别属性,通常在data science中采用的方式是将其转化为one-hot编码,即给每一个类别增加一个特征。但是当类别数量增加的时候,ont-hot编码增加的特征也在增加。所以,one-hot编码无法适用于高数量特征属性。

基本方法(clustering)

目前有一个常见的方法处理这个问题叫做clustering。即将原始的1-to-N的mapping问题变成1-to-k的mapping问题。(k<<N)

为了达到这个目标,这个高数量类别属性首先将依据target的值grouping成k个类(clusters),然后再依据这个grouping的结果进行one-hot编码。

不得不说,这个方法最大程度的保留了原始数据的信息。grouping的方法有一些:其中一个就是Hierarchical clustering Algorithm,它使用一个基于target的的统计距离来grouping,grouping的标准也可以度量每合并两个clusters带来的信息增量的影响,如gain ratio。两个距离最短的clusters将会被合并成一个。这个过程一直被迭代,直到迭代过程没有明显的改善。

这个问题更多解释可见《统计学习方法》5.2.2

cate_A target
a/b/c.... 1/0
... ...

对上述数据集, cate_A为高数量特征属性,其处理方法的伪代码如下:

while improvment > epsilon or unique(cate_A) >= k:
compute Conditional Entropy Target|cate_A: THA1
for _ :
Merge two random labels in cate_A into one
compute Conditional Entropy Target|cate_A: THA
Find the two labels that then compute to a minimum THA2
improvement = THA1 - THA2

上述方法其实很常见,且被运用在决策树的C4.5方法中进行特征选择。

这个方法在最后需要ont-hot编码。

另一方法(smoothing)

Smoothing,简单来说,就是将原来独立的高数量类别特征的每个值映射到概率估计上。基本来讲,这个预处理方法将原始的值放置到实际的机器学习模型之前先通过一个简单的特征处理模型(如贝叶斯模型)。

下面以binary target为例进行方法分析:

当target属性 \(Y\in\{0,1\}\)时,假设要处理的特征为X,该特征的每一个不同的值为\(X_{i}\)。我们要做的是, 将高数量类别特征将映射到一个标量\(S_{i}\)中,\(S_{i}\)代表一个条件概率,即

$X_{i} \to S_{i} \cong P(Y|X=X_{i}) ---(1)$

注意到\(S_{i}\)代表的是条件概率,那么他的值被归一到了0和1之间,这对于神经网络模型也是一个好的预处理。

下一步就是概率估计的过程。我们假设数据集被分成了\(n_{TR}\)个训练集和\(n_{TS}\)个测试集。因为这个概率估计成为了模型训练的一部分,所以只有训练集的数据被使用。注意到不是所有的X的可能值都会出现在训练集中,有的值可能只出现在测试集或者新进来的数据中。所以,这个映射过程必须要能够处理这个特征的不可预见性的值。

如果该特征某个值如\(X=X_{i}\)出现的数量足够多,那么这个概率估计可以这样计算:

$S_{i}=\frac{n_{iY}}{n_{i}} ---(2)$

这是一个后验概率的计算过程。然而不幸的是,特征的值的数量分布通常是不均匀的,有很多值的数量非常少。所以这种使用\(P(Y|X=X_{i})\)的直接估计是不太可靠的。

为了减小这种小数量值的影响,\(S_{i}\)的计算可能被分成两个概率的组合。后验概率的计算如公式(2),先验概率的计算如\(P(Y) = \frac{n_{Y}}{n_{TR}}\)。整个组合计算公式为:

$S_{i}=\lambda(n_{i})\frac{n_{iY}}{n_{i}}+(1-\lambda(n_{i}))\frac{n_{Y}}{n_{TR}} ---(3)$

\(n_{Y}\)代表在整个数据集中\(Y=1\)的数量。\(\lambda(n_{i})\)是一个在0-1之间的单调递增函数。

原理:一方面,当特征的某个值的数量很多,即\(\lambda\cong1\)时,公式即为(2),计算后验概率。另一方面,当特征的某个值的数量很少时,即\(\lambda\cong0\)时,公式前项为0,只计算先验概率。

所以,关键我们怎么选取\(\lambda(n_{i})\)这个函数呢?有一个典型函数如下:

$\lambda(n)=\frac{1}{1+\exp^{-\frac{n-k}{f}}} ---(4)$

这个公式是一个s形状的函数,当 n=k 时值为 0.5 。

  • 参数 f 控制函数在转折处的斜率,决定了先验概率和后验概率之间的平衡。如果\(f\to\infty\),那么公式(3)变为一个硬间隔,即先验概率和后验概率各占0.5。

  • 参数 k 决定于我们允许的特征值数量的最小值的一半。so important!

我们在来看看经验贝叶斯估计(Empirical Bayes estimation) 的一般公式:

$P=B_{i}y_{i}+(1-B_{i})\overline{y}---(5)$

\(\overline{y}\)是先验概率,\(y_{i}\)是经验后验概率。收缩系数\(B_{i}\)根据不同的估计方法有不同的形式。当所有概率分布服从高斯分布的时候:

$B_{i}=\frac{n_{i}\tau^{2}}{\sigma^{2}+n_{i}\tau^{2}}---(6)$

\(\sigma^{2}\)是值的方差,\(\tau^{2}\)是样本方差。事实上,公式(6)是公式(4)的一般形式。

以下是我在kaggle中看到大佬对该方法的coding实现,借以参考,帮助理解:

def add_noise(series, noise_level):
return series * (1 + noise_level * np.random.randn(len(series))) def target_encode(trn_series=None,
tst_series=None,
target=None,
min_samples_leaf=1,
smoothing=1,
noise_level=0):
"""
trn_series : training categorical feature as a pd.Series
tst_series : test categorical feature as a pd.Series
target : target data as a pd.Series
min_samples_leaf (int) : minimum samples to take category average into account
smoothing (int) : smoothing effect to balance categorical average vs prior
"""
assert len(trn_series) == len(target)
assert trn_series.name == tst_series.name
temp = pd.concat([trn_series, target], axis=1)
# Compute target mean
averages = temp.groupby(by=trn_series.name)[target.name].agg(["mean", "count"])
# Compute smoothing
smoothing = 1 / (1 + np.exp(-(averages["count"] - min_samples_leaf) / smoothing))
# Apply average function to all target data
prior = target.mean()
# The bigger the count the less full_avg is taken into account
averages[target.name] = prior * (1 - smoothing) + averages["mean"] * smoothing
averages.drop(["mean", "count"], axis=1, inplace=True)
# Apply averages to trn and tst series
ft_trn_series = pd.merge(
trn_series.to_frame(trn_series.name),
averages.reset_index().rename(columns={'index': target.name, target.name: 'average'}),
on=trn_series.name,
how='left')['average'].rename(trn_series.name + '_mean').fillna(prior)
# pd.merge does not keep the index so restore it
ft_trn_series.index = trn_series.index
ft_tst_series = pd.merge(
tst_series.to_frame(tst_series.name),
averages.reset_index().rename(columns={'index': target.name, target.name: 'average'}),
on=tst_series.name,
how='left')['average'].rename(trn_series.name + '_mean').fillna(prior)
# pd.merge does not keep the index so restore it
ft_tst_series.index = tst_series.index
return add_noise(ft_trn_series, noise_level), add_noise(ft_tst_series, noise_level)

两个方法比较

smoothing方法可以只要通过对本地数据集的操作就可完成预处理,而clustering方法需要更复杂的算法而且可能导致信息量的减少(因为最后仍然需要进行one-hot编码)。

当然,对于smoothing方法来说, \(\lambda\)函数的选择直接影响到了结果,可能不同的\(\lambda\)函数可以适用于不同的分支领域,这都需要实验的考证。


PS:该篇文章主要基于对文献的翻译,这个翻译过程终于让我体会到翻译的不易了,以后我再也不会抱怨专业书翻译者的不专业了。

Reference:

  1. A Preprocessing Scheme for High-Cardinality Categorical Attributes in Classification and Prediction Problems
  2. 《统计学习方法》.李航
  3. Python target encoding for categorical features

高数量类别特征(high-cardinality categorical attributes)的预处理方法的更多相关文章

  1. 对于高并发短连接造成Cannot assign requested address解决方法

    https://www.cnblogs.com/dadonggg/p/8778318.html 感谢这篇文章给予的启发 在tcp四次挥手断开连接时,主动释放连接的一方最后会进入TIME_WAIT状态, ...

  2. 机器学习实战基础(十一):sklearn中的数据预处理和特征工程(四) 数据预处理 Preprocessing & Impute 之 处理分类特征:编码与哑变量

    处理分类特征:编码与哑变量 在机器学习中,大多数算法,譬如逻辑回归,支持向量机SVM,k近邻算法等都只能够处理数值型数据,不能处理文字,在sklearn当中,除了专用来处理文字的算法,其他算法在fit的 ...

  3. 机器学习实战基础(九):sklearn中的数据预处理和特征工程(二) 数据预处理 Preprocessing & Impute 之 数据无量纲化

    1 数据无量纲化 在机器学习算法实践中,我们往往有着将不同规格的数据转换到同一规格,或不同分布的数据转换到某个特定分布的需求,这种需求统称为将数据“无量纲化”.譬如梯度和矩阵为核心的算法中,譬如逻辑回 ...

  4. Sql Server本地高版本备份数据备份至远程低版本数据库方法

    想要将Sqlserver高版本备份的数据还原到低版本SqlServer2008R2上去,但是这在SqlServer中是没法直接还原数据库的,通过以下方法可以顺利还原. 通过高版本生成sql脚本在低版本 ...

  5. 无法debug断点跟踪JDK源代码——missing line number attributes的解决方法

    在项目工程->Properties->Java Build Path->Libraries中导入的JRE System Library库里,给jar包添加JDK源代码包后,能够直接打 ...

  6. VC6的工程转到VC2010或更高版本出现fatal error C1189编译错误的解决方法

    以前也遇到过,当时解决了没写下来,这次正好又遇到了,就顺手写一下吧,别下次又忘记了. 当VC6的工程转到VC2010或更高版本时编译出现如下错误: c:\program files\microsoft ...

  7. 高并发下用pdo,文件排它锁,redis三种方法对比

    <?php header('content-type:text/html;charset=utf-8');                 // //无控制     // $DB_DSN = ' ...

  8. ArcGis基础——把类别代码替换成对应中文名称的方法

    挂接! 上面是答案,展开一下就是做一个Excel对照表,就两列,代码与中文名称.然后用类别代码字段匹配挂接. 别傻傻找vbs/py代码,不知道拐个弯.

  9. 机器学习实战基础(十二):sklearn中的数据预处理和特征工程(五) 数据预处理 Preprocessing & Impute 之 处理分类特征:处理连续性特征 二值化与分段

    处理连续性特征 二值化与分段 sklearn.preprocessing.Binarizer根据阈值将数据二值化(将特征值设置为0或1),用于处理连续型变量.大于阈值的值映射为1,而小于或等于阈值的值 ...

随机推荐

  1. DB2许可证文件

    与 DB2® 数据库产品相关联的许可证文件有两种类型: 基本许可证密钥和 完整许可证密钥.这些许可证密钥以纯文本格式存储,通常称为 许可证文件或 许可证权利证书. "基本"许可证未 ...

  2. oracle面试题目总结

    阿里巴巴公司DBA笔试题  http://searchdatabase.techtarget.com.cn/tips/2/2535002.shtml   注:以下题目,可根据自己情况挑选题目作答,不必 ...

  3. Day14 Javascript 点击添加出弹窗,取消隐藏弹窗小练习 反选,全选,取消边框

    点击添加出弹窗,取消隐藏弹窗小练习 代码如下: <!DOCTYPE html> <html lang="en"> <head> <meta ...

  4. DjangoRestFramework实践笔记

    1.Restful服务的实现方式一共三种:function based view,class based view,viewset+router,这三种实现方式的封装重度依序升高,越往后越适合典型CU ...

  5. 阿里服务器CentOS报错base ls command not found

    第一次linux中安装jdk时,踩过的坑. 1.vi command not found ,输入任何命令都无法实现 只要原因是因为环境变量的问题,编辑profile文件没有写正确,导致在命令行下 ls ...

  6. 初探Apache Beam

    文章作者:luxianghao 文章来源:http://www.cnblogs.com/luxianghao/p/9010748.html  转载请注明,谢谢合作. 免责声明:文章内容仅代表个人观点, ...

  7. JavaScript之对象继承

    原型链继承 function SuperType(){ this.property = true; } SuperType.prototype.getSuperValue = function(){ ...

  8. FPGA中的除法运算及初识AXI总线

    FPGA中的硬件逻辑与软件程序的区别,相信大家在做除法运算时会有深入体会.硬件逻辑实现的除法运算会占用较多的资源,电路结构复杂,且通常无法在一个时钟周期内完成.因此FPGA实现除法运算并不是一个&qu ...

  9. 关于cannot find module 'xxxx’的一个可能解决方法。

    关于cannot find module 'xxxx'的一个可能解决方法. 由于学习angular2,想单独学习一下typescript下angular2使用的'rxjs'是怎么使用的,我用npm自己 ...

  10. java web 开发实战经典(一)

    一.jsp三种Scriptlet(脚本小程序) 1.<% %>  :定义局部变量.编写语句等. <% String str = "hello world!";// ...