一般在建立分类模型时,当我们进行特征工程的工作经常需要对连续型变量进行离散化的处理,也就是将连续型字段转成离散型字段。
离散化的过程中,连续型变量重新进行了编码。特征离散化后,模型会更稳定,降低了模型过拟合的风险。本文主要介绍3种常见的特征分箱方法:
模拟一份简单的数据和收入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
本文中介绍的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)
全部参数解释:
全部属性信息:
重点解释3个参数的使用:
参数n_bins参数上指定需要分箱的个数,默认是5个
指定不同的分箱策略strategy:KBinsDiscretizer类实现了不同的分箱策略,可以通过参数strategy进行选择:
uniform
策略使用固定宽度的bins;箱体的宽度一致quantile
策略在每个特征上使用分位数(quantiles)值以便具有相同填充的binskmeans
策略基于在每个特征上独立执行的k-means聚类过程定义bins。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
等频分箱指的是每个区间内包含的取值个数是相同的,和等宽分箱的区别:
在实施等频分箱之前,我们需要先对数据进行升序排列,然后取中间值进行分箱
In [9]:
# 1、先排序
sort_df = sorted(df["INCOME"])
sort_df
Out[9]:
[0, 10, 14, 20, 35, 49, 50, 78, 88, 150]
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)
总共是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)
In [21]:
df["label_uniform"] = label_uniform
df["label_quantile"] = label_quantile
df["label_kmeans"] = label_kmeans
df
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/junhongzhang/article/details/126239109
内容来源于网络,如有侵权,请联系作者删除!