matlab: случайная перестановка строк и столбцов двумерного массива - PullRequest
0 голосов
/ 09 декабря 2011

У меня большая матрица (около 80 000 X 60 000), и я в основном хочу скремблировать все записи (то есть, случайным образом переставить как строки, так и столбцы независимо).

Я полагаю, что это сработает, если я переберу столбцы и использую randperm для случайной перестановки каждого столбца. (Или я мог бы с тем же успехом делать строки.) Поскольку это включает цикл с итерациями по 60 КБ, мне интересно, может ли кто-нибудь предложить более эффективный вариант?

Я также работал с numpy / scipy, так что если вы знаете хороший вариант в python, это тоже было бы здорово.

Спасибо! Susan

Спасибо за все продуманные ответы! Немного больше информации: строки матрицы представляют документы, а данные в каждой строке представляют собой вектор весов tf-idf для этого документа. Каждый столбец соответствует одному термину в словаре. Я использую pdist для вычисления сходства косинусов между всеми парами статей. И я хочу создать случайный набор документов для сравнения.

Я думаю, что тогда будет работать только перестановка столбцов, потому что каждой статье назначается случайный набор частот терминов. (Перестановка строк означает просто переупорядочение документов.) Как отметил Джонатан, это дает преимущество не в том, чтобы делать новую копию всей матрицы, и похоже, что все остальные варианты будут.

Ответы [ 3 ]

4 голосов
/ 09 декабря 2011

Вы должны быть в состоянии reshape преобразовать матрицу в 1 × 4800000000 «массив», randperm это и, наконец, reshape вернуть обратно в матрицу 80000 × 60000.

Для этого потребуется скопировать 4,8 миллиарда записей в худшем случае 3 раза.Это может быть неэффективно.

EDIT : На самом деле Matlab автоматически использует линейное индексирование, поэтому первый reshape не требуется.Достаточно просто

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

(таким образом, уменьшая 1 ненужное потенциальное копирование).


Обратите внимание, что это предполагает, что у вас плотная матрица.Если у вас есть разреженная матрица, вы можете извлечь значения, а затем случайным образом переназначить им индексы.Если имеется N ненулевых записей, то в худшем случае требуется только 8N копирование (для описания одной записи требуется 3 числа).

2 голосов
/ 09 декабря 2011

Я думаю, что было бы лучше сделать это:

import numpy as np

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

Вы в основном сводите матрицу к списку, перетасовываете список и затем восстанавливаете матрицу из списка.

0 голосов
/ 09 декабря 2011

Оба вышеупомянутых решения великолепны и будут работать, но я полагаю, что оба будут включать в себя создание совершенно новой копии всей матрицы в памяти при выполнении работы.Поскольку это огромная матрица, это довольно больно.В случае решения MATLAB, я думаю, вы, возможно, создадите две дополнительные временные копии, в зависимости от того, как внутреннее изменение формы.Я думаю, что вы были на правильном пути, работая с колонками, но проблема в том, что он будет карабкаться только по колонкам.Тем не менее, я полагаю, что после того, как вы выполните randperm вдоль строк, вы получите полностью переставленную матрицу.Таким образом, вы будете создавать только временные переменные, которые в худшем случае равны 80 000 на 1. Да, это два цикла по 60 000 и 80 000 итераций в каждом, но внутри это должно произойти независимо.Алгоритм должен посещать каждую ячейку памяти как минимум дважды.Вероятно, вы могли бы сделать более эффективный алгоритм, написав функцию C MEX, которая работает полностью на месте, но я предполагаю, что вы бы предпочли этого не делать.

...