不过,如果我这样做,然后四舍五入到二进制/1-5,排名就会增加。在
通过进行奇异值分解并取第一个r奇异值,也可以得到矩阵的低阶近似值。但是,这些值不会位于所需的集合中,取整它们将再次提高排名。在
This question是相关的,但接受的答案不是“随机的”,另一个答案是SVD,这在这里不起作用。在
我想到的一种可能性是从集合中使r线性独立的行或列向量,然后通过这些向量的线性组合得到矩阵的其余部分。我不太清楚,不管是如何得到“随机”的线性独立向量,还是之后如何以一种准随机的方式组合它们。在
(不是说它是超级相关的,但我在纽比做这个。)
更新:我尝试过EMS在评论中建议的方法,使用以下简单的实现:real = np.dot(np.random.normal(0, 1, (10, 3)), np.random.normal(0, 1, (3, 10)))
bin = (real > .5).astype(int)
rank = np.linalg.matrix_rank(bin)
niter = 0
while rank > des_rank:
cand_changes = np.zeros((21, 5))
for n in range(20):
i, j = random.randrange(5), random.randrange(5)
v = 1 - bin[i,j]
x = bin.copy()
x[i, j] = v
x_rank = np.linalg.matrix_rank(x)
cand_changes[n,:] = (i, j, v, x_rank, max((rank + 1e-4) - x_rank, 0))
cand_changes[-1,:] = (0, 0, bin[0,0], rank, 1e-4)
cdf = np.cumsum(cand_changes[:,-1])
cdf /= cdf[-1]
i, j, v, rank, score = cand_changes[np.searchsorted(cdf, random.random()), :]
bin[i, j] = v
niter += 1
if niter % 1000 == 0:
print(niter, rank)
它对小矩阵很快有效,但对于10x10这样的矩阵则会崩溃——它似乎在6或7级卡住了,至少在数十万次迭代中是这样。在
这看起来像是用一个更好的(即不太平坦的)目标函数更好地工作,但我不知道那会是什么。在
我还尝试了一种简单的拒绝方法来建立矩阵:
^{pr2}$
这适用于任何秩的10x10二进制矩阵,但不适用于0-4矩阵或更大的低秩二进制。(例如,得到一个排名为15的20x20二进制矩阵需要42000次拒绝;而排名为10的20x20则需要120万次拒绝。)
这显然是因为第一行r所跨越的空间在我采样的空间中太小了,例如在这些情况下{0,1}^10。在
我们需要第一个r行的跨度与一组有效值的交集。
所以我们可以试着从跨度中取样并寻找有效值,但由于跨度涉及实值系数,因此永远找不到有效向量(即使我们将其规格化,例如第一个分量在有效集中)。在
也许这可以表述为一个整数规划问题,或者其他什么?在