在 R^n 中对 cube/sphere 进行网格搜索
Grid search over a cube/sphere in R^n
我正在尝试对 R^n
中的球体实施网格搜索(在 Python 中,如果重要的话),其中 n
未知。
输入包括球体的半径和中心,以及控制网格分辨率的超参数 theta
。我想将这个球体中的每个点表示为这三个参数的函数。
我也愿意考虑立方体搜索,只迭代立方体的面。
(即迭代 L_inf
sphere)
如果我知道n=2,我会做的是:
import numpy as np
def enumerate_2d_sphere(R,theta,center=(0,0)):
for n in xrange(int(2*np.pi / theta)+1):
degree = n*theta
point =(center[0]+R*np.cos(degree),center[1]+R*np.sin(degree))
yield point
for p in enumerate_2d_sphere(1,0.1):
print p
由于 n
可以任意大,我正在寻找一种有效地迭代 sphere\cube 的方法。
有什么想法吗?
+++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++
我最终使用了 strubbly 建议的修改版本:
import itertools
import numpy as np
import matplotlib.pyplot as plt
def f(d, center, scale=1):
dim = len(center)
print d/-2.0
diff = scale * np.array([d/-2.0 for _ in xrange(dim)])
bias = diff + center
for i in range(dim):
l = ([ xrange(1,d) for _ in xrange(i)] +
[[0,d]] +
[ xrange(d+1) for _ in xrange(dim-i-1)]
)
for r in itertools.product(*l):
yield scale*np.array(r)+bias
#example for R^2:
center = (1,1.5)
data = np.array([x for x in f(20,center,scale = 0.1)])
plt.scatter(data[:,0], data[:,1],color='r',s=100,alpha=0.5)
plt.scatter(center[0], center[1],color='b',s=300,alpha=0.5)
plt.show()
输出图:
还有一个选择,就是生成
uniformly distributed samples on the sphere。请注意,样本数控制点的 "density"(或预期密度):
import numpy as np
def generate_random_points(R,center,quantity=1000):
"""
:param R: float
:param center: np.array
:param quantity: int
"""
dim = len(center)
for n in xrange(quantity):
s = np.random.normal(0, 1,dim)
r = np.sqrt(np.dot(s,s))
s = (R/r) * s
yield s+center
最糟糕的方法(就简单性和效率而言)是使用 enumeration of n-1 angles 在球体上生成点。缺乏效率是因为需要经常计算产品 sin
和 cos
(尽管这也可以被黑客攻击)
我认为 sklearn 网格搜索功能没有这个选项,但手动实现这个应该不难
- 迭代 n 的值
- 对于每个 n,以从 0 到 360 的 theta 步幅迭代 n 个不同的角度参数
- 如果您不需要球体体积,也可以迭代半径 - 如果您只需要表面,请保持半径不变
您可以使用 n 维球面坐标(例如 wikipedia),或者您可以使用欧氏坐标,只需将最后一个坐标设置为获得正确半径(正负)所需的任何值即可.这两个都是很好的参数化,将为您提供球体上的所有点 - 使用正确数量的参数进行迭代。
但它们不会自然地导致恒定面积(体积)元素 - 仅考虑 3 球体就很容易看出这一点。这个问题没有简单的解决方案。
我认为一种可能的方法是使用 n-1 维网格参数化,但根据体积将第 n 个分量细分为可变数量的值。
n立方体的面更简单:只需生成第n个坐标为最小或最大的n对面。因此,例如,考虑从原点开始的大小为 1 的 n 维立方体:
将第一个坐标设置为零,并在其余坐标上枚举一个网格。然后将其设置为一个并再次执行。然后重复第二个坐标。等等。
这是使用 itertools.product
执行此操作的简单方法。为了简单和高效,我已将框缩放为整数坐标:您需要重新缩放并移动中心。所以 n
是维数,d
是沿每个轴的细分数。
import itertools
def f(n,d):
for i in range(n):
l = ([ range(1,d-1) for _ in range(i)] +
[[0,d-1]] +
[ range(d) for _ in range(n-i-1)]
)
for r in itertools.product(*l):
yield r
print(list(f(4,3)))
我正在尝试对 R^n
中的球体实施网格搜索(在 Python 中,如果重要的话),其中 n
未知。
输入包括球体的半径和中心,以及控制网格分辨率的超参数 theta
。我想将这个球体中的每个点表示为这三个参数的函数。
我也愿意考虑立方体搜索,只迭代立方体的面。
(即迭代 L_inf
sphere)
如果我知道n=2,我会做的是:
import numpy as np
def enumerate_2d_sphere(R,theta,center=(0,0)):
for n in xrange(int(2*np.pi / theta)+1):
degree = n*theta
point =(center[0]+R*np.cos(degree),center[1]+R*np.sin(degree))
yield point
for p in enumerate_2d_sphere(1,0.1):
print p
由于 n
可以任意大,我正在寻找一种有效地迭代 sphere\cube 的方法。
有什么想法吗?
+++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++
我最终使用了 strubbly 建议的修改版本:
import itertools
import numpy as np
import matplotlib.pyplot as plt
def f(d, center, scale=1):
dim = len(center)
print d/-2.0
diff = scale * np.array([d/-2.0 for _ in xrange(dim)])
bias = diff + center
for i in range(dim):
l = ([ xrange(1,d) for _ in xrange(i)] +
[[0,d]] +
[ xrange(d+1) for _ in xrange(dim-i-1)]
)
for r in itertools.product(*l):
yield scale*np.array(r)+bias
#example for R^2:
center = (1,1.5)
data = np.array([x for x in f(20,center,scale = 0.1)])
plt.scatter(data[:,0], data[:,1],color='r',s=100,alpha=0.5)
plt.scatter(center[0], center[1],color='b',s=300,alpha=0.5)
plt.show()
输出图:
还有一个选择,就是生成 uniformly distributed samples on the sphere。请注意,样本数控制点的 "density"(或预期密度):
import numpy as np
def generate_random_points(R,center,quantity=1000):
"""
:param R: float
:param center: np.array
:param quantity: int
"""
dim = len(center)
for n in xrange(quantity):
s = np.random.normal(0, 1,dim)
r = np.sqrt(np.dot(s,s))
s = (R/r) * s
yield s+center
最糟糕的方法(就简单性和效率而言)是使用 enumeration of n-1 angles 在球体上生成点。缺乏效率是因为需要经常计算产品 sin
和 cos
(尽管这也可以被黑客攻击)
我认为 sklearn 网格搜索功能没有这个选项,但手动实现这个应该不难
- 迭代 n 的值
- 对于每个 n,以从 0 到 360 的 theta 步幅迭代 n 个不同的角度参数
- 如果您不需要球体体积,也可以迭代半径 - 如果您只需要表面,请保持半径不变
您可以使用 n 维球面坐标(例如 wikipedia),或者您可以使用欧氏坐标,只需将最后一个坐标设置为获得正确半径(正负)所需的任何值即可.这两个都是很好的参数化,将为您提供球体上的所有点 - 使用正确数量的参数进行迭代。
但它们不会自然地导致恒定面积(体积)元素 - 仅考虑 3 球体就很容易看出这一点。这个问题没有简单的解决方案。
我认为一种可能的方法是使用 n-1 维网格参数化,但根据体积将第 n 个分量细分为可变数量的值。
n立方体的面更简单:只需生成第n个坐标为最小或最大的n对面。因此,例如,考虑从原点开始的大小为 1 的 n 维立方体:
将第一个坐标设置为零,并在其余坐标上枚举一个网格。然后将其设置为一个并再次执行。然后重复第二个坐标。等等。
这是使用 itertools.product
执行此操作的简单方法。为了简单和高效,我已将框缩放为整数坐标:您需要重新缩放并移动中心。所以 n
是维数,d
是沿每个轴的细分数。
import itertools
def f(n,d):
for i in range(n):
l = ([ range(1,d-1) for _ in range(i)] +
[[0,d-1]] +
[ range(d) for _ in range(n-i-1)]
)
for r in itertools.product(*l):
yield r
print(list(f(4,3)))