Случайно перемешивать элементы в каждой строке массива - PullRequest
0 голосов
/ 27 мая 2018

У меня есть пустой массив, подобный следующему:

Xtrain = np.array([[1, 2, 3],
                   [4, 5, 6],
                   [1, 7, 3]])

Я хочу перетасовать элементы каждой строки отдельно, но не хочу, чтобы перемешивание было одинаковым для каждой строки (как в нескольких примерахпросто порядок столбцов в случайном порядке).

Например, я хочу вывод, подобный следующему:

output = np.array([[3, 2, 1],
                   [4, 6, 5],
                   [7, 3, 1]])

Как можно эффективно произвольно перемешать в случайном порядке каждую из строк?Мой фактический массив np превышает 100000 строк и 1000 столбцов.

Ответы [ 5 ]

0 голосов
/ 27 мая 2018

Это решение никоим образом неэффективно, но мне было интересно об этом думать, поэтому я записал его.По сути, вы разбиваете массив и создаете массив меток строк и массив индексов.Вы перемешиваете индексный массив и индексируете массивы меток оригинала и строки вместе с этим.Затем вы применяете stable argsort к меткам строк, чтобы собрать данные в строки.Примените этот индекс и измените форму и альт, данные перетасовываются независимо по строкам:

import numpy as np

r, c = 3, 4  # x.shape

x = np.arange(12) + 1  # Already raveled 
inds = np.arange(x.size)
rows = np.repeat(np.arange(r).reshape(-1, 1), c, axis=1).ravel()

np.random.shuffle(inds)
x = x[inds]
rows = rows[inds]

inds = np.argsort(rows, kind='mergesort')
x = x[inds].reshape(r, c)

Вот ссылка IDEOne

0 голосов
/ 27 мая 2018

Допустим, у вас есть массив a с формой 100000 x 1000.

b = np.random.choice(100000 * 1000, (100000, 1000), replace=False)
ind = np.argsort(b, axis=1)
a_shuffled = a[np.arange(100000)[:,np.newaxis], ind]

Я не знаю, если это быстрее, чем цикл, потому что он требует сортировки, но с этим решением, возможно, вы будетепридумать что-нибудь получше, например, с np.argpartition вместо np.argsort

0 голосов
/ 27 мая 2018

Поскольку вы хотите перетасовать только столбцы, вы можете просто выполнить перетасовку для транспонированной матрицы:

In [86]: np.random.shuffle(Xtrain.T)

In [87]: Xtrain
Out[87]: 
array([[2, 3, 1],
       [5, 6, 4],
       [7, 3, 1]])

Обратите внимание, что random.suffle () в двумерном массиве перемешивает строки, а не элементы в каждой строке.т.е. меняет положение строк.Поэтому, если вы измените положение транспонированных строк матрицы, вы фактически перетасуете столбцы вашего исходного массива.

Если вам все еще требуется полностью независимое перемешивание, вы можете создать случайные индексы для каждой строки, а затем создать окончательный результат.массив с простой индексацией:

In [172]: def crazyshuffle(arr):
     ...:     x, y = arr.shape
     ...:     rows = np.indices((x,y))[0]
     ...:     cols = [np.random.permutation(y) for _ in range(x)]
     ...:     return arr[rows, cols]
     ...: 

Демо:

In [173]: crazyshuffle(Xtrain)
Out[173]: 
array([[1, 3, 2],
       [6, 5, 4],
       [7, 3, 1]])

In [174]: crazyshuffle(Xtrain)
Out[174]: 
array([[2, 3, 1],
       [4, 6, 5],
       [1, 3, 7]])
0 голосов
/ 27 мая 2018

Мы можем создать случайную двумерную матрицу, отсортировать ее по каждой строке и затем использовать индексную матрицу, заданную argsort, для изменения порядка целевой матрицы.

target = np.random.randint(10, size=(5, 5))
# [[7 4 0 2 5]
# [5 6 4 8 7]
# [6 4 7 9 5]
# [8 6 6 2 8]
# [8 1 6 7 3]]

shuffle_helper = np.argsort(np.random.rand(5,5), axis=1)
# [[0 4 3 2 1]
# [4 2 1 3 0]
# [1 2 3 4 0]
# [1 2 4 3 0]
# [1 2 3 0 4]]

target[np.arange(shuffle_helper.shape[0])[:, None], shuffle_helper]
# array([[7, 5, 2, 0, 4],
#       [7, 4, 6, 8, 5],
#       [4, 7, 9, 5, 6],
#       [6, 6, 8, 2, 8],
#       [1, 6, 7, 8, 3]])

Пояснение

  • Мы используем np.random.rand и argsort для имитации эффекта перетасовки.
  • random.rand дает случайность.
  • Затем мы используем argsort с axis=1, чтобы помочь ранжировать каждую строку.Это создает индекс, который можно использовать для переупорядочения.
0 голосов
/ 27 мая 2018

От: https://github.com/numpy/numpy/issues/5173

def disarrange(a, axis=-1):
    """
    Shuffle `a` in-place along the given axis.

    Apply numpy.random.shuffle to the given axis of `a`.
    Each one-dimensional slice is shuffled independently.
    """
    b = a.swapaxes(axis, -1)
    # Shuffle `b` in-place along the last axis.  `b` is a view of `a`,
    # so `a` is shuffled in place, too.
    shp = b.shape[:-1]
    for ndx in np.ndindex(shp):
        np.random.shuffle(b[ndx])
    return
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...