【问题标题】:one hot encoding function一种热编码功能
【发布时间】:2018-10-25 07:59:05
【问题描述】:

我需要创建一个函数,它接受两个整数 xN,其中 N > x 并返回一个维度为 N 的向量,除了组件 x 外,它的向量全为零,其中它有一个1

我设法通过以下方式做到了,

Function=function(x,N){
  vec=rep(0,N)
  r=as.integer(x)
  vec[r]=1
  return(vec)
}

但是当我需要迭代过程并将其应用于大量实现时,速度非常慢。另一方面,我的一个朋友可以用一个 python 函数(我认为是“OneHotEncoder”)来做同样的事情,而且速度非常快。

我想知道 R 中是否有适合此目的的函数。

【问题讨论】:

  • 问题可能在于你如何将此函数应用于更大的案例,而不是函数本身。
  • 不定义自定义函数,可以library(magrittr); integer(N) %>% `[<-`(x, 1L)
  • 您可以使用已经可用的优化方法之一,而不是编写自己的 one-hot 编码器,例如 model.matrix(或 Matrix::sparse.model.matrix,如果您的数据非常大)。如果你在 R 标签中搜索“one hot encoding”或“dummy variables”,你会发现很多例子。

标签: r one-hot-encoding


【解决方案1】:

按照@Axeman 所说的,您应该考虑是否可以以矢量化方式找到单热编码,即类似的方式

set.seed(1234)
x = sample.int(5, size=10, replace=TRUE)
x
#  [1] 1 4 4 4 5 4 1 2 4 3

nC = max(x) #could be also larger (user-defined)
nR = length(x)
matrix(`[<-`(integer(nR * nC),(seq.int(nR) - 1) * nC + x, 1),
       nR, nC, byrow=TRUE)
#       [,1] [,2] [,3] [,4] [,5]
#  [1,]    1    0    0    0    0
#  [2,]    0    0    0    1    0
#  [3,]    0    0    0    1    0
#  [4,]    0    0    0    1    0
#  [5,]    0    0    0    0    1
#  [6,]    0    0    0    1    0
#  [7,]    1    0    0    0    0
#  [8,]    0    1    0    0    0
#  [9,]    0    0    0    1    0
# [10,]    0    0    1    0    0

model.matrix 方法与上面给出的方法进行比较:

#longer input vector
x = sample.int(5, size=1e4, replace=TRUE)

oneHotMtx = function(x) {
  nC = max(x) #could be also larger (user-defined)
  nR = length(x)
  matrix(`[<-`(integer(nR * nC),(seq.int(nR) - 1) * nC + x, 1),
         nR, nC, byrow=TRUE)
}

oneHotMdl = function(x) {
  xf = factor(x)
  model.matrix(~xf+0)
}

oneHotMdl2=function(x) {
  #version without factor conversion
  model.matrix(~x+0)
}

xf = factor(x)
library(microbenchmark)
microbenchmark(oneHotMtx(x),
               oneHotMdl(x),
               oneHotMdl2(xf), times=1e3)

#Unit: microseconds
#          expr      min       lq      mean    median       uq        max neval cld
#  oneHotMtx(x)  386.621  412.510  678.2977  416.4625  435.382   5394.265  1000 a  
#  oneHotMdl(x) 7363.481 7528.230 8823.8435 7629.8850 7851.019 261808.302  1000   c
#oneHotMdl2(xf) 4253.366 4377.784 5059.0979 4471.5315 4638.637 257106.400  1000  b 

【讨论】:

  • 但是为什么要使用这种方法一次对一个变量进行一次热编码,而不是使用model.matrix 一次完成所有这些呢?毫无疑问,这是对 OP 代码的改进,但为什么要停在这里呢?
  • 很好,虽然我认为在模型矩阵运行时包含因子转换并不公平,但我认为更常见的用例将从因子开始。
  • 谢谢@Gregor,我认为您找到了问题所在。到目前为止,我一直在使用 for 循环将该函数应用于大向量的每个分量。 “model.matrix”似乎是我一直在寻找的。我现在就研究一下它是如何工作的。
  • @Gregor 好点 - 添加了另一个没有因子转换的版本。
  • @3sm1r 只需确保您想要一次性编码的任何列都是因素,然后是 mm = model.matrix(response ~ . + 0, data = your_data_frame)
【解决方案2】:

试试

one_hot_encoder <- function(x, N) {
  vec <- integer(N)
  vec[x] <- 1L
  return(vec)
}

【讨论】:

  • 使用 1L 而不是 1 可以避免将 vec 从整数强制转换为数字。
  • 非常感谢你们俩。
【解决方案3】:

@cryo111 答案的更详细的变体:

one_hot_vec <- function(x) {
    nc <- max(x)
    nr <- length(x)
    m <- integer(nr * nc)
    i <- (seq_len(nr) - 1) * nc + x
    m[i] <- 1L
    matrix(m, nrow = nr, ncol = nc, byrow = TRUE)
}

【讨论】:

    猜你喜欢
    • 2019-08-26
    • 2018-06-26
    • 2016-03-19
    • 2019-02-06
    • 1970-01-01
    • 1970-01-01
    • 2021-12-01
    • 2018-12-17
    • 1970-01-01
    相关资源
    最近更新 更多