Python 生成";“随机”;固定元素集上某一秩的矩阵

Python 生成";“随机”;固定元素集上某一秩的矩阵,python,matlab,math,numpy,linear-algebra,Python,Matlab,Math,Numpy,Linear Algebra,我想生成大小为mxn和秩为r的矩阵,元素来自指定的有限集,例如{0,1}或{1,2,3,4,5}。我希望它们是“随机”的,在这个词的某个非常松散的意义上,也就是说,我希望从算法中获得各种可能的输出,其分布模糊地类似于所有矩阵在具有指定秩的元素集合上的分布 事实上,我并不关心它是否有秩r,只是它接近秩r(由Frobenius范数度量)的矩阵 当手头的集合是reals时,我已经做了以下工作,这完全满足了我的需要:生成大小为mxr和V的nxr的矩阵,并从中独立采样元素,例如Normal(0,2)。然后

我想生成大小为
m
x
n
和秩为
r
的矩阵,元素来自指定的有限集,例如
{0,1}
{1,2,3,4,5}
。我希望它们是“随机”的,在这个词的某个非常松散的意义上,也就是说,我希望从算法中获得各种可能的输出,其分布模糊地类似于所有矩阵在具有指定秩的元素集合上的分布

事实上,我并不关心它是否有秩
r
,只是它接近秩
r
(由Frobenius范数度量)的矩阵

当手头的集合是reals时,我已经做了以下工作,这完全满足了我的需要:生成大小为
m
x
r
V
n
x
r
的矩阵,并从中独立采样元素,例如Normal(0,2)。然后
uv'
是秩
r
m
x
n
矩阵(好的,
=r和n>=r)
反式=假
如果m>n:#我认为列多于行更好
m、 n=n,m
trans=真
get_vec=lambda:np.array([random.choice(VAL)表示范围(n)中的i)])
vecs=[]
n_拒绝=0
#填充r个线性独立的行
而len(vecs)len(vecs):
附加向量(v)
其他:
n_拒绝+=1
打印(“具有{}独立({}拒绝)”。格式(r,n_拒绝))
#填写其余的相关行
而len(vecs)len(vecs):
n_拒绝+=1
如果n_拒绝%1000==0:
打印(n_拒绝)
其他:
附加向量(v)
打印(“完成({}全部拒绝)”。格式(n_拒绝))
m=np.vstack(向量)
如果trans-else m,则返回m.T
这适用于任何秩的10x10二进制矩阵,但不适用于0-4个矩阵或秩较低的更大二进制矩阵(例如,获得秩15的20x20二进制矩阵需要42000次拒绝;使用秩10的20x20,需要120万次拒绝)

这显然是因为第一个
r
行所跨越的空间在我采样的空间中太小了,例如在这些情况下,
{0,1}^10

我们需要第一个
r
行的跨度与有效值集的交点。 因此,我们可以尝试从范围中采样并寻找有效值,但由于范围涉及实值系数,因此永远无法找到有效向量(即使我们进行规范化,例如,第一个分量在有效集中)


也许这可以表述为一个整数规划问题,或者什么的?

我的朋友丹尼尔·约翰逊(Daniel Johnson)在上面发表了评论,他提出了一个想法,但我看到他从未发布过。它不是很充实,但你可能能够适应它

如果
A
是m-by-r,
B
是r-by-n,并且两者都有秩r,那么
AB
有秩r。现在,我们只需要选择
A
B
,这样
AB
只有给定集合中的值。最简单的情况是
S={0,1,2,…,j}

一种选择是使用适当的行/列和生成一个二进制文件 这保证了正确的秩和
B
,列和相加为no 超过
j
(因此产品中的每个术语都是
S
)和行总和 挑选以引起排名
r
(或者至少鼓励它,因为可能会被拒绝 使用)

我只是觉得我们可以得出两个独立的样本
A
B
上的方案比尝试更简单、更快速 一次攻击整个矩阵。不幸的是,我所有的矩阵 采样代码在另一台计算机上。我知道它很容易推广 允许输入大于
{0,1}
(即
S
)的项,但我不能 还记得计算是如何用
m*n
缩放的吗


我不确定这个解决方案会有多有用,但你可以构造一个矩阵,允许你在另一个矩阵上搜索该解决方案,其中只有0和1作为条目。如果你在二进制矩阵上随机搜索,这相当于随机修改最终矩阵的元素,但也有可能想出一些规则这比随机搜索要好得多

如果要在元素集E和元素ei上生成
m
-by-
n
矩阵,
0这样如何

rank = 30
n1 = 100; n2 = 100
from sklearn.decomposition import NMF
model = NMF(n_components=rank, init='random', random_state=0)
U = model.fit_transform(np.random.randint(1, 5, size=(n1, n2)))
V = model.components_
M = np.around(U) @ np.around(V)

当你的矩阵是在有限集合上定义的,比如
{0,1}
{1,2,3,4,5}
你是否也在使用与这些集合上的向量空间一致的运算?如果不是,你将遇到问题。(例如,你必须对元素
{0,1,2,3,4}进行算术mod 5)
获取该集合上的一组有效矩阵。您不能使用实值算术并期望随机抽取、线性组合等被关闭。)@很抱歉,我忘了提到我使用的是正规实向量空间。这就是我想要的:R上的矩阵,但其元素来自这些有限集。如果我做线性组合的事情,我显然必须小心这样做,元素仍然位于所讨论的集合中,但我希望秩w.R.t.实是
r
。我认为你不能像那样混合和匹配基础字段。如果线性独立性的定义包括矩阵行/列中条目的实值系数,那么某些列的跨度可以是r上矩阵的巨大子集,而不是有限集上的矩阵。如果你处理matrIce必须在有限集上,然后你必须处理这个运算
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
rank = 30
n1 = 100; n2 = 100
from sklearn.decomposition import NMF
model = NMF(n_components=rank, init='random', random_state=0)
U = model.fit_transform(np.random.randint(1, 5, size=(n1, n2)))
V = model.components_
M = np.around(U) @ np.around(V)