2016-06-14 4 views
1

Я работаю с массивами NumPy.Эффективно изменить матрицу numpy

У меня есть 2N длины вектор D а и хочу, чтобы изменить его часть в N x N массив C.

Сейчас этот код делает то, что я хочу, но является узким местом для увеличения N:

`` `

import numpy as np 
M = 1000 
t = np.arange(M) 
D = np.sin(t) # initial vector is a sin() function 
N = M/2 
C = np.zeros((N,N)) 
for a in xrange(N): 
    for b in xrange(N): 
     C[a,b] = D[N + a - b] 

` ``

После C сделан я иду вперед и сделайте некоторую матричную арифметику на нем и т. д.

Этот вложенный цикл довольно медленный, но поскольку эта операция является по существу изменением индекса Я понял, что могу использовать встроенную формулу NumPy (numpy.reshape), чтобы ускорить эту часть.

К сожалению, я не могу найти способ преобразования этих показателей.

Любая помощь, ускоряющая эту часть вверх?

ответ

3

Вы можете использовать NumPy broadcasting удалить эти вложенные циклы -

C = D[N + np.arange(N)[:,None] - np.arange(N)] 

Можно также использовать np.take заменить индексацию, например, так -

C = np.take(D,N + np.arange(N)[:,None] - np.arange(N)) 

Более пристальный взгляд показывает образец, чтобы быть ближе до toeplitz и hankel Матрицы. Таким образом, используя их, у нас было бы еще два подхода к его решению, хотя с сопоставимыми ускорениями, как и с трансляцией. Реализации будет выглядеть примерно так это -

from scipy.linalg import toeplitz 
from scipy.linalg import hankel 

C = toeplitz(D[N:],np.hstack((D[0],D[N-1:0:-1]))) 
C = hankel(D[1:N+1],D[N:])[:,::-1] 

Продолжительность испытания

In [230]: M = 1000 
    ...: t = np.arange(M) 
    ...: D = np.sin(t) # initial vector is a sin() function 
    ...: N = M/2 
    ...: 

In [231]: def org_app(D,N): 
    ...:  C = np.zeros((N,N)) 
    ...:  for a in xrange(N): 
    ...:   for b in xrange(N): 
    ...:    C[a,b] = D[N + a - b] 
    ...:  return C 
    ...: 

In [232]: %timeit org_app(D,N) 
    ...: %timeit D[N + np.arange(N)[:,None] - np.arange(N)] 
    ...: %timeit np.take(D,N + np.arange(N)[:,None] - np.arange(N)) 
    ...: %timeit toeplitz(D[N:],np.hstack((D[0],D[N-1:0:-1]))) 
    ...: %timeit hankel(D[1:N+1],D[N:])[:,::-1] 
    ...: 
10 loops, best of 3: 83 ms per loop 
100 loops, best of 3: 2.82 ms per loop 
100 loops, best of 3: 2.84 ms per loop 
100 loops, best of 3: 2.95 ms per loop 
100 loops, best of 3: 2.93 ms per loop 
+0

Awesome! Это обеспечило значительное ускорение цикла. – jjgoings

+0

@jjgoings Yup, подтвердил это! – Divakar