【问题标题】:How to handle categorical data for preprocessing in Machine Learning如何处理分类数据以在机器学习中进行预处理
【发布时间】:2019-04-27 22:00:42
【问题描述】:

这可能是一个基本问题,我有一个分类数据,我想将其输入到我的机器学习模型中。我的 ML 模型只接受数字数据。将此分类数据转换为数值数据的正确方法是什么。

我的示例 DF:

  T-size Gender  Label
0      L      M      1
1      L      M      1
2      M      F      1
3      S      F      0
4      M      M      1
5      L      M      0
6      S      F      1
7      S      F      0
8      M      M      1

我知道以下代码将我的分类数据转换为数字

类型 1:

df['T-size'] = df['T-size'].cat.codes

以上行只是将类别从 0 转换为 N-1。它不遵循它们之间的任何关系。

对于这个例子,我知道 S

类型 2:

在这种类型中我没有M和F之间的关系。但我可以看出M的概率比F的概率大。即,样本为 1 / 样本总数

男性,

(4/5)

对于女性,

(2/4)

WKT,

(4/5) > (2/4)

我应该如何替换这种列?

对于这个问题,我可以用 (4/5) 替换 M 和用 (2/4) 替换 F 吗?

处理列的正确方法是什么?

帮助我更好地理解这一点。

【问题讨论】:

    标签: python pandas dataframe machine-learning feature-selection


    【解决方案1】:

    对于第一个问题,如果您的类别较少,您可以map带有字典的列。这样就可以设置订单了:

    d = {'L':2, 'M':1, 'S':0}
    df['T-size'] = df['T-size'].map(d)
    

    输出:

       T-size Gender  Label
    0       2      M      1
    1       2      M      1
    2       1      F      1
    3       0      F      0 
    4       1      M      1
    5       2      M      0
    6       0      F      1
    7       0      F      0
    8       1      M      1
    

    对于第二个问题,您可以使用相同的方法,但我将保留男性和女性 01 的 2 个值。如果您只需要类别而不需要对值进行操作,则一个值等于另一个值。

    【讨论】:

    • 感谢您的回答,这里您使用了 s->0、M->2、L->2 的映射值,请问您为什么选择 0,1,2。如果它代表重量,我可以分别使用 10、20、30。它会对我的模型有什么影响吗
    • 我会从最小值0开始,一直增加到最大
    • 我真的不知道要分配什么值。将标量值替换为类别是否足以处理分类数据?
    • 是的,够了
    • 对不起,重复的问题,我真的很想知道,我不需要明确地给予权重吗?
    【解决方案2】:

    如果您想在大小参数中使用层次结构,您可以考虑为其使用线性映射。这将是:

    size_mapping = {"S": 1, "M":2 , "L":3}
    
    #mapping to the DataFrame
    df['T-size_num'] = df['T-size'].map(size_mapping)
    

    这允许您将输入视为数字数据,同时保留层次结构

    至于性别,您误解了重新分区和预处理。如果您已经将重新分区作为输入,您将在数据中引入偏差。您必须将男性和女性视为两个不同的类别,无论它们现有的重新分区如何。你应该用两个不同的数字来映射它,但不要引入比例。

    df['Gender_num'] = df['Gender'].map({'M':0 , 'F':1})
    

    对于比您的问题更详细的解释和更具体的覆盖范围,我建议阅读this article regarding categorical data in Machine Learning

    【讨论】:

    • 感谢您的回答,对于第一个问题,您分配了 1、2、3 我可以知道这背后的原因吗?
    • 你的尺寸参数值的关系是未知的,所以我假设它是线性的。而且由于尺寸是正实体,我将您的最小值设为大于 0。它确保 M 尺寸是 S 尺寸的倍数(当然 L 尺寸也是如此),它不会是对于 S=0、M=1 和 L=3 为真
    • 我很想知道而不是1, 2, 3 我可以使用10, 20, 305, 10, 15 吗?
    • 是的,你可以。最重要的部分是建模元素之间关系的方式。如果将其设置为与 c=3a 和 b=2a 成线性关系,那么无论您使用 1、2 和 3 还是任何其他保持相同线性关系的三元组,您在数据中发现的模式都将保持不变。
    【解决方案3】:

    有很多方法可以对分类数据进行编码,其中一些方法完全取决于您打算如何处理它。例如,如果您计划使用决策树/随机森林/GBM,那么很容易成为最受欢迎的选择的 one-hot-encoding 是 extremely poor choice

    关于你上面的T恤,你可以给熊猫分类类型一个顺序:

    df['T-size'].astype(pd.api.types.CategoricalDtype(['S','M','L'],ordered=True)).
    

    如果您已将您的 T 恤设置为这样,那么您的 .cat.codes 方法将完美运行。这也意味着您可以轻松使用 scikit-learn 的 LabelEconder,它可以完美地融入管道。

    关于你的性别编码,你在使用你的目标变量(你的Label)时需要非常小心。您不想在训练测试拆分之前进行此编码,否则您正在使用您看不见的数据的知识,使其不是真正看不见的。如果您使用交叉验证,这将变得更加复杂,因为您需要在每次 CV 迭代中进行编码(即每次折叠的新编码)。如果你想这样做,我建议你从 skcontribs Category Encoders 中查看TargetEncoder 但同样,一定要在 sklearn Pipeline 中使用它,否则你会弄乱训练测试拆分并从测试集中泄漏信息进入你的训练集。

    【讨论】:

    • ordered的重要性是什么。即 df['T-size'].astype('category') 和 df['T-size'].astype(pd.api.types.CategoricalDtype(['S','M','L'],ordered=True)) 有什么区别
    • 嗯,你说你想确定 S
    • 是的 ;-)
    • 为了澄清You don't want to do this encoding before your train-test split otherwise you're using knowledge of your unseen data making it not truly unseen. 这个声明this encoding 代表哪种编码?你的意思是我对编码的假设对吗?还是你的意思是别的?
    • @MohamedThasinah 从技术上讲,任何编码,尤其是使用目标变量或被编码变量分布的任何编码。
    【解决方案4】:

    对于 M/F 示例来说这可能有点过头了,因为它是二进制的 - 但如果您曾经担心将分类转换为数字形式,请考虑 one hot encoding。它基本上将包含 n 类别的单列延伸到 n 二进制列。

    所以一个数据集:

    Gender
    M
    F
    M
    M
    F
    

    会变成

    Gender_M    Gender_F
    1           0
    0           1
    1           0
    1           0
    0           1
    

    这消除了任何关于一件事比另一件事更“积极”的概念 - 对于具有超过 2 个选项的分类数据来说,这是绝对必须的,其中没有传递的 A > B > C 关系,并且您不想抹黑您的通过强制一个进入您的编码方案来产生结果。

    【讨论】:

    • 谢谢解答,第一部分我看懂了,但是an absolute must for categorical data with more than 2 options, where there's no transitive A > B > C relationship and you don't want to smear your results by forcing one into your encoding scheme.这一点我没看懂。你能说清楚吗?
    • 因此您在示例中概述了两种类型的分类变量,{S,M,L} 是可传递的,因为您可以为它们分配顺序。 {M,F} 不是可传递的,但它是二进制的,因此编码为 {0,1} 可能是可以的。另一种类型的分类变量是有超过 2 个选项但不可排序(即不可传递)的分类变量 - 因此 {Vanilla, Strawberry, Grape} 可能是分类变量中的选项,但如果转换为 {0, 1,2} 引入了一个偏斜,表明当在任意编码之外不存在这种关系时,草莓存在于香草和葡萄“之间”。
    • 很好的解释,非常感谢。对于这个{Vanilla, Strawberry, Grape}一个热编码解决问题吧?
    • 是的,完全正确。也没有什么能阻止您将它用于{M,F}。 One-hot 编码的缺点是会扩展数据的维度,当字段中的类别数量变大时,这可能会成为问题,但请记住,它通常是一个很好的通用选项。
    猜你喜欢
    • 2018-08-18
    • 1970-01-01
    • 2017-12-15
    • 2018-03-07
    • 1970-01-01
    • 2020-06-15
    • 2014-02-17
    • 1970-01-01
    • 2015-08-18
    相关资源
    最近更新 更多