嘿,我有以下问题。我有一个很大的参数空间。就我而言,我有10个维度。但为了简化,假设我有3个变量x1,x2和x3。它们是从1到10的离散数字。现在我创建所有可能的参数组合,并希望将它们用于后处理。在我的实际案例中,组合太多了。所以我想做一个准随机序列搜索来减少搜索空间。但搜索空间中的组合应该尽可能地覆盖它。 (统一分布)。我想在搜索空间中阻止参数组合到Cluster,它应该尽可能地覆盖整个搜索空间。我需要在参数处理中找到参数组合的首选项。有很多方法可以做到这一点,比如Haton,Hammersley或Sobol序列。但他们并不适用于离散数字。一个做准随机序列的包是混乱的。如果我对序列的数量进行舍入,则每个变量的可变数量将在不同的变量组合中出现不止一次。那不是我想要的。我希望每个变量号只出现一次,变量在搜索空间中均匀分布。是否有可能从一开始就创建一个随机的多维变量组合集,其中每个变量只出现一次?例如,在二维网格10x10中,一种可能的组合是对角线。当然,在3个维度中,我需要100个组合来覆盖所有参数值,
让我们看一个简单的例子,其中包含1-3个带Sobol序列的三个变量:
import numpy as np
import chaospy as cp
#Create a Joint distributuon of the three varaibles, which ranges going from 1 to 10
distribution2 = cp.J(cp.Uniform(1, 10),cp.Uniform(1, 10),cp.Uniform(1, 10))
#Create 10 numbers in the variable space
samplesSobol = distribution2.sample(10, rule="S")
#Transpose the array to get the variable combinations in subarrays
sobolPointsTranspose = np.transpose(samplesSobol)
示例输出:
[[ 7.89886475 6.34649658 4.8336792 ]
[ 5.64886475 4.09649658 2.5836792 ]
[ 1.14886475 8.59649658 7.0836792 ]
[ 1.21917725 5.01055908 2.5133667 ]
[ 5.71917725 9.51055908 7.0133667 ]
[ 7.96917725 2.76055908 9.2633667 ]
[ 3.46917725 7.26055908 4.7633667 ]
[ 4.59417725 1.63555908 5.8883667 ]
[ 9.09417725 6.13555908 1.3883667 ]
[ 6.84417725 3.88555908 3.6383667 ]]
现在,每个变量编号都是唯一的,但输出不是离散的。我可以绕过它并得到:
[[ 8. 6. 5.]
[ 6. 4. 3.]
[ 1. 9. 7.]
[ 1. 5. 3.]
[ 6. 10. 7.]
[ 8. 3. 9.]
[ 3. 7. 5.]
[ 5. 2. 6.]
[ 9. 6. 1.]
[ 7. 4. 4.]]
现在问题是,例如1在第一维中出现两次,在第二维中出现4或在第三维中出现7。
答案 0 :(得分:1)
"是否有可能从一开始就创建一个随机的多维变量组合集,其中每个变量只出现一次?" 为此,每个变量组合都有效变量必须具有相同数量的可能值。在你的例子中,这个数字是10,所以我将使用它。
生成随机点的一种方法是堆叠范围(10)的随机排列。像这样,例如,有三个变量:
In [180]: np.column_stack([np.random.permutation(10) for _ in range(3)])
Out[180]:
array([[6, 6, 4],
[9, 2, 0],
[0, 4, 3],
[5, 9, 5],
[2, 8, 7],
[1, 1, 9],
[8, 3, 8],
[3, 5, 1],
[4, 0, 2],
[7, 7, 6]])
答案 1 :(得分:1)
这是一个很晚的答案,因此我认为与原始海报不再相关,但是我在尝试找到下面描述的现有实现时遇到了该帖子。
听起来您正在寻找类似拉丁文超立方体的东西:https://en.wikipedia.org/wiki/Latin_hypercube_sampling。 本质上,如果我有n个变量并且我想要10个样本,则每个变量的范围将分为10个间隔,每个变量的可能值是(例如)每个间隔的中间点。 Latin hypercube算法以这样的方式随机抽取样本:每个变量的10个值中的每个仅出现一次。沃伦(Warren)的答案中的一个例子是拉丁超立方体。
这无助于尽可能覆盖搜索空间(或换句话说,检查设计是否填充了空间)。莫里斯和米切尔(Morris and Mitchell)在1995年的论文《探索性设计》中有一个针对计算实验的标准,该标准通过查看点之间的距离来计算填充样品的空间。您可以创建大量不同的Latin Hypercube设计,然后使用该准则选择最佳设计,或者采用初始设计并对其进行操作以提供更好的设计。后者在此处的算法中实现:https://github.com/1313e/e13Tools/blob/master/e13tools/sampling/lhs.py 他们在代码中提供了一些示例,例如5分和2个变量:
import numpy as np
np.random.seed(0)
lhd(5, 2, method='fixed')
返回类似
的内容array([[ 0.5 , 0.75],
[ 0.25, 0.25],
[ 0. , 1. ],
[ 0.75, 0.5 ],
[ 1. , 0. ]])
这将使Latin Hypercube在间隔[0,1]上缩放,因此您将需要使用例如
来缩放到参数范围https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.MinMaxScaler.html
根据莫里斯-米切尔(Morris-Mitchell)准则,这个人非常擅长空间填充。
答案 2 :(得分:0)
这个答案给出了一个生成4值列表列表的函数 [a,b,c,d]是1到10之间的自然数。在每个集合中,参数可能只取任何一个值。
import random
def generate_random_sequences(num_params=4, seed=0)
random.seed(seed)
value_lists = [[val for val in range(1, 11)] for _ in range(num_params)]
for values in value_lists:
random.shuffle(values)
ret = [[] for _ in range(num_params)]
for value_idx in range(10):
for param_idx in range(num_params):
ret[param_idx].append(value_lists[param_idx][value_idx])
return ret
我刚刚看到Warren使用numpy的答案是优越的,你无论如何都使用了numpy。仍然将这个作为纯python实现提交。