Scikit-Learn的LabelEncoder、OneHotEncoder、LabelBinarizer的区别

Scikit-Learn中提供了几个对分类变量进行独热编码的转换量(transformer):LabelEncoder、OneHotEncoder、LabelBinarizer。可能是由于版本的差异,在实际使用过程中和《Scikit-Learn与TensorFlow机器学习实用指南》的运行结果略有不同。故在本文中对三者做个简单梳理。
我的sklearn版本是0.20.0,Python是3.7.0 on Windows x64,本文使用房价数据进行测试。

>>> import sklearn
>>> sklearn.__versions__
0.20.0

首先导入数据源,提取需要处理的字段。

>>> import pandas as pd
>>> housing = pd.read_csv("housing/housing.csv")
>>> attrib_cat = housing["ocean_proximity"]
>>> attrib_cat.describe()
count         20640
unique            5
top       <1H OCEAN
freq           9136
Name: ocean_proximity, dtype: object

要处理的字段存储在attrib_cat变量中,包含5个类型,共计20640个样本,类型是pands的Series。接下来开始依次使用以上三个转换量来将其转换为独热编码:

LabelEncoder

>>> from sklearn.preprocessing import LabelEncoder, OneHotEncoder, LabelBinarizer
>>> LabelEncoder?
Encode labels with value between 0 and n_classes-1.
...
It can also be used to transform non-numerical labels (as long as they are
hashable and comparable) to numerical labels.

LabelEncoder可以将值转换为0~n-1个类型,也可以用来将非数值的标签转换为数值标签(需要确保非数值标签是可比的和可哈希的)。
Sklearn的API设计的比较巧妙,所有转换的过程都比较类似:

>>> le = LabeEncoder()
>>> letrans = le.fit_transform(attrib_cat)
>>> letrans
array([3, 3, 3, ..., 1, 1, 1])

分类变量被转换成由数值做成的数组(array)。获取独热编码还需要使用OneHotDecoder(),书中介绍的第一种方法也是这个流程。

>>> oh = OneHotDecoder()
>>> oh.fit_transform(letrans)
ValueError: Expected 2D array, got 1D array instead:
array=[3 3 3 ... 1 1 1].
Reshape your data either using array.reshape(-1, 1) if your data has a single feature or array.reshape(1, -1) if it contains a single sample.

OneHotDecoder接受的数据需要是2维数组,错误提示很明显,书中也提到了这一点,这里仅仅作为提示。OneHotDecoder的介绍后面再整理。

>>> oh.fit_transform(letrans.reshape(-1,1))
<20640x5 sparse matrix of type '<class 'numpy.float64'>'
        with 20640 stored elements in Compressed Sparse Row format>

输出结果是SciPy的稀疏矩阵,为了减少内存的占用。调用toarray()可以将其转换为NumPy的数组。

OneHotDecoder

>>> OneHotDecoder?
Encode categorical integer features as a one-hot numeric array.

The input to this transformer should be an array-like of integers or
strings, denoting the values taken on by categorical (discrete) features.
The features are encoded using a one-hot (aka 'one-of-K' or 'dummy')
encoding scheme. This creates a binary column for each category and
returns a sparse matrix or dense array.

By default, the encoder derives the categories based on the unique values
in each feature. Alternatively, you can also specify the `categories`
manually.
The OneHotEncoder previously assumed that the input features take on
values in the range [0, max(values)). This behaviour is deprecated.

This encoding is needed for feeding categorical data to many scikit-learn
estimators, notably linear models and SVMs with the standard kernels.

Note: a one-hot encoding of y labels should use a LabelBinarizer
instead.

OneHotEncoder将数值型的特征转换为独热编码的数值型数组。接收的输入是类数组的数值和字符串变量,依次来代表分类(离散)特征。这些特征会被按照热点编码的方式进行转换。为每个类型创建一个二元的栏,返回一个稀疏矩阵或者密集数组。
该转换量默认以各个属性的唯一值作为分类依据。但也支持通过categories参数手动设置。
之前版本的OneHotEncoder假设输入属性的值在[0, max(values)]的范围,我用的版本已经被移除。
注意: 对预测属性的独热编码应该使用LabelBinarizer来进行。
上例中已经演示了OneHotEncoder对数值型数组的转换,但文档中可以看到它可以直接对字符类的数组进行独热编码,这里来尝试一下。

>>> oh.fit_transform(np.array(attrib_cat).reshape(-1,1))
<20640x5 sparse matrix of type '<class 'numpy.float64'>'
        with 20640 stored elements in Compressed Sparse Row format>

确实可以完成上一个例子中两步才能进行的操作。

LabelBinarizer

LabelBinarizer?
Binarize labels in a one-vs-all fashion

Several regression and binary classification algorithms are
available in scikit-learn. A simple way to extend these algorithms
to the multi-class classification case is to use the so-called
one-vs-all scheme.

At learning time, this simply consists in learning one regressor
or binary classifier per class. In doing so, one needs to convert
multi-class labels to binary labels (belong or does not belong
to the class). LabelBinarizer makes this process easy with the
transform method.

At prediction time, one assigns the class for which the corresponding
model gave the greatest confidence. LabelBinarizer makes this easy
with the inverse_transform method.

LabelBinarizer顾名思义将标签转换为一对多的形式。
为了将而分类或者回归算法扩展到多分类,我们需要将标签转换为一对多的形式。
在训练过程中,通常包含了为每个类学习二分类模型或者回归模型。为了实现这个目的,我们需要将多分类标签转换为而分类标签(属于某类或者不属于某类)。LabelBinerizer是这个转换的过程变得比较简单。
在预测阶段,LabelBinerizer也可以方便得将预测结果转换成多分类标签。

>>> lbe = LabelBinerizer()
>>> lbe.fit_transform(attrib_cat)
array([[0, 0, 0, 1, 0],
       [0, 0, 0, 1, 0],
       [0, 0, 0, 1, 0],
       ...,
       [0, 1, 0, 0, 0],
       [0, 1, 0, 0, 0],
       [0, 1, 0, 0, 0]])

LabelBinarizer相当于集合了LabeEncoder和OneHotEncoder的过程,同时相比与OneHotEncoder,他的操作更简单:直接接受pandas的Series格式数据,默认输出密集的NumPy数组,dtype是int32。

总结

梳理过后,三个转换量的区别就比较明显了:

  1. 描述
    • LabelEncoder :将类型变量转换为数值组成的数组。
    • OneHotEncoder:将数值类型属性转换成独热编码的数值型数组。
    • LabelBinerizer: 将标签二值化为一对多的形式。
  2. fit_transform的输入
    • LabelEncoder :pd.Series/np.array, 可哈希、可比的非数值或者数值, ndim=1。
    • OneHotEncoder:np.array,可比的非数值或者数值,ndim=2。
    • LabelBinerizer: pd.Series/np.array, 可哈希、可比的非数值或者数值,ndim=1。
  3. fit_transform的默认输出
    • LabelEncoder :np.array, dtype=int64。
    • OneHotEncoder:SciPy.Sparse Matrix, dtype=float64。
    • LabelBinerizer: np.array, dtype=int32。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容

  • 先决条件 在阅读这个教程之前,你多少需要知道点python。如果你想从新回忆下,请看看Python Tutoria...
    舒map阅读 2,570评论 1 13
  • NumPy是Python中关于科学计算的一个类库,在这里简单介绍一下。 来源:https://docs.scipy...
    灰太狼_black阅读 1,222评论 0 5
  • 基础篇NumPy的主要对象是同种元素的多维数组。这是一个所有的元素都是一种类型、通过一个正整数元组索引的元素表格(...
    oyan99阅读 5,112评论 0 18
  • 在机器学习和数据挖掘的应用中,scikit-learn是一个功能强大的python包。在数据量不是过大的情况下,可...
    城市中迷途小书童阅读 1,161评论 0 16
  • Numpy的组成与功能 Numpy(Numeric Python)可以被理解为一个用python实现的科学计算包,...
    不做大哥好多年阅读 4,271评论 0 10