这里需要了解两件事可能会有所帮助:(1) patsy 默认情况下包含拦截(有一个不可见的拦截)1 +
在每个公式的开头),以及(2)在对分类值进行编码时,patsy 自动选择一种编码策略,以避免创建过度参数化的模型。
如果将截距 + 全秩 one-hot 编码结合起来,那么您将得到一个过度参数化的模型。因此 Patsy 切换到处理编码(= 基本上从您正在考虑的 one-hot 编码中删除一列)。这可以避免在编码列和截距列之间产生线性相关性。
避免这种情况的一个简单方法是删除截距——然后 patsy 就不会担心线性依赖性,并且将使用您期望的那种 one-hot 编码:y ~ -1 + a
(the -1
抵消掉不可见的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)
.