matlab:随机打乱二维数组的行和列

0 投票
3 回答
2169 浏览
提问于 2025-04-17 08:03

我有一个很大的矩阵(大约80,000行和60,000列),我想把里面的所有数据打乱一下,也就是随机排列每一行和每一列。

我觉得可以通过循环每一列,使用randperm这个函数来随机打乱每一列的数据。(当然,我也可以选择打乱每一行。)不过因为这个循环要执行60,000次,我在想有没有更高效的方法?

我也在用numpy和scipy,所以如果你知道在Python中有什么好的方法,那就太好了。

谢谢!

感谢大家的热心回答!再补充一点信息:这个矩阵的每一行代表一篇文档,而每一行的数据是该文档的tf-idf权重向量。每一列对应词汇表中的一个词。我正在使用pdist来计算所有论文之间的余弦相似度。我想生成一组随机的论文来进行比较。

我觉得只打乱列就可以了,因为这样每篇论文会被分配到一组随机的词频。(打乱行只是意味着重新排列论文而已。)正如Jonathan提到的,这样的好处是不会创建整个矩阵的新副本,而其他方法似乎都会这样做。

3 个回答

0

上面提到的两种解决方案都不错,能解决问题,但我觉得这两种方法在处理时都会在内存中重新复制整个矩阵。这对于一个很大的矩阵来说,开销可不小。以MATLAB的方案为例,我觉得你可能会创建两个额外的临时副本,这取决于reshape这个函数内部是怎么工作的。我认为你在处理列的时候思路是对的,但问题在于这样只会在列之间打乱顺序。不过,如果你在此之后再对行进行随机排列,那么最终你就能得到一个完全打乱的矩阵。这样的话,你只需要创建一些临时变量,最多也就是80,000行1列。没错,这样会有两个循环,分别迭代60,000次和80,000次,但无论如何,内部还是得这样进行。这个算法至少要访问每个内存位置两次。你可能可以通过写一个C语言的MEX函数来实现更高效的算法,这样就可以完全在原地操作,但我猜你可能不太想这么做。

2

我觉得这样做会更好:

import numpy as np

flat = matrix.ravel()
np.random.shuffle(flat)

你基本上是在把一个矩阵变成一个列表,然后把这个列表打乱,最后再从这个列表重新构建一个矩阵。

4

你应该能把这个矩阵变成一个 1 × 4800000000 的“数组”,然后用 randperm 随机打乱一下,最后再把它变回 80000 × 60000 的矩阵。

这样做的话,最坏的情况是要复制 48 亿个数据三次。这可能效率不高。

编辑:其实 Matlab 会自动使用线性索引,所以第一次的 reshape 是不需要的。只要

reshape(x(randperm(4800000000), 80000, 60000))

就可以了(这样就减少了一次不必要的复制)。


注意,这里假设你有一个密集矩阵。如果你有一个稀疏矩阵,你可以先提取出值,然后随机重新分配索引。如果有 N 个非零的条目,那么最坏情况下只需要复制 8N 次(因为描述一个条目需要 3 个数字)。

撰写回答