【问题标题】:Grid search over a cube/sphere in R^n在 R^n 中对立方体/球体进行网格搜索
【发布时间】:2016-02-28 07:51:59
【问题描述】:

我正在尝试在 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 可以任意大,我正在寻找一种有效地迭代球体\立方体的方法。

有什么想法吗?

++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++

我最终使用了 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。请注意,样本数控制点的“密度”(或预期密度):

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 在球体上生成点。效率低下是因为需要经常计算产品sincos(尽管这也可能被黑客入侵)

【问题讨论】:

  • 你能解释一下你想要什么吗?例如假设 R=10,n=2,c=(0, 0),theta=1。将这个圆盘中的所有点表示为 R、c 和 theta 的函数是什么意思?

标签: python grid-search hyperparameters


【解决方案1】:

您可以使用 n 维的球坐标(参见例如wikipedia),或者您可以使用欧几里得坐标,只需将最后一个坐标设置为获得正确半径(加或减)所需的任何值。这两个都是很好的参数化,会给你球体上的所有点 - 使用正确数量的参数进行迭代。

但它们不会自然地导致恒定面积(体积)元素 - 只需考虑 3 球体就很容易看出这一点。这个问题没有简单的解决方案。

我认为一种可能的方法是使用 n-1 维网格参数化,但根据体积将第 n 个组件细分为可变数量的值。

n-cube 的面更容易:只需生成 n 对面,其中第 n 个坐标最小或最大。因此,例如,考虑从原点开始的大小为 1 的 n 立方体:

将第一个坐标设置为零并在其余部分上枚举一个网格。然后将其设置为 1 并再次执行此操作。然后重复第二个坐标。以此类推。

这是使用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)))

【讨论】:

  • 我所说的“使用表面而不是体积缩放”的示例 - 考虑一种算法,该算法生成球内的所有点,并抛出位于球内部的所有点。您的解决方案只能使用递归来实现,对吧?
  • 嗯,我认为递归很容易,但不,不需要。例如,您可以使用itertools.product 或编写您自己的等价物..
  • 感谢您的回复。我更正了你的一些代码,因为它有一个错误,你可以在我原来的问题中看到它。谢谢!
  • 啊-很好发现-经典被一个错误关闭!我已经在我的回答中修复了它。
【解决方案2】:

我不认为sklearn网格搜索功能有这个选项,但是手动实现这个应该不难

  • 迭代 n 的值
  • 对于每个 n,迭代 n 个不同的角度参数,θ 步幅从 0 到 360
  • 如果您不需要球体体积,也可以迭代半径 - 如果您只需要曲面,请保持半径不变

【讨论】:

  • n 的维度在运行前是未知的,因此角度可以多于两个...
  • 没注意到这个……一定是gridsearch,还是手动代码也可以?
  • 请注意,在 3D 中,一个角度从 0 到 360,而另一个从 0 到 180,我不确定n 维度会发生什么...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-31
  • 2012-04-04
相关资源
最近更新 更多