Numpy: самый быстрый способ изменить 10% всех матричных элементов - PullRequest
1 голос
/ 21 февраля 2020

У меня есть матрица M размера m x n. В настоящее время, если я хочу изменить 10% всех матричных элементов в процессе, я делаю следующее:

M = np.ones((m, n))
for _ in range(999999999):
    M = M + (np.random.random(M.shape) < 0.1) * np.random.random(M.shape)
    # do stuff with M

Этот подход, однако, очень медленный во многих итерациях и для больших матриц и требует m*n случайных чисел когда мне действительно нужно только 0.1*m*n.

Как я могу выполнить описанную выше операцию намного быстрее?

Ответы [ 2 ]

1 голос
/ 21 февраля 2020

Я дал это взломать, и предложил один метод, который выполняется быстрее на моем ноутбуке. Я не сделал итераций от go до 1B!

Лучший исполнитель:

%timeit advancedSlice()
9.56 s ± 12.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

def advancedSlice():
    M = np.arange(12000000.0).reshape(1200,10000)
    rows = M.shape[0]
    cols = M.shape[1]
    sampleSize = M.size//10
    for _ in range(100):
        M[np.random.randint(rows, size=sampleSize), np.random.randint(cols, size=sampleSize),] += np.random.random(sampleSize)
    return M

2-й лучший исполнитель: с использованием метода Михаэля

%timeit advancedSlice2()
22.8 s ± 11.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

def advancedSlice2():
    M = np.arange(12000000.0).reshape(1200,10000)

    for _ in range(100):
        randIndecies =np.random.rand(*M.shape)>=0.9
        M[randIndecies] += np.random.random(randIndecies[randIndecies==True].size)
    return M

Оригинальный код:

%timeit randMask()
33.2 s ± 211 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

def randMask():
    M = np.arange(12000000.0).reshape(1200,10000)
    for _ in range(100):
        M = M + (np.random.random(M.shape)  < 0.1) * np.random.random(M.shape)
    return M
1 голос
/ 21 февраля 2020

Вы можете изменить значения со случайной индексацией, если ваш сценарий использования может допускать приблизительно 10% значений:

import numpy as np
a = np.ones((10,10))
a[np.random.rand(*a.shape)>=0.9] = 0.
a
array([[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
       [0., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 0., 1., 1., 1., 1., 1.],
       [1., 1., 1., 0., 1., 1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1., 1., 1., 0., 0., 1.],
       [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
       [1., 1., 1., 0., 1., 1., 0., 1., 1., 1.],
       [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1., 1., 1., 1., 0., 1.],
       [1., 1., 1., 1., 1., 1., 1., 1., 0., 1.]])

Как вы можете видеть, вы получите примерно 10 измененных значений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...