如何在sklearn中对连续属性进行离散化?

dat*_*ner 7 scikit-learn discretization

我的数据包含连续和分类功能的混合.下面是我的数据在csv格式中的一小部分(将其视为由在不同城市运营商店的超级商店链收集的数据)

city,avg_income_in_city,population,square_feet_of_store_area,  store_type ,avg_revenue
NY  ,54504            , 3506908   ,3006                       ,INDOOR    , 8000091
CH  ,44504            , 2505901   ,4098                       ,INDOOR    , 4000091
HS  ,50134            , 3206911   ,1800                       ,KIOSK     , 7004567
NY  ,54504            , 3506908   ,1000                       ,KIOSK     , 2000091
Run Code Online (Sandbox Code Playgroud)

她可以看到avg_income_in_city,square_feet_of_store_area和avg_revenue是连续值,其中city,store_type等是分类类(还有一些我没有在这里展示以保持数据的简洁性).

我希望对数据建模以预测收入.问题是如何使用sklearn"离散"连续值?sklearn是否为连续值的离散化提供了任何"现成的"类/方法?(就像我们在Orange中一样,例如Orange.Preprocessor_discretize(data,method = orange.EntropyDiscretization())

谢谢 !

mar*_*ama 10

更新(2018 年 9 月):从版本开始0.20.0,有一个函数sklearn.preprocessing.KBinsDiscretizer,它使用几种不同的策略提供连续特征的离散化:

  • 统一尺寸的垃圾箱
  • 内部具有“相等”数量样本的箱(尽可能多)
  • 基于 K-means 聚类的 bins

不幸的是,目前,该函数不接受自定义间隔(这对我来说是一个无赖,因为这是我想要的,也是我最终来到这里的原因)。如果你想达到同样的效果,你可以使用 Pandas 函数cut

import numpy as np
import pandas as pd
n_samples = 10
a = np.random.randint(0, 10, n_samples)

# say you want to split at 1 and 3
boundaries = [1, 3]
# add min and max values of your data
boundaries = sorted({a.min(), a.max() + 1} | set(boundaries))

a_discretized_1 = pd.cut(a, bins=boundaries, right=False)
a_discretized_2 = pd.cut(a, bins=boundaries, labels=range(len(boundaries) - 1), right=False)
a_discretized_3 = pd.cut(a, bins=boundaries, labels=range(len(boundaries) - 1), right=False).astype(float)
print(a, '\n')
print(a_discretized_1, '\n', a_discretized_1.dtype, '\n')
print(a_discretized_2, '\n', a_discretized_2.dtype, '\n')
print(a_discretized_3, '\n', a_discretized_3.dtype, '\n')
Run Code Online (Sandbox Code Playgroud)

它产生:

[2 2 9 7 2 9 3 0 4 0]

[[1, 3), [1, 3), [3, 10), [3, 10), [1, 3), [3, 10), [3, 10), [0, 1), [3, 10), [0, 1)]
Categories (3, interval[int64]): [[0, 1) < [1, 3) < [3, 10)]
 category

[1, 1, 2, 2, 1, 2, 2, 0, 2, 0]
Categories (3, int64): [0 < 1 < 2]
 category

[1. 1. 2. 2. 1. 2. 2. 0. 2. 0.]
 float64
Run Code Online (Sandbox Code Playgroud)

请注意,默认情况下,pd.cut返回具有Category类型元素的dtype 的 pd.Series 对象interval[int64]。如果您指定自己labels的 dtype,输出的 dtype 仍将是 a Category,但元素将是 type int64。如果您希望系列具有数字 dtype,则可以使用.astype(np.int64).

我的示例使用整数数据,但它应该与浮点数一样好。


And*_*ler 8

答案是不.scikit-learn中没有binning.正如eickenberg所说,你可能想要使用np.histogram.假设scikit-learn中的特征是连续的,而不是离散的.没有装箱的主要原因可能是大部分sklearn是基于文本,图像特征或来自科学界的数据集开发的.在这些设置中,分箱很少有用.你知道一个免费提供的数据集,其中binning真的有益吗?

  • 实际上我并不认为binning对树有意义,但它可能有助于此数据集上的线性分类器. (3认同)

eic*_*erg 5

您还可以考虑将分类变量呈现为数值,例如通过指示符变量,这一过程也称为单热编码

尝试

from sklearn.preprocessing import OneHotEncoder
Run Code Online (Sandbox Code Playgroud)

并将其适合您的分类数据,然后采用线性回归等数值估计方法。只要类别不是太多(城市可能有点太多),就可以很好地工作。

对于连续变量的离散化,您可以考虑使用调整后的箱大小进行分箱,或者等效地,在直方图归一化后进行均匀分箱。numpy.histogram在这里可能会有帮助。另外,虽然 Fayyad-Irani 聚类未在 中实现sklearn,但请sklearn.cluster随意检查数据的自适应离散化(即使它只是一维),例如通过 KMeans 。