【发布时间】:2018-05-05 21:44:59
【问题描述】:
我正在使用线性程序来测试两组点是否可以被一条线分开。理论上这是可行的,但在实践中,如果这些点接近共线或彼此靠近,则似乎存在数值问题。
我使用的包是scipy linprog。
我写了一些代码来举例说明我在说什么。这段代码产生一个包含 N 个点的云“位置”,并选择一些随机线,然后使用这些线周围的边距将“位置”集的子集划分为两个区域 X 和 Y,然后检查线性程序是否成功找到 X 和 Y 之间的分隔线,或者如果线性程序得出结论不存在这样的分隔线(未能找到可行点)。
从输出(下图)可以看出,随着边距从 1 变为 2^(-10),线性程序正确检测到两个区域是线性可分的概率会衰减。这表明在检测到可以分离非常近的点云时可能存在一些问题。
请注意,因为我正在输入保证线性可分的线性程序集,所以输出应该都是 1。
import numpy as np
from scipy.optimize import linprog
N = 100
for minv in range(10):
margin = 1/(2**minv)
locations = np.random.uniform(-1,1,[N,2])
tests = []
for i in range(50):
p = np.random.normal(0,1,[3])
X = []
Y = []
for a in locations:
if np.dot(a, [p[0],p[1]]) < p[2] - margin:
X.append(a)
if np.dot(a, [p[0],p[1]]) > p[2] + margin:
Y.append(a)
#X and Y are two linearly seperable subsets of 'locations'
A = []
b = []
if X != [] and Y != []:
#This if is just to avoid an edge case that causes problems with linprog
for s in X:
A.append( [-1*v for v in s] + [1] )
b.append(-1)
for s in Y:
A.append( list(s) + [-1])
b.append(-1)
#See: https://www.joyofdata.de/blog/testing-linear-separability-linear-programming-r-glpk/
res = linprog(c = [0,0,0], A_ub = A, b_ub = b, bounds = [-np.inf, np.inf])
tests.append(res["success"])
print(np.mean(tests))
输出:
1.0
1.0
0.909090909091
0.8
0.805555555556
0.5
0.375
0.444444444444
0.378378378378
0.410256410256
我的问题:
如何可靠(有效)解决检测两组点是否线性可分的问题? (另一种方法是构建凸包,我大部分都写出来了。使用 Qhull 有一些问题:Qhull Convex hull wants me to input at least 3 points)
这是 scipy linprog 中的错误吗?还是我没有正确使用它?
【问题讨论】:
-
所以看起来蒙特卡罗性质可能对您的解释起作用,并且这部分没有被分析(该观察的可能性有多大)。这听起来像是一个非常广泛的问题。但如果你问:我可以信任 scipy.linprog 吗?不,你不能。它(恕我直言)仅对玩具问题有用(密集的画面;没有 presolve 和 co。;scipy 1.0 中可用的内点方法非常好;但尽管采用了自对偶设计:不可行性检测通常比 Simplex 差)。使用真正的求解器,无论是商业广告还是 Clp、Google 的或工具、Glpk……甚至可能是 SCIP/Soplex 的有理单纯形!
-
@sascha 因为我输入了被构造为线性可分的集合,所以可行集合永远不会为空。所以输出应该都是 1。感谢 cmets - 我想我会尝试不同的求解器。
标签: python scipy linear-programming numerical-methods