查找与集合中的所有向量大致相等的向量

时间:2015-06-11 09:59:08

标签: python vector linear-algebra mathematical-optimization approximate

我有一组300万个向量(每个300个维度),我在这300个昏暗空间中寻找一个点,与所有其他点大致相同(载体)

我能做的是初始化随机向量v,并在v上运行优化,目标是: objective function

其中d_xy是向量x和向量y之间的距离,但这在计算上非常昂贵。

我正在为这个问题寻找近似解决方案向量,可以在非常大的向量集上快速找到。 (或任何为我做任何语言的图书馆) -

2 个答案:

答案 0 :(得分:1)

来自this question on the Math StackExchange

  

一般来说,没有必要等于4个或更多点   平面中的位置,或n维中的n + 2个点。

     

用一个点表示点集合的标准是   在统计学,机器学习和计算机科学中考虑过。该   质心是最小二乘意义上的最佳选择,但存在   还有很多其他的可能性。

     

质心是平面中C点的总和   平方距离$ \ sum | CP_i | ^ 2 $是最小的。人们也可以优化   不同的中心性衡量标准,或坚持代表   是一个点(如加权的图论中心)   生成树),或以某种方式为点分配权重   采取那些质心。

请注意,具体而言,“质心是最小二乘意义上的最佳选择”,因此成本函数的最优解(这是最小二乘成本)只是平均点的所有坐标(这将给你质心)。

答案 1 :(得分:1)

我同意,一般来说这是一个相当棘手的优化问题,尤其是在你所描述的规模上。每个目标函数评估需要O(nm + n ^ 2)工作n个维度点m - O(nm)来计算从每个点到新点的距离和O(n ^ 2)来计算给定距离的目标。当m = 300且n = 3M时,这非常可怕。因此,即使是一个功能评估也可能是难以处理的,更不用说解决完整的优化问题了。

另一个答案中提到的一种方法是采用点的质心,这可以有效地计算 - O(nm)。这种方法的缺点是它可能在拟议的目标上做得非常糟糕。例如,考虑一维空间中的情况,其中300万个点具有值1和1个点具有值0.通过检查,最优解是v = 0.5,其中目标值为0(它与每个点等距),但是质心将选择v = 1(嗯,比这个小一点),目标值为300万。

我认为比质心更好的方法是分别优化每个维度(忽略其他维度的存在)。虽然在这种情况下目标函数的计算成本仍然很高,但是一些代数表明目标的导数很容易计算。它是所有对(i,j)的总和,其中i <1。 v和j&gt; v的值为4 *((v-i)+(v-j))。请记住,我们正在优化单个维度,因此点i和j是1维,因为v。对于每个维度,我们因此可以对数据进行排序(O(n lg n)),然后计算值v的导数使用二分搜索和基本代数的O(n)时间。然后我们可以使用import bisect import scipy.optimize def fulldist(x, data): dists = [sum([(x[i]-d[i])*(x[i]-d[i]) for i in range(len(x))])**0.5 for d in data] obj = 0.0 for i in range(len(data)-1): for j in range(i+1, len(data)): obj += (dists[i]-dists[j]) * (dists[i]-dists[j]) return obj def f1p(x, d): lownum = bisect.bisect_left(d, x) highnum = len(d) - lownum lowsum = highnum * (x*lownum - sum([d[i] for i in range(lownum)])) highsum = lownum * (x*highnum - sum([d[i] for i in range(lownum, len(d))])) return 4.0 * (lowsum + highsum) data = [(0.0,), (3.0,), (3.0,)] opt = [] centroid = [] for d in range(len(data[0])): thisdim = [x[d] for x in data] meanval = sum(thisdim) / len(thisdim) centroid.append(meanval) thisdim.sort() opt.append(scipy.optimize.newton(f1p, meanval, args=(thisdim,))) print "Proposed", opt, "objective", fulldist(opt, data) # Proposed [1.5] objective 0.0 print "Centroid", centroid, "objective", fulldist(centroid, data) # Centroid [2.0] objective 2.0 来找到导数的零点,这将是该维度的最佳值。迭代所有维度,我们将对我们的问题有一个近似的解决方案。

首先考虑提出的方法与质心方法的简单设置,一维数据点{0,3,3}:

data = []
for n in range(1000):
    d = []
    for m in range(300):
        if random.random() <= 0.1:
            d.append(random.normalvariate(0.0, 1.0))
        else:
            d.append(random.normalvariate(100.0, 1.0))
    data.append(d)

所提出的方法找到了精确的最优解,而质心方法则略有不足。

考虑一个稍大的示例,其中1000个维度为300,每个点都是从高斯混合中绘制的。每个点的值通常以均值0和方差1分布,概率为0.1,正态分布为均值100和方差1,概率为0.9:

{{1}}

所提出的方法得到的客观值为1.1e6,质心方法得到的目标值为1.6e9,这意味着所提出的方法将目标值降低了99.9%以上。显然,客观价值的差异很大程度上受到分数分布的影响。

最后,为了测试缩放(去除最终目标值计算,因为它们通常是难以处理的),我得到以下缩放,m = 300:0.9秒为1,000点,7.1秒为10,000点,122.3秒数为100,000点。因此,我希望您的完整数据集需要大约1-2小时才能获得300万分。