Заполнение 4D матрицы 2d матрицами - PullRequest
0 голосов
/ 31 мая 2018

Мне было интересно, есть ли функция numpy, которая сделает это быстрее.Вот пример того, что я пытаюсь сделать.

def _sparse_4D_rand_mat(self, x, y, density):
    _4D_mat = np.empty((x, y, x, y))
    for i in range(self.size):
        for j in range(self.size):
            _4D_mat[:,i,j,:] = self._rand_sparse(x, y, density)
    return _4D_mat
def _rand_sparse(self, m, n, density, format='csr'):
    nnz = max(min(int(m * n * density), m * n), 0)
    row = np.random.random_integers(low=0, high=m - 1, size=nnz)
    col = np.random.random_integers(low=0, high=n - 1, size=nnz)
    data = np.ones(nnz, dtype=float)
    data = np.random.dirichlet(data)
    return csr_matrix((data, (row, col)), shape=(m, n)).toarray()

Спасибо за ваш вклад.Я новичок;)

1 Ответ

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

Поскольку плотность остается постоянной, вместо многократного вызова _rand_sparse для генерации множества небольших разреженных 2D-массивов, вы можете вызвать _rand_sparse один раз, чтобы создать один большой разреженный 2D-массив, а затем использовать метод reshape для изменения формы2D-результат в виде 4D-массива:

_4D_mat = _rand_sparse(x * y * x, y, density)
_4D_mat = _4D_mat.reshape((x, y, x, y))

Например,

import numpy as np
import scipy.sparse as sparse

def _rand_sparse(m, n, density, format='csr'):
    nnz = max(min(int(m * n * density), m * n), 0)
    # use randint since random_integer is deprecated in NumPy 1.11.0
    row = np.random.randint(low=0, high=m, size=nnz)
    col = np.random.randint(low=0, high=n, size=nnz)
    data = np.ones(nnz, dtype=float)
    data = np.random.dirichlet(data)
    return sparse.csr_matrix((data, (row, col)), shape=(m, n)).toarray()

def orig(x, y, density):
    _4D_mat = np.empty((x, y, x, y))
    for i in range(y):
        for j in range(x):
            _4D_mat[:, i, j, :] = _rand_sparse(x, y, density)
    return _4D_mat

def alt(x, y, density):
    _4D_mat = _rand_sparse(x * y * x, y, density)
    _4D_mat = _4D_mat.reshape((x, y, x, y))
    return _4D_mat

x, y, density = 2, 4, 0.5

Поскольку alt устраняет двойной цикл for, это решение будет намного быстрее, чем orig с ростом значений x и y (то есть с увеличением числа итераций в циклах for).На самом деле, даже для небольших значений, таких как использованные выше, alt уже (почти в 8 раз) быстрее, чем orig:

In [108]: %timeit orig(x, y, density)
100 loops, best of 3: 2.24 ms per loop

In [109]: %timeit alt(x, y, density)
1000 loops, best of 3: 281 µs per loop

Мне нужна сумма для каждого 2Dмассив в массиве 4D должен быть 1

Для нормализации соответствующих срезов вы можете использовать:

totals = np.nansum(_4D_mat, axis=0, keepdims=True)
totals = np.nansum(totals, axis=3, keepdims=True)
_4D_mat /= totals
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...