【问题标题】:how to perform an automatic optimisation如何执行自动优化
【发布时间】:2016-09-09 18:19:34
【问题描述】:

可以在此处找到示例数据。没办法,只能把数据放到网上,因为我无法生成有代表性的数据,

这是代码

myfunction <- function(df, parametr1, paramter2){
  do the stuff you want to do
}

我在这个函数中有两个参数需要优化

【问题讨论】:

  • 使用subset时不需要with。尝试删除它。
  • 不要使用subset,使用[]。下面是一个获取索引的例子:which(c(0:1) &gt; 1);获取值:c(0,1)[ which(c(0:1) &gt; 1)]which 需要一个逻辑表达式作为输入。
  • 使用str 更好地理解对象的结构。然后提取您感兴趣的列表项。
  • 我想你想在 res@listData 上工作。
  • 好的,但请帮助我理解:最合适的是没有任何平滑处理的那个。因此,就输入和拟合之间的差异而言,根本不进行任何过滤将给出最佳结果。或者,如果您必须进行一些平滑处理,请选择尽可能小的滤波器长度。但这肯定不是你的目标。我忽略了什么吗?

标签: r


【解决方案1】:

在开始回答的主要部分之前,先澄清一下:在问题中,您说要最小化“拟合残差(输入信号和平滑信号之间的差异)”。最小化残差之和几乎从来没有意义,因为这个和可能是负数 - 因此,尝试最小化这个函数将导致可以找到的最大负残差和(通常甚至不会收敛,因为残差可以变得无限负)。几乎总是做的是最小化残差的平方和,这就是我在这里所做的。

让我们从一个返回残差平方和的支付函数开始

payoff <- function(fl, forder) {
  M <- sav.gol(df[,1], fl = fl, forder = forder)
  resid2 <- (M-df[,1])^2
  sum(resid2)
}

请注意,我没有将 df 作为参数传递给此函数,而只是从父范围访问它。这是为了避免每次调用函数时不必要地复制数据帧,以减少内存和时间开销。

现在进入主要问题,对于整数值 1

这里的主要困难是优化参数fl和forder是整数。大多数典型的优化方法(例如那些由 optimize、optim 或 nlm 使用的方法)都是为连续参数的连续函数而设计的。离散优化完全是另一回事,其方法包括遗传算法等方法。例如,有关整数或离散优化的一些方法,请参阅这些 SO 帖子 herehere

对于离散优化没有完美的解决方案,尤其是当您正在寻找全局最小值而不是局部最小值时。在您的情况下,残差平方和(收益)函数的表现不是很好并且会振荡。所以我们真的应该寻找一个全局最小值,而不是可能有很多的局部最小值。找到全局最小值的唯一确定方法是通过蛮力,实际上我们可以在这里采用这种方法,因为蛮力解决方案可以在合理的时间长度内计算。以下代码将计算 fl 和 forder 的所有值下的收益(目标)函数:

resord2 <- sapply(1:NROW(df),  FUN= function(x) payoff(x, 2))
resord4 <- sapply(1:NROW(df),  FUN= function(x) payoff(x, 4))

计算这些函数的时间仅随数据行数线性增加。使用你的 43k 行,这在我不是特别快的笔记本电脑上大约需要一天半的时间。

不过,幸运的是,我们不需要投入那么多计算时间。下图显示了 forder=2(蓝线)和 forder=4(红线)的残差平方和,fl up 为 40。

resord2 <- sapply(1:40,  FUN= function(x) payoff(x, 2))
resord4 <- sapply(1:40,  FUN= function(x) payoff(x, 4))
plot(1:40, resord2, log="y", type="l", col="blue", xlab="dl", ylab="residual sum of squares")
lines(1:40, resord4, col="red")

很明显,fl 的高值会导致高残差平方和。因此我们可以将优化搜索限制在 dl

resord2 <- sapply(1:40,  FUN= function(x) payoff(x, 2))
resord4 <- sapply(1:40,  FUN= function(x) payoff(x, 4))
which.min(resord2)
# 3
which.min(resord4)
# 3

如果我们想说服自己残差平方和确实会在更大范围内随着 fl 的增加而增加,我们可以使用更大范围的值来创建快速现实检查,让 fl 以更大的步长递增:

low_fl <- 10
high_fl <- 100
step_size <- 10
fl <- seq(low_fl, high_fl, by=step_size)
resord2 <- sapply(fl,  FUN= function(x) payoff(x, 2))
plot(fl, resord2)

【讨论】:

  • 如果您在 OP 中链接了这篇文章就好了。文章的方法是v. diff。 OP中的问题。作者所做的不是最小化残差(这没有意义,因为这等于根本没有平滑)。正如作者所指出的,“必须在噪声消除和信号失真之间找到平衡”。因此,它们将残差和检测器空白的自相关之间的差异最小化。为此,“唯一必须提前知道的参数是检测器噪声的自相关函数。”您不提供此检测器噪声自相关。
  • 我没有提供,因为我不想完全按照他们的要求去做。我喜欢我自己的方法意味着最小化错误,因为我将在复制样本上使用它,它是有意义的。空白样品将有白噪声,意味着根本没有尖峰。所以从这个角度来看,它并没有提供一个很好的解决方案。我说的对吗?
  • 如果您正在寻求编程帮助,这里就是您的最佳选择。我的回答向您展示了如何为您提出的问题编写解决方案。您尝试的基础统计数据是否有意义并不是一个真正的问题,而是您应该在交叉验证后讨论的问题,或者可能与您所在机构的统计学家讨论。如果没有更多信息,我无法确定您的方法是否良好,尽管我的直觉是它听起来不太正确,您最好坚持使用已发布的方法。
  • 请添加其他内容,我会接受您的解决方案。评估 1 窗口大小、10 窗口大小、50 和 100 窗口大小。你展示的是1:40一一。我希望我在 10 点、50 点和 100 点结束。
  • 我接受了。我可以请你帮个忙吗?现在我在优化过程中只有一个不同的参数,如果我有两个呢?这里一个从 1 变为我的样本长度,另一个只有 2 或 4;我的意思是如果我有两个参数的最小值和最大值怎么办?
【解决方案2】:

如果我对您的理解正确,您希望尽量减少 T2 和您的输入 T 之间的差异。

首先,编辑sav.gol,使最后一行是return(T2)(我认为这不是必需的,但似乎是这样)。

以下内容不会给你我认为你想要的答案,因为它会选择接近 0 的过滤,但这是找到最小值的有效方法。

# make your residual function
resid <- function(fl, T, fo){
  fl <- round(fl)
  T2 <- sav.gol(T, fl, forder = fo, dorder = 0)
  sum((T2 - T) ^ 2)
}

# optimize for order 2
results_2 <- optimize(f = resid, interval = c(1, length(df[, 1])),
                      T = df[, 1], fo = 2)

# optimize for order 4
results_4 <- optimize(f = resid, interval = c(1, length(df[, 1])),
                      T=df[, 1], fo = 4)

编辑:

随着fl 的增加(最多 10k),我绘制了订单 2 的残差值; optimize 似乎找到了第一个局部最小值,可能需要一些调整。我建议您在答案中为您的过滤级别指定一些下限和上限。然后,您可以使用具有不同间隔的optimize

library(ggplot)
resids <- sapply(1:10000, resid, T = df[1:10000, 1], fo = 2)
qplot(seq_along(resids), resids / 10^10,
      xlab = 'fl', ylab = 'Residual', geom='line')

顺便说一下,上面的sapply 可以替代optimize。你可以在完整的数据集上运行它,

resids <- sapply(1:length(df[,1], resid, T = df[, 1], fo = 2) 

在我的笔记本电脑上看起来需要大约 10 个小时,但是一旦完成,您可以按照上面的方法绘制它并通过眼睛选择过滤级别(或执行which.min(resids[lb:ub]),其中lbub 是您的较低级别和上限)。

【讨论】:

  • 你的函数应该返回一个你想要基于这些参数和其他数据最小化的标量值,所以你的函数应该把你的参数矩阵作为它的第一个参数,然后你可以把它们取出函数内的矩阵。因此,假设您要估计的两个参数是称为arg1arg1 的向量。假设它们的长度相同,您可以为它们设置一些合理的初始值,然后将它们放入像 m &lt;- cbind(arg1, arg2) 这样的矩阵中。在你的函数中,你会把它们拉回来。
  • 看我的原始数据,它是一个3列多行的矩阵。该函数是 sav.gol
  • @HoHo,我认为最大化的输入参数需要是离散的。 OP 对此有些不清楚,但我认为 fl 表示许多行。
  • @HoHo 我喜欢你的回答,我感谢你的努力,但我不想使用持续优化而不是离散
  • 这就是我包含round 的原因——它最终确实执行了离散优化。或者,sapply 是真正离散的,它只会花费更长的时间(尽管您可以使用 doParellel 包和 foreach 来加快速度。)
猜你喜欢
  • 2021-12-19
  • 2015-08-17
  • 1970-01-01
  • 2012-11-28
  • 2011-01-13
  • 2012-10-04
  • 2015-07-12
  • 1970-01-01
  • 2015-08-31
相关资源
最近更新 更多