NumPy 배열에서 N 최대 값의 인덱스를 어떻게 얻습니까?
NumPy는를 통해 배열의 최대 값에 대한 인덱스를 얻는 방법을 제안합니다 np.argmax
.
비슷한 것을 원하지만 N
최대 값 의 색인을 반환 합니다.
I 배열이있는 경우 예를 들어 [1, 3, 2, 4, 5]
, function(array, n=3)
인덱스 반환 [4, 3, 1]
요소에 대응 [5, 4, 3]
.
내가 생각해 낸 가장 간단한 방법은 다음과 같습니다.
In [1]: import numpy as np
In [2]: arr = np.array([1, 3, 2, 4, 5])
In [3]: arr.argsort()[-3:][::-1]
Out[3]: array([4, 3, 1])
여기에는 완전한 종류의 배열이 포함됩니다. numpy
부분 정렬을 수행하는 기본 제공 방법을 제공 하는지 궁금합니다 . 지금까지 나는 그것을 찾을 수 없었습니다.
이 솔루션이 너무 느린 것으로 판명되면 (특히 작은 경우 n
) Cython 에서 코드를 작성하는 것이 좋습니다.
최신 NumPy 버전 (1.8 이상)에는이를 argpartition
위한 함수가 있습니다 . 네 가지 가장 큰 요소의 지수를 얻으려면
>>> a = np.array([9, 4, 4, 3, 3, 9, 0, 4, 6, 0])
>>> a
array([9, 4, 4, 3, 3, 9, 0, 4, 6, 0])
>>> ind = np.argpartition(a, -4)[-4:]
>>> ind
array([1, 5, 8, 0])
>>> a[ind]
array([4, 9, 6, 9])
와 달리 argsort
,이 함수는 최악의 경우 선형 시간으로 실행되지만 평가 결과에서 볼 수 있듯이 반환 된 인덱스는 정렬되지 않습니다 a[ind]
. 필요한 경우 나중에 정렬하십시오.
>>> ind[np.argsort(a[ind])]
array([1, 8, 5, 0])
이런 식으로 최상위 k 요소를 정렬 된 순서로 얻으려면 O ( n + k log k ) 시간이 걸립니다.
더 간단하면서도 :
idx = (-arr).argsort()[:n]
여기서 n 은 최대 값 수입니다.
사용하다:
>>> import heapq
>>> import numpy
>>> a = numpy.array([1, 3, 2, 4, 5])
>>> heapq.nlargest(3, range(len(a)), a.take)
[4, 3, 1]
일반 파이썬 목록의 경우 :
>>> a = [1, 3, 2, 4, 5]
>>> heapq.nlargest(3, range(len(a)), a.__getitem__)
[4, 3, 1]
Python 2를 사용 xrange
하는 경우 대신을 사용하십시오 range
.
출처 : heapq — 힙 큐 알고리즘
다차원 배열로 작업하는 경우 인덱스를 평평하게하고 풀어야합니다.
def largest_indices(ary, n):
"""Returns the n largest indices from a numpy array."""
flat = ary.flatten()
indices = np.argpartition(flat, -n)[-n:]
indices = indices[np.argsort(-flat[indices])]
return np.unravel_index(indices, ary.shape)
예를 들면 다음과 같습니다.
>>> xs = np.sin(np.arange(9)).reshape((3, 3))
>>> xs
array([[ 0. , 0.84147098, 0.90929743],
[ 0.14112001, -0.7568025 , -0.95892427],
[-0.2794155 , 0.6569866 , 0.98935825]])
>>> largest_indices(xs, 3)
(array([2, 0, 0]), array([2, 2, 1]))
>>> xs[largest_indices(xs, 3)]
array([ 0.98935825, 0.90929743, 0.84147098])
사용할 수 있는 K 번째로 큰 요소 의 순서 에 신경 쓰지 않으면 argpartition
전체 정렬보다 성능이 우수합니다 argsort
.
K = 4 # We want the indices of the four largest values
a = np.array([0, 8, 0, 4, 5, 8, 8, 0, 4, 2])
np.argpartition(a,-K)[-K:]
array([4, 1, 5, 6])
크레딧은 이 질문으로 갑니다 .
몇 가지 테스트를 실행 했으며 배열의 크기와 K의 값이 증가함에 따라 argpartition
성능이 뛰어 argsort
납니다.
다차원 배열의 경우 axis
키워드를 사용 하여 예상 축을 따라 분할을 적용 할 수 있습니다 .
# For a 2D array
indices = np.argpartition(arr, -N, axis=1)[:, -N:]
그리고 아이템을 잡기 위해 :
x = arr.shape[0]
arr[np.repeat(np.arange(x), N), indices.ravel()].reshape(x, N)
그러나 이렇게하면 정렬 된 결과가 반환되지 않습니다. 이 경우 np.argsort()
원하는 축을 따라 사용할 수 있습니다 .
indices = np.argsort(arr, axis=1)[:, -N:]
# Result
x = arr.shape[0]
arr[np.repeat(np.arange(x), N), indices.ravel()].reshape(x, N)
예를 들면 다음과 같습니다.
In [42]: a = np.random.randint(0, 20, (10, 10))
In [44]: a
Out[44]:
array([[ 7, 11, 12, 0, 2, 3, 4, 10, 6, 10],
[16, 16, 4, 3, 18, 5, 10, 4, 14, 9],
[ 2, 9, 15, 12, 18, 3, 13, 11, 5, 10],
[14, 0, 9, 11, 1, 4, 9, 19, 18, 12],
[ 0, 10, 5, 15, 9, 18, 5, 2, 16, 19],
[14, 19, 3, 11, 13, 11, 13, 11, 1, 14],
[ 7, 15, 18, 6, 5, 13, 1, 7, 9, 19],
[11, 17, 11, 16, 14, 3, 16, 1, 12, 19],
[ 2, 4, 14, 8, 6, 9, 14, 9, 1, 5],
[ 1, 10, 15, 0, 1, 9, 18, 2, 2, 12]])
In [45]: np.argpartition(a, np.argmin(a, axis=0))[:, 1:] # 1 is because the first item is the minimum one.
Out[45]:
array([[4, 5, 6, 8, 0, 7, 9, 1, 2],
[2, 7, 5, 9, 6, 8, 1, 0, 4],
[5, 8, 1, 9, 7, 3, 6, 2, 4],
[4, 5, 2, 6, 3, 9, 0, 8, 7],
[7, 2, 6, 4, 1, 3, 8, 5, 9],
[2, 3, 5, 7, 6, 4, 0, 9, 1],
[4, 3, 0, 7, 8, 5, 1, 2, 9],
[5, 2, 0, 8, 4, 6, 3, 1, 9],
[0, 1, 9, 4, 3, 7, 5, 2, 6],
[0, 4, 7, 8, 5, 1, 9, 2, 6]])
In [46]: np.argpartition(a, np.argmin(a, axis=0))[:, -3:]
Out[46]:
array([[9, 1, 2],
[1, 0, 4],
[6, 2, 4],
[0, 8, 7],
[8, 5, 9],
[0, 9, 1],
[1, 2, 9],
[3, 1, 9],
[5, 2, 6],
[9, 2, 6]])
In [89]: a[np.repeat(np.arange(x), 3), ind.ravel()].reshape(x, 3)
Out[89]:
array([[10, 11, 12],
[16, 16, 18],
[13, 15, 18],
[14, 18, 19],
[16, 18, 19],
[14, 14, 19],
[15, 18, 19],
[16, 17, 19],
[ 9, 14, 14],
[12, 15, 18]])
이것은 원래 배열의 크기와 선택한 크기에 따라 전체 정렬보다 빠릅니다.
>>> A = np.random.randint(0,10,10)
>>> A
array([5, 1, 5, 5, 2, 3, 2, 4, 1, 0])
>>> B = np.zeros(3, int)
>>> for i in xrange(3):
... idx = np.argmax(A)
... B[i]=idx; A[idx]=0 #something smaller than A.min()
...
>>> B
array([0, 2, 3])
물론 원래 배열을 변경하는 것도 포함됩니다. 사본을 만들거나 원래 값을 다시 대체하여 필요한 경우 수정할 수 있습니다. ... 사용 사례에 비해 저렴합니다.
메서드 np.argpartition
는 k 개의 가장 큰 인덱스 만 반환하고, 로컬 정렬을 수행하며, np.argsort
배열이 매우 클 때 (전체 정렬 수행) 보다 빠릅니다 . 그러나 반환 된 지수는 오름차순 / 내림차순 이 아닙니다 . 예를 들어 봅시다 :
우리는 엄격한 오름차순 주문 k 지수 np.argpartition
를 원한다면 원하는 것을 반환하지 않는다는 것을 알 수 있습니다.
np.argpartition 이후에 수동으로 정렬하는 것 외에도, 내 솔루션은 torch.topk
신경 네트워크 구성을위한 도구 인 PyTorch를 사용 하여 NumPy와 유사한 API에 CPU 및 GPU를 모두 지원하는 것입니다. MKL을 사용하면 NumPy만큼 빠르며 큰 행렬 / 벡터 계산이 필요한 경우 GPU를 향상시킵니다.
엄격한 오름차순 / 내림차순 k 지수 코드는 다음과 같습니다.
torch.topk
토치 텐서 를 받아들이고 top k 값과 top k 인덱스를 모두 type으로 반환합니다 torch.Tensor
. np와 마찬가지로 torch.topk는 축 인수를 허용하므로 다차원 배열 / 텐서를 처리 할 수 있습니다.
bottleneck
N 개의 가장 큰 값을 얻기 위해 전체 배열을 정렬하는 비용이 너무 큰 경우 부분 정렬 기능이 있습니다.
나는이 모듈에 대해 아무것도 모른다; 방금 봤어요 numpy partial sort
.
사용하다:
from operator import itemgetter
from heapq import nlargest
result = nlargest(N, enumerate(your_list), itemgetter(1))
이제 result
목록에는 최대화 된 N 개의 튜플 ( index
, value
) 이 포함 value
됩니다.
사용하다:
def max_indices(arr, k):
'''
Returns the indices of the k first largest elements of arr
(in descending order in values)
'''
assert k <= arr.size, 'k should be smaller or equal to the array size'
arr_ = arr.astype(float) # make a copy of arr
max_idxs = []
for _ in range(k):
max_element = np.max(arr_)
if np.isinf(max_element):
break
else:
idx = np.where(arr_ == max_element)
max_idxs.append(idx)
arr_[idx] = -np.inf
return max_idxs
2D 배열에서도 작동합니다. 예를 들어
In [0]: A = np.array([[ 0.51845014, 0.72528114],
[ 0.88421561, 0.18798661],
[ 0.89832036, 0.19448609],
[ 0.89832036, 0.19448609]])
In [1]: max_indices(A, 8)
Out[1]:
[(array([2, 3], dtype=int64), array([0, 0], dtype=int64)),
(array([1], dtype=int64), array([0], dtype=int64)),
(array([0], dtype=int64), array([1], dtype=int64)),
(array([0], dtype=int64), array([0], dtype=int64)),
(array([2, 3], dtype=int64), array([1, 1], dtype=int64)),
(array([1], dtype=int64), array([1], dtype=int64))]
In [2]: A[max_indices(A, 8)[0]][0]
Out[2]: array([ 0.89832036])
다음은 최대 요소와 위치를 볼 수있는 매우 쉬운 방법입니다. axis
도메인은 다음과 같습니다 . axis
= 0은 열 단위 최대 수를 axis
의미 하고 = 1은 2D 경우 행 최대 수를 의미합니다. 그리고 더 큰 치수의 경우 그것은 당신에게 달려 있습니다.
M = np.random.random((3, 4))
print(M)
print(M.max(axis=1), M.argmax(axis=1))
가장 직관적 인 사용을 발견했습니다 np.unique
.
아이디어는 고유 메소드가 입력 값의 색인을 리턴한다는 것입니다. 그런 다음 최대 고유 값과 지표에서 원래 값의 위치를 다시 만들 수 있습니다.
multi_max = [1,1,2,2,4,0,0,4]
uniques, idx = np.unique(multi_max, return_inverse=True)
print np.squeeze(np.argwhere(idx == np.argmax(uniques)))
>> [4 7]
다른 사람들이 언급했듯이 가장 시간 효율적인 방법은 수동으로 배열을 반복하고 k 크기의 최소 힙을 유지하는 것입니다.
그리고 나는 또한 무차별 대입 접근법을 생각해 냈습니다.
top_k_index_list = [ ]
for i in range(k):
top_k_index_list.append(np.argmax(my_array))
my_array[top_k_index_list[-1]] = -float('inf')
argmax를 사용하여 색인을 얻은 후 가장 큰 요소를 큰 음수 값으로 설정하십시오. 그리고 다음 argmax 호출은 두 번째로 큰 요소를 반환합니다. 또한 이러한 요소의 원래 값을 기록하고 원하는 경우 복구 할 수 있습니다.
'Programing' 카테고리의 다른 글
파이썬에서 ** kwargs를 사용하는 올바른 방법 (0) | 2020.02.21 |
---|---|
자식 준비 영역에서 파일을 제거하는 방법? (0) | 2020.02.21 |
컬러 리소스에서 color-int 가져 오기 (0) | 2020.02.21 |
언제 예외를 던지나요? (0) | 2020.02.21 |
스피너 텍스트 크기와 텍스트 색상을 변경하는 방법은 무엇입니까? (0) | 2020.02.21 |