posmax:类似于 argmax,但给出了 f[x] 最大的元素 x 的位置
Mathematica 有一个内置函数 ArgMax 用于无限域上的函数,基于标准数学定义。
有限域的模拟是一个方便的效用函数。 给定一个函数和一个列表(称为函数的域),返回列表中使函数最大化的元素。 下面是有限 argmax 的实际应用示例: 规范化 NFL 球队名称
这是我的实现(以及 argmin ) measure):
(* argmax[f, domain] returns the element of domain for which f of
that element is maximal -- breaks ties in favor of first occurrence. *)
SetAttributes[{argmax, argmin}, HoldFirst];
argmax[f_, dom_List] := Fold[If[f[#1]>=f[#2], #1, #2]&, First[dom], Rest[dom]]
argmin[f_, dom_List] := argmax[-f[#]&, dom]
首先,这是实现 argmax 最有效的方法吗? 如果您想要所有最大元素的列表而不仅仅是第一个元素怎么办?
其次,相关函数 posmax 怎么样,它不返回最大元素,而是返回最大元素的位置?
Mathematica has a built-in function ArgMax for functions over infinite domains, based on the standard mathematical definition.
The analog for finite domains is a handy utility function.
Given a function and a list (call it the domain of the function), return the element(s) of the list that maximize the function.
Here's an example of finite argmax in action:
Canonicalize NFL team names
And here's my implementation of it (along with argmin for good measure):
(* argmax[f, domain] returns the element of domain for which f of
that element is maximal -- breaks ties in favor of first occurrence. *)
SetAttributes[{argmax, argmin}, HoldFirst];
argmax[f_, dom_List] := Fold[If[f[#1]>=f[#2], #1, #2]&, First[dom], Rest[dom]]
argmin[f_, dom_List] := argmax[-f[#]&, dom]
First, is that the most efficient way to implement argmax?
What if you want the list of all maximal elements instead of just the first one?
Second, how about the related function posmax that, instead of returning the maximal element(s), returns the position(s) of the maximal elements?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
@dreeves,您是正确的,
Ordering
是在有限域上最快实现 ArgMax 的关键:使用
Fold
的原始实现的部分问题是您最终会对f
进行两倍的计算,这是低效的,尤其是当f
计算速度很慢时。在这里,我们只为域的每个成员评估f
一次。当域有很多重复元素时,我们可以通过 memoizing的值来进一步优化f
:在一些基本测试中,对于 0 到 100 之间的 100,000 个随机整数列表,这大约快了 30%。
对于 posmax 函数,这种有点不优雅的方法是最快的事情我可以想出:
当然,我们可以再次应用记忆:
要获得所有最大元素,您现在可以根据
PosMax<来实现
ArgMax
/代码>:@dreeves, you're correct in that
Ordering
is the key to the fastest implementation of ArgMax over a finite domain:Part of the problem with your original implementation using
Fold
is that you end up evaluatingf
twice as much as necessary, which is inefficient, especially when computingf
is slow. Here we only evaluatef
once for each member of the domain. When the domain has many duplicated elements, we can further optimize by memoizing the values off
:This was about 30% faster in some basic tests for a list of 100,000 random integers between 0 and 100.
For a
posmax
function, this somewhat non-elegant approach is the fastest thing I can come up with:Of course, we can apply memoization again:
To get all the maximal elements, you could now just implement
ArgMax
in terms ofPosMax
:对于 posmax,您可以首先将函数映射到列表上,然后仅询问最大元素的位置。即:
其中 posmax[list] 被多态定义为仅返回最大元素的位置。
事实证明,有一个内置函数 Ordering 基本上可以完成此操作。
因此,我们可以像这样定义 posmax 的单参数版本:
我刚刚针对基于循环的版本和递归版本进行了测试,排序速度要快很多倍。
递归版本非常漂亮,所以我将在这里展示它,但永远不要尝试在大输入上运行它!
这些都没有解决如何找到所有最大元素(或它们的位置)的问题。
在实践中我通常不会遇到这种情况,尽管我认为有这种情况会很好。
For posmax, you can first map the function over the list and then just ask for the position of the maximal element(s). Ie:
where
posmax[list]
is polymorphically defined to just return the position of the maximal element(s).It turns out there's a built-in function, Ordering that essentially does this.
So we can define the single-argument version of posmax like this:
I just tested that against a loop-based version and a recursive version and Ordering is many times faster.
The recursive version is pretty so I'll show it off here, but don't ever try to run it on large inputs!
None of this addresses the question of how to find all the maximal elements (or positions of them).
That doesn't normally come up for me in practice, though I think it would be good to have.