【问题标题】:Adding Gaussian noise to each element of rows of a matrix efficiently有效地将高斯噪声添加到矩阵行的每个元素
【发布时间】:2021-09-17 03:59:50
【问题描述】:

我有一个矩阵m:

set.seed(1)
m = matrix(rnorm(100), nrow = 10, ncol = 10) # my data is not a random matrix in reality, but it should not matter

我想为矩阵的每一行添加 5% Gaussian 噪声。矩阵行的每个元素都应该得到不同的随机噪声。应根据每行的sd 逐行计算随机值。

到目前为止,我已经用 for loop 实现了它,它似乎可以完成这项工作:

for (i in 1:nrow(m)){
        m[i, ] = m[i, ] + rnorm(n = ncol(m), mean = 0, sd = sd(m[i, ]) * 0.05)
}

但是,我的真实数据非常大,我想尽可能地将这个实现向量化。

【问题讨论】:

    标签: r for-loop matrix vectorization


    【解决方案1】:

    这可以解决问题:

    require(tidyverse)
    
    set.seed(1)
    m = matrix(rnorm(9), nrow = 3, ncol = 3)
    
    > m
               [,1]       [,2]      [,3]
    [1,] -0.6264538  1.5952808 0.4874291
    [2,]  0.1836433  0.3295078 0.7383247
    [3,] -0.8356286 -0.8204684 0.5757814
    

    逐行计算sd

    m_sd <- apply(m, 1, sd)
    

    按行计算噪声并将其放入矩阵中

    m_noise <- map(m_sd, rnorm, n = nrow(m), mean = 0) %>% 
      unlist %>% 
      matrix(nrow = 3, ncol = 3, byrow = TRUE)
    

    添加原始和噪声矩阵

    m + m_noise * 0.05
    
    > m + m_noise * 0.05
               [,1]       [,2]      [,3]
    [1,] -0.6434161  1.6792503 0.5090823
    [2,]  0.1747117  0.2976669 0.7544979
    [3,] -0.8374496 -0.8211245 0.6140321
    

    【讨论】:

      【解决方案2】:

      一种方法是这样的......

      #calculate the sd for each row...
      sds <- apply(m, 1, sd)
      
      #generate all noise factors at once and just add to m...
      m <- m + rnorm(nrow(m) * ncol(m), mean = 0, sd = sds * 0.05)
      

      这是有效的,因为 sds 将为每一列回收。一般来说,这些矩阵运算在 R 中非常快。

      【讨论】:

      • nrow(m) * ncol(m) == length(m) m 是一个矩阵
      • 这比我的解决方案更优雅 - 不知道回收。谢谢
      • 如果你乐于使用非base 包,我认为matrixStats::rowSds 比apply 快。
      • @bird rnorm 调用需要nrow * ncol 的sd 值,但sds 只有nrow 长,所以它只是根据需要重复它多次。这是 R 的一般特性,通常非常有用! m 只是一个向量(具有矩阵属性),它一个接一个地保存矩阵列。因此,噪声值对应于环绕的行。
      • @bird 后半部分的另一种表达方式:在 R 中,矩阵位于 column-major order 中。因此,矩阵按该顺序填充值(但请注意matrix 中的byrow 参数)。因为随机值是使用 sd 生成的,这些值是按行计算并在 rnorm 中回收的,所以这些值最终会以列为主填充顺序出现在正确的行中。
      猜你喜欢
      • 1970-01-01
      • 2016-01-25
      • 2011-09-12
      • 2022-01-20
      • 2013-10-14
      • 1970-01-01
      • 2016-02-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多