【问题标题】:why are these memoised functions different?为什么这些记忆功能不同?
【发布时间】:2015-12-07 03:05:33
【问题描述】:

我发现如果我以两种不同的方式在函数上使用 memoise,我会得到两种不同的行为,我想了解原因。

# Non Memoised function
fib <- function(n) {
  if (n < 2) return(1)
  fib(n - 2) + fib(n - 1)
}

system.time(fib(23))
system.time(fib(24))

library(memoise)

# Memoisation stragagy 1
fib_fast <- memoise(function(n) {
  if (n < 2) return(1)
  fib_fast(n - 2) + fib_fast(n - 1)
})

system.time(fib_fast(23))
system.time(fib_fast(24))

# Memoisation strategy 2
fib_not_as_fast <- memoise(fib)

system.time(fib_not_as_fast(23))
system.time(fib_not_as_fast(24))

策略 1 非常快,因为它重用了递归结果,而策略 2 只有在之前已经看到确切输入的情况下才很快。

谁能解释一下这是为什么?

【问题讨论】:

    标签: r memoization memoise


    【解决方案1】:

    我认为原因很简单。在慢速情况下,函数fib_not_as_fast 被记忆。在函数内部,fib 被调用,它没有被记忆。更详细地说:当你计算fib_not_so_fast(24)时,在函数内部你有fib(22) + fib(23)。这两个都没有被记住。

    然而,在fib_fast 中,您也在递归中使用记忆版本。因此,在这种情况下,fib_fast(24) 需要评估 fib_fast(22) + fib_fast(23)。当您计算 fib_fast(23) 并因此被记忆时,这两个函数调用都已经发生了。

    真正起作用的是在定义函数之后再记忆它。因此,只需将函数 fib() 重新定义为 fib &lt;- memoise(fib) 即可。

    【讨论】:

    • 跟进:假设你已经定义了fib——你会如何记忆它?替换函数体中的东西?
    • @Frank - Recall 对于避免这些情况很有用。如果您在 R 中编写递归函数,那么您应该使用 Recall
    • @Dason 酷啊,不知道有这样的功能。如果我理解正确,似乎没有设置 memoise 包来处理这种情况。我看到 fib &lt;- function(n) {if (n &lt; 2) return(1); Recall(n - 2) + Recall(n - 1)}ffib &lt;- memoise(fib) 的时间相同
    • 这是因为内部的fibs已经被评估了吗?我知道内部的谎言没有被记住,但我很难理解为什么它们没有?
    • fib 的记忆版本存储在fib_not_so_fastfib 本身永远不会存储为记忆函数。
    猜你喜欢
    • 1970-01-01
    • 2016-01-19
    • 2010-12-28
    • 2018-05-02
    • 2019-07-05
    • 1970-01-01
    • 2022-08-09
    • 2019-08-18
    • 1970-01-01
    相关资源
    最近更新 更多