numpy 2 차 배열에 대한 indexing의 계산 속도

11031 단어 파이썬numpy
numpy의 2차 배열이 있고, 다음과 같이 행과 열을 indexing하는 것을 생각합니다.
(아래 그림에서는 6x6의 2차 배열에서 [[9, 12], [21, 24]]를 꺼내려고 합니다)



이 때 계산 방법에 따라 속도에 상당한 차이가있었습니다!
# 巨大な二次配列からランダムな行、列の要素を抽出する
import numpy as np

N = 10000
X = np.arange(N ** 2).reshape(N, N)

M = 100
a = np.random.choice(N, M)
b = np.random.choice(N, M)

%timeit Y1 = X[a][:, b] 
# 実行例) 1.09 ms ± 243 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit Y2 = X[a[:, np.newaxis], b]
# 実行例) 66.8 µs ± 1.56 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
X[a][:, b] 보다 X[a[:, np.newaxis], b] 의 계산 쪽이 압도적으로 고속입니다.

다음은 사족입니다만, 원래 위의 그림과 같이 2차 배열에 대해서 indexing하는데 손이 들었으므로, 여기에 이르기까지의 우여곡절을 남겨 둡니다.

Slice의 경우



이 경우에는 간단합니다.
import numpy as np
N = 10000
X = np.arange(N ** 2).reshape(N, N)

a = np.s_[0:100]      # 行に関するslice
b = np.s_[100:300]    # 列に関するslice
# スライスした結果
Y = X[a, b]           # Y.shape = (100,200)

라고 표현할 수 있습니다. 다만, 보다 유연하게 행·열을 꺼내려고 하면 슬라이스라고 한계가 있습니다.

Indexing의 경우 (실패 예)



위와 같이 하려고 하면 실은 잘 되지 않습니다.
import numpy as np
N = 10000
X = np.arange(N ** 2).reshape(N, N)

a = np.arange(0,100)       # 行に関するindexing
b = np.arange(100, 300)    # 列に関するindexing
# indexingの結果
Y = X[a, b]           # エラーが起きる

2차원 배열에 대해 위와 같이 indexing하는 경우 a와 b는 같은 길이의 배열이어야 합니다.
또한 같은 길이에서도 다음과 같은 배열이 반환됩니다.
import numpy as np
N = 10000
X = np.arange(N ** 2).reshape(N, N)

a = np.arange(3)      # 行に関するindexing
b = np.arange(3)      # 列に関するindexing
# indexingの結果
Y = X[a, b]           # 結果: [0, 10001, 20002]

다만 Y[i] = X[a[i], b[i]] 라고 하는 거동입니다.

Indexing (성공 예)



위의 방법이 안 된다는 것으로 아래와 같이 재작성하면 상정대로 indexing 할 수 있었습니다.
import numpy as np
N = 10000
X = np.arange(N ** 2).reshape(N, N)

a = np.arange(0,100)       # 行に関するindexing
b = np.arange(100, 300)    # 列に関するindexing
# indexingの結果
Y = X[a][:, b]           

다만, numpy 문서 을 읽어 보면 이런 기술이.

So note that x[0,2] = x[0][2] though the second case is more inefficient as a new temporary array is created after the first index that is subsequently indexed by 2.

X[a] 로 하는 것으로, 일시적인 배열이 생성되어 효율이 나쁜 것 같습니다.
실제로, 처음의 코드에서도 보여준 것처럼 2차 배열이 커지면 계산 시간에 여전히 영향을 주었습니다.

재게재이지만 최종 indexing 방법은 다음과 같습니다.
import numpy as np
N = 10000
X = np.arange(N ** 2).reshape(N, N)

a = np.arange(0,100)       # 行に関するindexing
b = np.arange(100, 300)    # 列に関するindexing
# indexingの結果
Y = X[a[:, np.newaxis], b]           

이상, 사족이었습니다.
시행착오로의 결과이므로, 보다 효율적인 방법이 있으면 꼭 가르쳐 주셨으면 합니다.

좋은 웹페이지 즐겨찾기