【问题标题】:How to one hot encode unordered discrete data in python?如何在python中对无序离散数据进行热编码?
【发布时间】:2018-12-28 18:18:37
【问题描述】:

问题

似乎没有简单的方法来对没有顺序的数据进行一次热编码。我的问题是,单热编码没有特定顺序的值的最佳方法是什么?如果没有标准化的方法来做到这一点,为什么要订购 one-hot-encoded 功能?

示例

我正在尝试对一组特性进行单热编码,其中值是自定义对象。我的对象如下所示:

class MyObject(object)
    def __init__(self, identity):
        self.identity = identity

    def __hash__(self):
        return self.identity

    def __eq__(self, other):
        return self.identity == other.identity

在此设置中,可以比较 MyObject 的每个实例是否相等。假设我们有以下对象列表:

objects = [MyObject(0), MyObject(1), MyObject(0)]

函数set(objects) 产生一组2 个对象,即MyObject(0)MyObject(1)。这确实是我所期望的行为。因此,当我尝试对这些数据进行一次热编码时,我会期望以下形式的内容:

index   MyObject_0, MyObject_1
    0            1           0
    1            0           1
    2            1           0

但是,我尝试过的所有解决方案都需要对数据进行一次热编码以具有某种顺序,而在我的情况下这是未定义的。我认为,如果订单未定义,则应该仍然可以使用 one-hot-encoding,因为在这种情况下,哪个 one-hot-encoded 功能在另一个之前并不重要。

尝试的解决方案

熊猫数据框

我第一次尝试的解决方案是使用 pandas 的 get_dummies() 函数。

import pandas as pd

objects   = [MyObject(0), MyObject(1), MyObject(0)]
dataframe = pd.DataFrame({'MyObjectFeature': objects})
dummies   = pd.get_dummies(dataframe)

但是,这个例子给出了一个 TypeError:

TypeError: 'values' is not ordered, please explicitly specify the categories order by passing in a categories argument.

Scikit-learn LabelEncoder & OneHotEncoder

我的第二次尝试是使用 Scikit-learn 的 LabelEncoder 对值进行编码,然后将它们放入 OneHotEncoder 对象中。但是,在LabelEncoder 中出现了与使用 Pandas 数据帧相同的问题。

from sklearn.preprocessing  import LabelEncoder, OneHotEncoder

objects = [MyObject(0), MyObject(1), MyObject(0)]
encoder = LabelEncoder()
dummies = encoder.fit_transform(objects)

这个例子也给出了一个 TypeError:

TypeError: '<' not supported between instances of 'MyObject' and 'MyObject'

自定义解决方案

我还创建了自己的UnorderedLabelEncoder 对象来对标签进行编码,而无需订购。这很好用,但我想知道我的问题是否有标准解决方案,即使用知名库。或者如果不是这种情况,我想知道是否有需要订购功能的理由?

class UnorderedLabelEncoder(object):

    def __init__(self):
        """ CustomLabelEncoder is capable of handling any
            hashable object including None values.
            """
        self.classes_ = dict()

    def fit(self, y):
        """ Fit label encoder.

            Parameters
            ----------
            y : array-like of shape (n_samples,)
                Target values.

            Returns
            -------
            self : returns an instance of self.
            """
        self.classes_ = {o:i for i, o in enumerate(set(y))}
        return self

    def fit_transform(self, y):
        """ Fit label encoder and return encoded labels.

            Parameters
            ----------
            y : array-like of shape [n_samples]
                Target values.

            Returns
            -------
            y : array-like of shape [n_samples]
        """
        self.fit(y)
        return self.transform(y)

    def transform(self, y):
        """ Transform labels to normalized encoding.

            Parameters
            ----------
            y : array-like of shape [n_samples]
                Target values.

            Returns
            -------
            y : array-like of shape [n_samples]
        """
        return np.array([self.classes_.get(x, -1) for x in y])

问题

重申一下:我的问题是,对没有特定顺序的值进行一次热编码的最佳方法是什么?如果没有标准化的方法来做到这一点,为什么要订购 one-hot-encoded 功能?

【问题讨论】:

    标签: python pandas one-hot-encoding


    【解决方案1】:

    我会说,如果值没有源自其类型的内在顺序(部分顺序),那么您可以人为地定义顺序(类似于数据库中的人工主键)。然后这是您对数据施加的顺序,然后您可以使用任何可用于有序数据的方法(就好像一开始就有 [部分] 顺序)。

    【讨论】:

    • 嗨 sophros,是的,确实如此。在我的示例中,我可以通过实现 =、> 轻松地强加一个命令。但是,在我的实际程序中,我没有像本例那样使用MyObject 对象,而是我无法控制的对象。因此,我无法(除非解决这个问题)添加直接在类中强制执行订单的方法。您知道在这种情况下是否有任何下达命令的方法?
    • 如果这是您想要的,为什么不 decorate 您的班级添加排序运算符?
    • 正确。 @ThijsvanEde 这就是图书馆(熊猫和scikit)所做的。他们只(暂时)从类别中创建数字,因为可以轻松快速地处理数字。之后,他们将按照您的预期返回数据。
    • @Thijs van Ede - 既然它有帮助,请您接受答案吗?
    • 它有帮助,但它没有回答我的问题,因为引入人工顺序不应该是 one-hot 编码的必要条件。
    猜你喜欢
    • 2021-11-16
    • 2020-11-14
    • 1970-01-01
    • 2016-10-23
    • 2021-12-29
    • 1970-01-01
    • 2022-09-27
    • 2018-04-28
    • 2018-12-17
    相关资源
    最近更新 更多