我有一组300万个向量(每个300个维度),我在这300个昏暗空间中寻找一个新点,与所有其他点大致相同(载体)
我能做的是初始化随机向量v,并在v上运行优化,目标是:
其中d_xy是向量x和向量y之间的距离,但这在计算上非常昂贵。
我正在为这个问题寻找近似解决方案向量,可以在非常大的向量集上快速找到。 (或任何为我做任何语言的图书馆) -
答案 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万分。