Press "Enter" to skip to content

特征工程-特征分箱

本站内容均来自兴趣收集,如不慎侵害的您的相关权益,请留言告知,我们将尽快删除.谢谢.

特征工程-特征分箱

 

公众号:尤而小屋

 

作者:Peter

 

编辑:Peter

 

大家好,我是Peter~

 

一般在建立分类模型时,当我们进行特征工程的工作经常需要对连续型变量进行离散化的处理,也就是将连续型字段转成离散型字段。

 

离散化的过程中,连续型变量重新进行了编码。特征离散化后,模型会更稳定,降低了模型过拟合的风险。本文主要介绍3种常见的特征分箱方法:

 

 

分箱特点

 

 

    1. 连续型变量执行离散化的分箱操作,能够更加简洁地呈现数据信息

 

    1. 消除特征变量的量纲影响,因为分箱之后都是类别数,例如:0,1,2…

 

    1. 能够在一定程度上减少异常值的影响,对异常数据有很强的鲁棒性

 

 

模拟数据

 

模拟一份简单的数据和收入INCOME相关

 

In [1]:

 

import pandas as pd
import numpy as np

 

In [2]:

 

df = pd.DataFrame({"ID":range(10),
                  "INCOME":[0,10,20,150,35,78,50,49,88,14]})
df

 

 

sklearn之KBinsDiscretizer类

 

本文中介绍的3种分箱操作都是基于sklearn中的KBinsDiscretizer类,官网学习地址:

 

scikit-learn.org/stable/modu…

 

from sklearn.preprocessing import KBinsDiscretizer
sklearn.preprocessing.KBinsDiscretizer(n_bins=5, 
                                       encode='onehot', 
                                       strategy='quantile', 
                                       dtype=None, 
                                       subsample='warn', 
                                       random_state=None)

 

全部参数解释:

 

全部属性信息:

 

 

重点解释3个参数的使用:

 

n_bins

 

参数n_bins参数上指定需要分箱的个数,默认是5个

 

strategy

 

指定不同的分箱策略strategy:KBinsDiscretizer类实现了不同的分箱策略,可以通过参数strategy进行选择:

 

uniform
quantile
kmeans

 

encode

 

encode参数表示 分箱后 的离散字段是否需要进一步进行独热编码或者其他编码处理

 

KBinsDiscretizer 类只能识别列向量, 需要将DataFrame的数据进行转化 :

 

In [3]:

 

income = np.array(df["INCOME"].tolist()).reshape(-1,1)
income

 

Out[3]:

 

array([[  0],
       [ 10],
       [ 20],
       [150],
       [ 35],
       [ 78],
       [ 50],
       [ 49],
       [ 88],
       [ 14]])

 

使用之前先导进来:

 

In [4]:

 

from sklearn.preprocessing import KBinsDiscretizer

 

等宽分箱

 

所谓的等宽分箱就是将数据分成等宽的几份,比如模拟数据中INCOME的范围是0-150。现在将其等宽分成3份,那幺每一份对应的取值范围是: [0,50),[50,100)[100,150]

 

In [5]:

 

from sklearn.preprocessing import KBinsDiscretizer
dis = KBinsDiscretizer(n_bins=3,
                       encode="ordinal",
                       strategy="uniform"
                      )
dis

 

Out[5]:

 

KBinsDiscretizer(encode='ordinal', n_bins=3, strategy='uniform')

 

In [6]:

 

label_uniform = dis.fit_transform(income)  # 转换器
label_uniform

 

Out[6]:

 

array([[0.],
       [0.],
       [0.],
       [2.],
       [0.],
       [1.],
       [1.],
       [0.],
       [1.],
       [0.]])

 

等宽分箱的边界查看:

 

In [7]:

 

dis.bin_edges_

 

Out[7]:

 

array([array([  0.,  50., 100., 150.])], dtype=object)

 

In [8]:

 

dis.n_bins

 

Out[8]:

 

3

 

等频分箱

 

等频分箱指的是每个区间内包含的取值个数是相同的,和等宽分箱的区别:

等频分箱:每个区间内包括的值一样多,pd.qcut
等宽分箱:每两区间之间的距离是一样的,pd.cut

在实施等频分箱之前,我们需要先对数据进行 升序排列 ,然后取中间值进行分箱

 

In [9]:

 

# 1、先排序
sort_df = sorted(df["INCOME"])
sort_df

 

Out[9]:

 

[0, 10, 14, 20, 35, 49, 50, 78, 88, 150]

 

分成2个类别

 

In [10]:

 

# 2、中间值:35和49的均值
(35 + 49) / 2

 

Out[10]:

 

42.0

 

下面我们以42作为等频分箱的依据:

 

In [11]:

 

dis = KBinsDiscretizer(n_bins=2,
                       encode="ordinal",
                       strategy="quantile"
                      )
dis.fit_transform(income)  # 转换器

 

Out[11]:

 

array([[0.],
       [0.],
       [0.],
       [1.],
       [0.],
       [1.],
       [1.],
       [1.],
       [1.],
       [0.]])

 

In [12]:

 

dis.bin_edges_

 

Out[12]:

 

array([array([  0.,  42., 150.])], dtype=object)

 

分成3个类别

 

总共是10个元素,分成3个类, 10/3=3...1 ,前面两个3个元素,最后一个是4个元素,即最后一个箱体会包含余数部分的元素:

 

In [13]:

 

dis = KBinsDiscretizer(n_bins=3,
                       encode="ordinal",
                       strategy="quantile"
                      )
label_quantile = dis.fit_transform(income)  # 转换器
label_quantile

 

Out[13]:

 

array([[0.],
       [0.],
       [1.],
       [2.],
       [1.],
       [2.],
       [2.],
       [1.],
       [2.],
       [0.]])

 

In [14]:

 

dis.bin_edges_  # 分箱边界

 

Out[14]:

 

array([array([  0.,  20.,  50., 150.])], dtype=object)

 

In [15]:

 

sort_df  # 排序后的数据

 

Out[15]:

 

[0, 10, 14, 20, 35, 49, 50, 78, 88, 150]

 

聚类分箱

 

聚类分箱指的是先对连续型变量进行聚类,然后所属样本的类别作为标识来代替原来的数值。

 

In [16]:

 

from sklearn import cluster

 

In [17]:

 

kmeans = cluster.KMeans(n_clusters=3)
kmeans.fit(income)

 

Out[17]:

 

KMeans(n_clusters=3)

 

聚类完成后查看每个样本所属的类别:

 

In [18]:

 

kmeans.labels_

 

Out[18]:

 

array([1, 1, 1, 2, 1, 0, 0, 0, 0, 1], dtype=int32)

 

使用KBinsDiscretizer来实施聚类分箱:

 

In [19]:

 

dis = KBinsDiscretizer(n_bins=3,
                       encode="ordinal",
                       strategy="kmeans"
                      )
label_kmeans = dis.fit_transform(income)  # 转换器
label_kmeans

 

Out[19]:

 

array([[0.],
       [0.],
       [0.],
       [2.],
       [0.],
       [1.],
       [0.],
       [0.],
       [1.],
       [0.]])

 

In [20]:

 

dis.bin_edges_  # 分箱边界

 

Out[20]:

 

array([array([  0.        ,  54.21428571, 116.5       , 150.        ])],
      dtype=object)

 

3种方法对比

 

In [21]:

 

df["label_uniform"] = label_uniform
df["label_quantile"] = label_quantile
df["label_kmeans"] = label_kmeans
df

 

 

参考

 

 

    1. 特征离散化(分箱)综述:

zhuanlan.zhihu.com/p/68865422

    1. 书籍《特征工程入门与实践》

 

    1. sklearn官网:

scikit-learn.org/stable/modu…

Be First to Comment

发表回复

您的电子邮箱地址不会被公开。