【问题标题】:One-hot encoding in patsypatsy 中的 One-hot 编码
【发布时间】:2019-09-06 21:15:55
【问题描述】:

对于回归,我通常使用 sklearn 的 OneHotEncoder 对分类变量进行编码。

我现在正在探索使用 patsy,但它似乎不提供 One-hot 编码:http://patsy.readthedocs.io/en/latest/categorical-coding.html

是否可以使用 patsy 指定 One-hot 编码?

【问题讨论】:

    标签: python machine-learning scikit-learn patsy


    【解决方案1】:

    这里有两件事可能会有所帮助:(1) patsy 默认包含一个截距(在每个公式的开头都有一个不可见的 1 +),以及 (2) 编码分类值时,自动 patsy选择避免创建过度参数化模型的编码策略。

    如果您将截距 + 全秩 one-hot 编码结合起来,那么您将得到一个过度参数化的模型。因此,patsy 切换到处理编码(= 基本上从您正在考虑的 one-hot 编码中删除一列)。这样可以避免在编码列和截距列之间产生线性依赖关系。

    避免这种情况的一个简单方法是删除截距 - 这样 patsy 就不会担心线性相关性,而是会使用您所期望的那种单热编码:y ~ -1 + a(@987654323 @ 取消不可见的1 以消除拦截)。

    或者,如果您真的想要一个过度参数化的模型,那么如果您在链接到的文档页面上进一步向下滚动,它会告诉您如何定义任意自定义编码方案。

    import numpy as np
    from patsy import ContrastMatrix
    
    class FullRankOneHot(object):
        def __init__(self, reference=0):
            self.reference = reference
    
        # Called to generate a full-rank encoding
        def code_with_intercept(self, levels):
            return ContrastMatrix(np.eye(len(levels)),
                                  ["[My.%s]" % (level,) for level in levels])
    
        # Called to generate a non-full-rank encoding. But we don't care,
        # we do what we want, and return a full-rank encoding anyway.
        # Take that, patsy.
        def code_without_intercept(self, levels):
            return self.code_with_intercept(levels)
    

    然后你可以像这样使用它:y ~ 1 + C(a, FullRankOneHot)

    【讨论】:

      【解决方案2】:

      您提供的链接中的第一个示例确实是单热编码:

      In [3]: data
      Out[3]: {'a': ['a1', 'a2', 'a3', 'a1', 'a2', 'a3']}
      
      In [4]: dmatrix("a", data)
      Out[4]: 
      DesignMatrix with shape (6, 3)
        Intercept  a[T.a2]  a[T.a3]
                1        0        0
                1        1        0
                1        0        1
                1        0        0
                1        1        0
                1        0        1
        Terms:
          'Intercept' (column 0)
          'a' (columns 1:3)
      

      请注意,要对具有 3 个级别的分类变量进行编码,您只需要 2 个二进制变量。本文档中的编码以a1 为基础,并为a2a3 添加了另外两个二进制变量。如果a2a3 都为0,则表示该值为a1

      在 sklearn 的 OneHotEncoder 或 pandas 的 pd.get_dummies() 中,它们返回一个矩阵,其列数与分类变量的级别相同,但包含一个额外的列,因为您可以用其他列中的值。

      【讨论】:

      • 我希望 patsy 显式返回额外的列,就像在 sklearn 中一样。这样我就可以直接解释每个级别的系数,而不必在截距的上下文中解释它们。那可能吗?或者 patsy 中有后处理工具吗?
      • @DontDivideByZero 如果你有一个过度参数化的模型(就像你对所有值都有一个截距和一个热编码时所做的那样),那么你最终会得到一个具有不同系数的等效模型的无限空间,并且您的拟合代码任意选择其中之一。因此,无论如何尝试解释这些系数可能是个坏主意。有无数种不同的系数同样有效。
      • 当你使用正则化时,这种过度参数化会消失
      猜你喜欢
      • 2019-11-18
      • 2017-06-21
      • 1970-01-01
      • 2021-08-05
      • 2021-04-14
      • 2020-09-18
      • 2019-07-14
      • 2020-02-08
      • 2016-11-15
      相关资源
      最近更新 更多