【问题标题】:One-hot encoding using model.matrix使用 model.matrix 的 One-hot 编码
【发布时间】:2020-09-18 20:02:13
【问题描述】:

model.matrix 中有一些我不明白的地方。当我输入一个没有截距的二进制变量时,它返回两个级别。

> temp.data <- data.frame('x' = sample(c('A', 'B'), 1000, replace = TRUE))
> temp.data.table <- model.matrix( ~ 0 + x, data = temp.data)
> head(temp.data.table)
  xA xB
1  1  0
2  0  1
3  0  1
4  0  1
5  1  0
6  0  1

但是,当我输入另一个二进制级别时,它只会创建 3 列。这是为什么?是什么让函数的行为突然不同?我该如何避免呢?

> temp.data <- data.frame('x' = sample(c('A', 'B'), 1000, replace = TRUE),
+                         'y' = sample(c('J', 'D'), 1000, replace = TRUE))
> temp.data.table <- model.matrix( ~ 0 + x + y, data = temp.data)
> head(temp.data.table)
  xA xB yJ
1  0  1  0
2  0  1  1
3  0  1  1
4  0  1  0
5  1  0  1
6  0  1  0

【问题讨论】:

    标签: r one-hot-encoding


    【解决方案1】:

    您需要使用factors 并将contrasts 设置为FALSE。试试这个:

    n <- 10
    temp.data <- data.frame('x'=sample(c('A', 'B'), n, replace=TRUE),
                            'y'=factor(sample(c('J', 'D'), n, replace=TRUE)))
    model.matrix( ~ 0 + x + y, data=temp.data,
                  contrasts=list(y=contrasts(temp.data$y, contrasts=FALSE)))
    
    #    xA xB yD yJ
    # 1   0  1  1  0
    # 2   1  0  0  1
    # 3   0  1  1  0
    # 4   1  0  0  1
    # 5   0  1  0  1
    # 6   1  0  1  0
    # 7   1  0  1  0
    # 8   0  1  1  0
    # 9   0  1  0  1
    # 10  0  1  1  0
    # attr(,"assign")
    # [1] 1 1 2 2
    # attr(,"contrasts")
    # attr(,"contrasts")$x
    # [1] "contr.treatment"
    # 
    # attr(,"contrasts")$y
    #   D J
    # D 1 0
    # J 0 1
    

    要了解为什么会发生这种情况,请尝试:

    contrasts(temp.data$y)
    #   J
    # D 0
    # J 1
    
    contrasts(temp.data$y, contrasts=F)
    #   D J
    # D 1 0
    # J 0 1
    

    使用您的 x 变量,这会通过设置 0 + 来删除拦截自动发生。 (其实x也应该编码为factor)。

    原因是,在线性回归中,因子变量的水平通常与参考水平(您可以使用relevel 更改)进行比较。在您的模型矩阵中,使用0 +,您可以删除第一个变量的截距,但不会删除以下变量(尝试model.matrix( ~ 0 + y + x, data=temp.data),您只会得到一个x,但会删除y)。这是在标准contrasts 设置中使用默认处理对比确定的。

    您可能需要阅读 Rose Maier (2015) 的相关帖子,详细解释这一点:

    【讨论】:

    • 为什么会这样?我理解将具有 k 级的因子编码为 k - 1 列的想法。但如果是这样,为什么不对每个因素都这样做呢?如果我们删除截距,为什么它不将每个因素映射到级别数。我正在为它背后的逻辑而苦苦挣扎。
    • 谢谢,我不确定你会得到答案,但为什么它会以某种方式表现呢? (使用一个无截距的分类变量与两个分类变量的区别)。
    • @Kozolovska Why 是一个相当哲学的问题 :) 但这就是最普遍需要的方式,因此也是最普遍的。我在答案中添加了更多关于逻辑的解释。
    • 非常感谢您的帮助。我或多或少知道,我认为这在 model.matrix 中有点奇怪,因为我认为如果我不想要拦截,它应该暗示所有因素都不应该有一个。
    • 我认为这种行为的原因是为了确保设计矩阵是满秩的(当输入变量也是线性无关时)。由于model.matrix 旨在构建线性模型的设计矩阵,因此作为默认行为是有意义的。
    【解决方案2】:

    您需要重新设置因子变量的对比度。见this post

    temp.data <- data.frame('x' = sample(c('A', 'B'), 1000, replace = TRUE),
    +                         'y' = sample(c('J', 'D'), 1000, replace = TRUE))
    
    dat = model.matrix(~ -1 +., data=temp.data, contrasts.arg = lapply(temp.data[,1:2], contrasts, contrasts=FALSE))
    head(dat)
    
      xA xB yD yJ
    1  0  1  0  1
    2  1  0  0  1
    3  1  0  0  1
    4  1  0  0  1
    5  0  1  1  0
    6  0  1  0  1
    

    【讨论】:

      猜你喜欢
      • 2019-06-28
      • 2017-06-21
      • 1970-01-01
      • 1970-01-01
      • 2021-04-14
      • 2019-07-14
      • 2019-11-18
      • 2020-02-08
      • 2020-11-15
      相关资源
      最近更新 更多