【问题标题】:R: Comparing the Time for Random SearchesR:比较随机搜索的时间
【发布时间】:2022-01-20 21:34:14
【问题描述】:

我正在使用 R 编程语言。

我正在尝试使用带替换的随机搜索和不带替换的随机搜索来优化 Rastrign 函数

Rastrigin <- function(x1, x2)
{
  20 + x1^2 + x2^2 - 10*(cos(2*pi*x1) + cos(2*pi*x2))
}

x1 <- x2 <- seq(-5.12, 5.12, by = 0.1)
f <- outer(x1, x2, Rastrigin)

第 1 部分:带替换的随机搜索:

为了进行替换采样,我生成了 100 个点(我将这些点转换为整数格式,以便更容易查看 第 2 部分中哪些点是重复的),然后在这 100 个点上评估函数点。然后我提取了对应于函数最小值的数据行。我还记录了所用的时间:

start.time <- Sys.time()

x1 = as.integer(rnorm(100,5,5))
x2 = as.integer(rnorm(100,5,5))
func_value = 20 + x1^2 + x2^2 - 10*(cos(2*pi*x1) + cos(2*pi*x2))

frame = data.frame(x1,x2,func_value)

sort_frame <- frame[order(func_value),]

final_answer = sort_frame[1,]

end.time <- Sys.time()
time.taken <- end.time - start.time

time.taken

Time difference of 0.01810408 secs

第 2 部分:没有替换的随机搜索:

由于我不知道如何为传统方式编写代码来执行不带替换的随机搜索(即生成随机值,看看这个生成的值是否已经发生:如果没有,则在这个值处评估函数,否则生成新的值,直到生成一个看不见的值) - 因为我想以 100 个值评估函数,所以我决定生成 200 个值,希望这 200 个值中至少有 100 个值是唯一的。然后,我重复了上面的过程:

start.time <- Sys.time()

x1 = as.integer(rnorm(200,5,5))
x2 = as.integer(rnorm(200,5,5))

frame = data.frame(x1,x2)
de_duplicated = frame[!(duplicated(frame) | duplicated(frame, fromLast = TRUE)), ]

#check to make sure at least 100 values in "de_duplicated"

ifelse(nrow(de_duplicated)<100, "BAD", "GOOD")

[1] "GOOD"

#only keep 100 values in de_duplicated:

de_duplicated = de_duplicated[1:100,]

func_value = 20 + de_duplicated$x1^2 + de_duplicated$x2^2 - 10*(cos(2*pi*de_duplicated$x1) + cos(2*pi*de_duplicated$x2))

final_frame = data.frame(de_duplicated$x1,de_duplicated$x2,func_value)

sort_frame <- final_frame[order(func_value),]

final_answer = sort_frame[1,]

end.time <- Sys.time()
time.taken <- end.time - start.time

time.taken

Time difference of 0.03689885 secs

我的问题:因为我有兴趣比较 Part 1Part 2 的时间 - 我认为这不公平,因为我以非常“笨拙”的方式编写了第 2 部分的代码。

如果您以更“传统”的方式编写第 2 部分的代码,即使用“while 循环” - 这会减少 第 2 部分所需的时间>? C有人请告诉我如何做到这一点 - 使用“while 循环”编写不带替换的随机搜索(即第 2 部分)实际上是传统的方法吗?

谢谢!

【问题讨论】:

    标签: r loops optimization random while-loop


    【解决方案1】:

    以下是我可以在整数值处对函数进行采样的示例方法,无论是否替换:

    set.seed(123)
    
    fSearchReplace <- function() {
      # sampling with replacement
      x1 <- as.integer(rnorm(100, 5, 5))
      x2 <- as.integer(rnorm(100, 5, 5))
      func_value <- 20 + x1^2 + x2^2 - 10*(cos(2*pi*x1) + cos(2*pi*x2))
      idxMin <- which.min(func_value)
      frame <- data.frame(x1 = x1[idxMin], x2 = x2[idxMin], func_value = func_value[idxMin])
    }
    
    fSearchNoReplace1 <- function() {
      # sampling without replacement by rejection
      frame <- unique.data.frame(data.frame(x1 = as.integer(rnorm(200, 5, 5)), x2 = as.integer(rnorm(200, 5, 5))))
      
      while (nrow(frame) < 100L) {
        sz <- (100L - nrow(frame))*2L
        frame <- unique.data.frame(rbind(frame, data.frame(x1 = as.integer(rnorm(sz,5,5)), x2 = as.integer(rnorm(sz, 5, 5)))))
      }
      
      func_value <- 20 + frame[1:100,]$x1^2 + frame[1:100,]$x2^2 - 10*(cos(2*pi*frame[1:100,]$x1) + cos(2*pi*frame[1:100,]$x2))
      idxMin <- which.min(func_value)
      frame <- data.frame(x1 = frame$x1[idxMin], x2 = frame$x2[idxMin], func_value = func_value[idxMin])
    }
    
    fSearchNoReplace2 <- function() {
      # sampling without replacement using weights
      p <- diff(pnorm(-15.5:5.5, 5, 5))
      w1 <- c(p, rev(head(p, -1)))
      frame <- setNames(expand.grid(rep(list(-15:25), 2))[sample(1681, 100, prob = outer(w1, w1)),], c("x1", "x2"))
      frame$func_value <- 20 + frame$x1^2 + frame$x2^2 - 10*(cos(2*pi*frame$x1) + cos(2*pi*frame$x2))
      frame <- frame[which.min(frame$func_value),]
    }
    
    print(fSearchReplace(), row.names = FALSE)
    #>  x1 x2 func_value
    #>   0  0          0
    print(fSearchNoReplace1(), row.names = FALSE)
    #>  x1 x2 func_value
    #>   1  0          1
    print(fSearchNoReplace2(), row.names = FALSE)
    #>  x1 x2 func_value
    #>   0  0          0
    
    microbenchmark::microbenchmark(fSearchReplace(), fSearchNoReplace1(), fSearchNoReplace2())
    #> Unit: microseconds
    #>                 expr   min     lq     mean  median      uq    max neval
    #>     fSearchReplace() 220.7 255.65  298.925  291.60  324.40  490.8   100
    #>  fSearchNoReplace1() 802.0 880.55 1043.916 1027.65 1132.70 2036.8   100
    #>  fSearchNoReplace2() 495.7 530.85  650.703  610.35  679.65 2779.4   100
    

    注意:如果搜索限制为整数,rnorm 可以被视为无替换抽样。在 100 个中得到两对相同的 x1x2 的概率实际上是 0(这就是为什么 rnorm 没有 replace 参数)。

    【讨论】:

      【解决方案2】:

      如果没有替换,您不会使用 while 循环进行采样。 要么使用sample,它有一个参数replace。 或者使用指定向量的某种形式的随机排序:

      x <- 1:10
      ## [1]  1  2  3  4  5  6  7  8  9 10
      
      x[order(runif(length(x)))]
      ## [1]  6  8  2  5  3  7  1 10  9  4
      

      【讨论】:

        猜你喜欢
        • 2018-11-08
        • 2016-12-10
        • 2015-05-28
        • 1970-01-01
        • 2016-01-09
        • 2014-05-26
        • 2020-11-22
        • 2021-02-09
        • 1970-01-01
        相关资源
        最近更新 更多