我想生成大小的矩阵m
X n
和秩r
包含元素从指定的有限集合,例如未来{0,1}
或{1,2,3,4,5}
我希望他们能在这个词的一些很不确切的“随机”,即我想从与分布依稀相似,所有矩阵超过该集合与指定等级元素的分布算法获得各种可能的输出。
其实,我并不真正关心它的秩r
只是它的接近秩的矩阵r
由弗罗比尼斯范数计)。
当设置在手是实数,我已经执行以下操作,这是完全足够我需要:生成矩阵U
尺寸的m
X r
和V
的n
X r
,0从例如普通独立地采样元件(, 2)。 然后U V'
是一个m
X n
秩的矩阵r
当然, <= r
,但我认为这是r
以高概率)。
如果我这样做,然后一轮二进制/ 1-5,不过,排名上升。
它也可以通过做SVD和采取率先拿到下级近似矩阵r
奇异值。 这些值,不过,不会说谎在所需的设定,并四舍五入他们将再次提高等级。
这个问题是相关的,但接受的答案是没有“随机”而对方的回答表明,SVD,这是指出不会在这里工作。
我想过的一种可能性是,使r
从组线性无关的行或列向量,然后通过这些的线性组合获得其矩阵的其余部分。 我不是很清楚,不过,无论是如何获得“随机”线性无关向量,或者如何在他们之后,一个准随机的方式结合起来。
(不,它是超相关的,但我在numpy的事情了。)
更新:我已经试过在评论由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)
它的工作原理迅速为小矩阵,但分崩离析为10×10如 - 它似乎停留在6级或7点,至少重复成千上万。
看起来这可能工作有一个更好的(即不太平坦的)目标函数更好,但我不知道这是什么会。
我也尝试了建立矩阵简单的消除方法:
def fill_matrix(m, n, r, vals):
assert m >= r and n >= r
trans = False
if m > n: # more columns than rows I think is better
m, n = n, m
trans = True
get_vec = lambda: np.array([random.choice(vals) for i in range(n)])
vecs = []
n_rejects = 0
# fill in r linearly independent rows
while len(vecs) < r:
v = get_vec()
if np.linalg.matrix_rank(np.vstack(vecs + [v])) > len(vecs):
vecs.append(v)
else:
n_rejects += 1
print("have {} independent ({} rejects)".format(r, n_rejects))
# fill in the rest of the dependent rows
while len(vecs) < m:
v = get_vec()
if np.linalg.matrix_rank(np.vstack(vecs + [v])) > len(vecs):
n_rejects += 1
if n_rejects % 1000 == 0:
print(n_rejects)
else:
vecs.append(v)
print("done ({} total rejects)".format(n_rejects))
m = np.vstack(vecs)
return m.T if trans else m
这工作好与任何级别如10×10的二值矩阵,而不是0-4矩阵或更低级别更大的二进制文件。 (例如,获取等级15的20×20二元矩阵把我拒绝42000;与排名10的20×20,花了120万美元。)
这显然是因为由第一跨越的空间r
行是我是从取样的空间中,例如过小的部分{0,1}^10
,在这些情况下。
我们希望第一跨度的交叉r
行与有效值的集合。 因此,我们可以尝试从跨度采样,并寻找有效的值,但由于跨度涉及这永远不会找到我们有效载体实值系数(即使我们正常化使得例如第一部分是在有效集)。
也许这可以用公式为整数规划问题,还是什么?