0

我已经模拟了一个具有 28 个参数的物理系统。模拟计算另一个大约 10 个输出参数的列表。现在我需要探索参数空间:一些输入参数我保持不变,一些有几个值。输入结构是这样的:

input_params = {
    'input1': [0.3], # fixed
    'input2': [1.5, 4.5, 4], # variable param: [start, end, number_of_intermediate_values]
    'input3': [1200.0], # fixed
    'input4': [-0.1, -0.5, 10], # variable param: [start, end, number_of_intermediate_values]
    'input5': [1e-3], # fixed
}

模拟程序的输出是这样的(对于输入的组合):

output_params = {
    'output1': 3.9,
    'output2': -2.5,
    'output3': 100.0,
}

我想生成一个 n 维数组,以便以后可以以最大的灵活性对其进行探索。对于上面的例子,它应该是一个这样的数组:

results = np.zeros(shape=(1,4,1,10,1,8))

其中第一个轴用于input1(一个值),第二个轴用于input2(四个值)等等,最后一个轴包含所有数据[input1, input2, input3, input4, input5, output1, output2, output3](5 + 3 = 8 个值)。对于此示例,它将是一个 4 x 10 x 8 = 320 值的数组,其形状如所述。

我的问题是:如何生成这个结构,然后填充它(在每个轴上迭代)而不for手动编写 28 个嵌套循环?

或者也许我的数据结构不正确并且存在更好的解决方案?

我对使用 pandas 的解决方案持开放态度(因为我希望能够将参数名称作为字符串处理)。或简单的python dicts。执行速度并不那么重要,因为瓶颈是每次模拟的计算时间(它需要达到稳定状态),我可以承受在模拟之间花费几毫秒的时间。

我还需要灵活地选择哪些参数是固定的,哪些是可变的(以及它们有多少值)。

4

1 回答 1

1

要生成所有输入模式,您可以使用:pd.MultiIndex.from_product()

这是代码:

import numpy as np
import pandas as pd

input_params = {
    'input1': [0.3], # fixed
    'input2': [1.5, 4.5, 4], # variable param: [start, end, number_of_intermediate_values]
    'input3': [1200.0], # fixed
    'input4': [-0.1, -0.5, 10], # variable param: [start, end, number_of_intermediate_values]
    'input5': [1e-3], # fixed
}

def expand_input(inputs):
    if len(inputs) == 1:
        return inputs
    return np.linspace(*inputs).tolist()

def sim(in_pars):
    "dummy simulation that returns three results"
    return np.min(in_pars), np.mean(in_pars), np.max(in_pars)

items = sorted(input_params.items())
keys = [item[0] for item in items]
inputs = [expand_input(item[1]) for item in items]

idx = pd.MultiIndex.from_product(inputs, names=keys)
df = pd.DataFrame(np.zeros((len(idx), 3)), columns="res1 res2 res3".split(), index=idx)

for key, row in df.iterrows():
    row[:] = sim(key)

print df

输出:

                                           res1        res2  res3
input1 input2 input3 input4    input5                            
0.3    1.5    1200   -0.100000 0.001  -0.100000  240.340200  1200
                     -0.144444 0.001  -0.144444  240.331311  1200
                     -0.188889 0.001  -0.188889  240.322422  1200
                     -0.233333 0.001  -0.233333  240.313533  1200
                     -0.277778 0.001  -0.277778  240.304644  1200
                     -0.322222 0.001  -0.322222  240.295756  1200
                     -0.366667 0.001  -0.366667  240.286867  1200
                     -0.411111 0.001  -0.411111  240.277978  1200
                     -0.455556 0.001  -0.455556  240.269089  1200
                     -0.500000 0.001  -0.500000  240.260200  1200
       2.5    1200   -0.100000 0.001  -0.100000  240.540200  1200
                     -0.144444 0.001  -0.144444  240.531311  1200
                     -0.188889 0.001  -0.188889  240.522422  1200
                     -0.233333 0.001  -0.233333  240.513533  1200
                     -0.277778 0.001  -0.277778  240.504644  1200
                     -0.322222 0.001  -0.322222  240.495756  1200
                     -0.366667 0.001  -0.366667  240.486867  1200
                     -0.411111 0.001  -0.411111  240.477978  1200
                     -0.455556 0.001  -0.455556  240.469089  1200
                     -0.500000 0.001  -0.500000  240.460200  1200
       3.5    1200   -0.100000 0.001  -0.100000  240.740200  1200
                     -0.144444 0.001  -0.144444  240.731311  1200
                     -0.188889 0.001  -0.188889  240.722422  1200
                     -0.233333 0.001  -0.233333  240.713533  1200
                     -0.277778 0.001  -0.277778  240.704644  1200
                     -0.322222 0.001  -0.322222  240.695756  1200
                     -0.366667 0.001  -0.366667  240.686867  1200
                     -0.411111 0.001  -0.411111  240.677978  1200
                     -0.455556 0.001  -0.455556  240.669089  1200
                     -0.500000 0.001  -0.500000  240.660200  1200
       4.5    1200   -0.100000 0.001  -0.100000  240.940200  1200
                     -0.144444 0.001  -0.144444  240.931311  1200
                     -0.188889 0.001  -0.188889  240.922422  1200
                     -0.233333 0.001  -0.233333  240.913533  1200
                     -0.277778 0.001  -0.277778  240.904644  1200
                     -0.322222 0.001  -0.322222  240.895756  1200
                     -0.366667 0.001  -0.366667  240.886867  1200
                     -0.411111 0.001  -0.411111  240.877978  1200
                     -0.455556 0.001  -0.455556  240.869089  1200
                     -0.500000 0.001  -0.500000  240.860200  1200

如果有这么多输入模式,我认为将所有结果保存在内存中并不是一个好主意,您可以将结果保存到文件中:

from itertools import product

with open("result.txt", "w") as f:
    for in_pars in product(*inputs):
        res = sim(in_pars)
        f.write(",".join(str(x) for x in in_pars + res))
        f.write("\n")
于 2014-11-09T02:03:56.390 回答