【问题标题】:How to write a recursion function for all the possible parameter combinations in python如何为python中所有可能的参数组合编写递归函数
【发布时间】:2015-05-10 18:17:05
【问题描述】:

我正在尝试编写一段代码来遍历python算法的所有可能参数组合。

import numpy as np
parameter={'alpha1':np.linspace(0.3,0.4,10),'alpha2':np.linspace(0.9,2,100),...'alpha5':np.linspace(5,10,100)}

问题是我无法编写 5 嵌套 for 循环。任何人都可以演示如何编写递归函数来列出所有可能的参数组合吗? 谢谢

【问题讨论】:

  • 首先,你这样做是为了学习递归吗?因为如果不是 (a) 你通常不想对 NumPy 数组进行深度递归 迭代,并且 (b) 如果你这样做了,那么有更简单(更有效)的方法来编写它——参见itertools 文档。
  • 同时,向我们展示您为一个更简单的问题编写的代码,该问题只需要固定且少量的嵌套循环,例如 2 或 3,向您展示如何更容易将其转化为适用于动态或大量嵌套的递归解决方案。

标签: python recursion combinations


【解决方案1】:

您可以使用itertools.product 函数,该函数获取迭代器列表并创建其笛卡尔积的迭代器(请参阅documentation)。

在我的解决方案中,我使用 parameter 字典中的值作为迭代器。我检查每个键的选项乘积 (for values_option in product(*parameter.values())) 并使用原始键创建一个新字典)

from itertools import product
import numpy as np

parameter={'alpha1':np.linspace(0.3,0.4,10),'alpha2':np.linspace(0.9,2,100)}

def parameter_options(parameter):
    for values_option in product(*parameter.values()):
        yield dict(zip(parameter.keys(), values_option))

for opt in parameter_options(parameter):
    print opt

让我们一块一块地看:

parameter.values()

这给出了字典中每个键值对值的列表。

例如,如果我们有dictionary = {a: (1, 2, 3), b: (4, 5, 6)},使用dictionary.values() 将返回[(1, 2, 3), (4, 5, 6)]。执行dictionary.keys() 将得到['a', 'b']

注意:Python 2 和 Python 3 之间存在差异 - 在 Python 2 中,这些方法(keys()values())将返回普通列表,而在 Python 3 中它们返回一个特殊的列表迭代器。这不应该改变解决方案。

product(*parameter.values())

我们使用星号来“解包”列表。简单地说,itertools.product 接收任意数量的参数。我们想使用所有的values 作为输入:

vals = parameter.values()
product(vals[0], vals[1], vals[2], ..., vals[len(vals)])

Python 有一种简单的方法可以将列表作为输入传递给接收任意数量参数的函数。最后一行与product(*vals) 相同。

for values_option in product(*parameter.values()):

我们检查了parameter 字典值的所有选项。

第一次迭代将为所有参数提供第一个选项。第二次迭代将为除一个参数之外的所有参数提供第一个选项,该参数将具有第二个选项。这一直持续到我们有最后一个选项,每个参数都有它的最后一个选项。

zip(parameter.keys(), values_option)

这需要两个列表(键和可能的值)并基本上转置它们。它给出了一个相同长度的列表,其中包括对:第一个列表中的第一个元素和第二个列表中的第二个元素。像这样:

keys = ['a', 'b', 'c', 'd']
vals = [1, 2, 3, 4]
zip(keys, vals) = [('a', 1), ('b', 2), ('c', 3), ('d', 4)]

dict(...)

现在我们可以使用这个压缩列表来创建字典。这是启动 dict 的另一种方式

{'a': 1, 'b': 2, 'c': 3} == dict([('a', 1), ('b', 2), ('c', 3)])

yield ...

这就是我们在 python 中用来创建迭代器的方法。这是一个复杂的主题,但您可以在 for 循环之前写下这一行

options = []

而不是yield dict(...)options.append(dict(...))。 并在函数的末尾return options

瞧。

【讨论】:

  • 您好,感谢您的详细解释,很抱歉由于上周被埋在一个糟糕的项目中,所以迟到了回复。我用 3 个参数尝试了你的代码,很高兴看到结果!
  • 你知道itertools中的笛卡尔积是怎么实现的吗?通过递归?
  • 您可以在文档中查看实现(链接在我的答案中)。这是一个递归执行的 for 循环。
猜你喜欢
  • 1970-01-01
  • 2014-02-28
  • 2016-12-11
  • 1970-01-01
  • 1970-01-01
  • 2018-01-11
  • 2021-04-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多