• 【机器学习】这3种特征分箱方法,一定要理解掌握


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

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

    文末提供详细资料、完整代码及技术交流方式

    图片

    分箱特点

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

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

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

    模拟数据

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

    In [1]:

    import pandas as pd
    import numpy as np
    
    • 1
    • 2

    In [2]:

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

    图片

    sklearn之KBinsDiscretizer类

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

    https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.KBinsDiscretizer.html

    from sklearn.preprocessing import KBinsDiscretizer
    
    sklearn.preprocessing.KBinsDiscretizer(n_bins=5, 
                                           encode='onehot', 
                                           strategy='quantile', 
                                           dtype=None, 
                                           subsample='warn', 
                                           random_state=None)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    全部参数解释:图片

    全部属性信息:

    图片

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

    n_bins

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

    strategy

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

    • 等宽:uniform 策略使用固定宽度的bins;箱体的宽度一致

    • 等频:quantile 策略在每个特征上使用分位数(quantiles)值以便具有相同填充的bins

    • 聚类:kmeans 策略基于在每个特征上独立执行的k-means聚类过程定义bins。

    encode

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

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

    In [3]:

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

    Out[3]:

    array([[  0],
           [ 10],
           [ 20],
           [150],
           [ 35],
           [ 78],
           [ 50],
           [ 49],
           [ 88],
           [ 14]])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    使用之前先导进来:

    In [4]:

    from sklearn.preprocessing import KBinsDiscretizer
    
    • 1

    等宽分箱

    所谓的等宽分箱就是将数据分成等宽的几份,比如模拟数据中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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    Out[5]:

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

    In [6]:

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

    Out[6]:

    array([[0.],
           [0.],
           [0.],
           [2.],
           [0.],
           [1.],
           [1.],
           [0.],
           [1.],
           [0.]])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    等宽分箱的边界查看:

    In [7]:

    dis.bin_edges_
    
    • 1

    Out[7]:

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

    In [8]:

    dis.n_bins
    
    • 1

    Out[8]:

    3
    
    • 1

    等频分箱

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

    • 等频分箱:每个区间内包括的值一样多,pd.qcut

    • 等宽分箱:每两区间之间的距离是一样的,pd.cut

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

    In [9]:

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

    Out[9]:

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

    分成2个类别

    In [10]:

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

    Out[10]:

    42.0
    
    • 1

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

    In [11]:

    dis = KBinsDiscretizer(n_bins=2,
                           encode="ordinal",
                           strategy="quantile"
                          )
    
    dis.fit_transform(income)  # 转换器
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    Out[11]:

    array([[0.],
           [0.],
           [0.],
           [1.],
           [0.],
           [1.],
           [1.],
           [1.],
           [1.],
           [0.]])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    In [12]:

    dis.bin_edges_
    
    • 1

    Out[12]:

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

    分成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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    Out[13]:

    array([[0.],
           [0.],
           [1.],
           [2.],
           [1.],
           [2.],
           [2.],
           [1.],
           [2.],
           [0.]])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    In [14]:

    dis.bin_edges_  # 分箱边界
    
    • 1

    Out[14]:

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

    In [15]:

    sort_df  # 排序后的数据
    
    • 1

    Out[15]:

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

    聚类分箱

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

    In [16]:

    from sklearn import cluster
    
    • 1

    In [17]:

    kmeans = cluster.KMeans(n_clusters=3)
    
    kmeans.fit(income)
    
    • 1
    • 2
    • 3

    Out[17]:

    KMeans(n_clusters=3)
    
    • 1

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

    In [18]:

    kmeans.labels_
    
    • 1

    Out[18]:

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

    使用KBinsDiscretizer来实施聚类分箱:

    In [19]:

    dis = KBinsDiscretizer(n_bins=3,
                           encode="ordinal",
                           strategy="kmeans"
                          )
    
    label_kmeans = dis.fit_transform(income)  # 转换器
    label_kmeans
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    Out[19]:

    array([[0.],
           [0.],
           [0.],
           [2.],
           [0.],
           [1.],
           [0.],
           [0.],
           [1.],
           [0.]])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    In [20]:

    dis.bin_edges_  # 分箱边界
    
    • 1

    Out[20]:

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

    3种方法对比

    In [21]:

    df["label_uniform"] = label_uniform
    df["label_quantile"] = label_quantile
    df["label_kmeans"] = label_kmeans
    
    df
    
    • 1
    • 2
    • 3
    • 4
    • 5

    图片

    参考

    • 特征离散化(分箱)综述:https://zhuanlan.zhihu.com/p/68865422
    • 书籍《特征工程入门与实践》
    • sklearn官网

    联系方式

    目前开通了技术交流群,群友已超过3000人,添加时最好的备注方式为:来源+兴趣方向,方便找到志同道合的朋友,资料、代码获取也可以加入

    方式1、添加微信号:dkl88191,备注:来自CSDN
    方式2、微信搜索公众号:Python学习与数据挖掘,后台回复:加群
    在这里插入图片描述

  • 相关阅读:
    配置MyBatis(不用Maven)
    深度学习 --- stanford cs231学习笔记七(训练神经网络之梯度下降优化器)
    php 把数字转化为大写中文
    数据还可以刷新但是显示不到页面上了
    看着别人月入过万,30岁想转入做软件测试,有什么难度?
    数据挖掘与分析应用:分类算法:k近邻KNN,决策树CART,贝叶斯,支持向量机SVM
    万集wlr718雷达测试记录和stm32h745驱动编写,数据分析
    vue3 watch & watchEffect
    3.4 这些都是小红书的流量入口【玩赚小红书】
    《Vision Permutator: A Permutable MLP-Like ArchItecture For Visual Recognition》论文笔记
  • 原文地址:https://blog.csdn.net/qq_34160248/article/details/126329373