以索引作为哈希函数生成参数随机组合的有效方法

Efficient way to generate random combinations of parameters with index as a hash function

我有 13 个变量,步长为 15,这意味着每个变量的长度为 15 np.linspace(min, max, step)。如果我尝试获得所有组合,那将是大约 15**13 种组合。我想从这个组合 space 中提取 10,000 个样本,即 np.random, choice(15**13, 10000, replace=False)。这将生成我感兴趣的组合的索引。现在如何生成这些组合?下面是生成暴力组合的代码:

def _build_combinations(self):
    #val_dict = {'A': [50, 100], 'B': [10, 40], ...}
    val_dict = {k: np.linspace(*v, self.n_steps) for k, v in val_dict.items()}
    
    for instance in itertools.product(*val_dict.values()):
        yield dict(zip(val_dict.keys(), instance))

for i, param_dict in enumerate(self._build_combinations(), 1):
            self.write(i, param_dict)

这里,i是那个组合的唯一索引。它适用于少量步骤。但是对于大步骤,即使 np.random.choice 也会引发内存错误。

我的问题是:

  1. 如何从 13**15 个数字生成 10,000 个随机索引而不 运行 进入内存错误。
  2. 给定索引,如何在没有运行 itertools.product的情况下生成相应的组合。
import itertools


def _build_combinations(val_dict):
    for instance in itertools.product(*val_dict.values()):
        yield dict(zip(val_dict.keys(), instance))


def params_to_index(val_dict, param_dict):
    result = 0
    for key, values in val_dict.items():
        result *= len(values)
        result += values.index(param_dict[key])
    return result


def index_to_params(val_dict, i):
    param_dict = {}
    for key, values in list(val_dict.items())[::-1]:
        i, v_index = divmod(i, len(values))
        param_dict[key] = values[v_index]
    return param_dict


def test_index():
    val_dict = dict(
        a=[1, 2],
        b=[3, 4, 5],
        c=[6, 7, 8, 9]
    )
    for i, param_dict in enumerate(_build_combinations(val_dict)):
        assert i == params_to_index(val_dict, param_dict)
        assert param_dict == index_to_params(val_dict, i)


test_index()