una tutorial transpuesta multiplicar matriz matrices funciones español elementos ejemplos crear con array agregar python numpy

python - tutorial - ¿Cómo obtengo índices de N valores máximos en una matriz NumPy?



numpy tutorial español pdf (15)

Creo que la forma más eficiente de tiempo es iterar manualmente a través de la matriz y mantener un min-heap tamaño k, como han mencionado otras personas.

Y también se me ocurre un enfoque de fuerza bruta:

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'')

Establezca el elemento más grande en un valor negativo grande después de usar argmax para obtener su índice. Y luego la siguiente llamada de argmax devolverá el segundo elemento más grande. Y puede registrar el valor original de estos elementos y recuperarlos si lo desea.

NumPy propone una forma de obtener el índice del valor máximo de una matriz a través de np.argmax .

Me gustaría algo similar, pero devolviendo los índices de los N valores máximos.

Por ejemplo, si tengo una matriz, [1, 3, 2, 4, 5] , la function(array, n=3) devolverá [4, 3, 1] .


El método np.argpartition solo devuelve los k índices más grandes, realiza una ordenación local y es más rápido que np.argsort (realiza una ordenación completa) cuando la matriz es bastante grande. Pero los índices devueltos NO están en orden ascendente / descendente . Digamos con un ejemplo:

Podemos ver que si desea un índice ascendente k de orden ascendente estricto, np.argpartition no devolverá lo que desea.

Además de hacer una ordenación manual después de np.argpartition, mi solución es usar PyTorch, torch.topk , una herramienta para la construcción de redes neuronales, que proporciona API de tipo NumPy con soporte para CPU y GPU. Es tan rápido como NumPy con MKL, y ofrece un impulso de GPU si necesita grandes cálculos de matrices / vectores.

El código de índices de ascenso / descenso superior k será:

Tenga en cuenta que torch.topk acepta un tensor de antorcha y devuelve tanto los valores k superiores como los índices k superiores en el tipo torch.Tensor . Similar a np, torch.topk también acepta un argumento de eje para que pueda manejar matrices / tensores multidimensionales.


Esto será más rápido que una ordenación completa dependiendo del tamaño de su matriz original y el tamaño de su selección:

>>> 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])

Por supuesto, implica la manipulación de su matriz original. Que podría arreglar (si es necesario) haciendo una copia o reemplazando los valores originales. ... lo que sea más barato para su caso de uso.


La siguiente es una manera muy fácil de ver los elementos máximos y sus posiciones. Aquí el axis es el dominio; axis = 0 significa el número máximo sabio de la columna y axis = 1 significa el número máximo sabio de la fila para el caso 2D. Y para dimensiones superiores depende de ti.

M = np.random.random((3, 4)) print(M) print(M.max(axis=1), M.argmax(axis=1))


Las nuevas versiones de NumPy (1.8 y superiores) tienen una función llamada argpartition para esto. Para obtener los índices de los cuatro elementos más grandes, haga

>>> 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])

A diferencia de argsort , esta función se ejecuta en tiempo lineal en el peor de los casos, pero los índices devueltos no están ordenados, como se puede ver en el resultado de evaluar a[ind] . Si también necesitas eso, ordénalos después:

>>> ind[np.argsort(a[ind])] array([1, 8, 5, 0])

Para obtener los mejores elementos de k en orden, de esta forma, se tarda O ( n + k log k ).


Lo más simple que he podido encontrar es:

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])

Esto implica un tipo completo de la matriz. Me pregunto si numpy proporciona una forma integrada de hacer una ordenación parcial; Hasta ahora no he podido encontrar uno.

Si esta solución resulta ser demasiado lenta (especialmente para las pequeñas n ), puede valer la pena considerar la codificación de algo en Cython .


Más simple aún:

idx = (-arr).argsort()[:n]

donde n es el número de valores máximos.


Me pareció más intuitivo usar np.unique .

La idea es que el método único devuelva los índices de los valores de entrada. Luego, a partir del valor único máximo y las indicaciones, se puede recrear la posición de los valores originales.

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]


Para matrices multidimensionales, puede utilizar la palabra clave axis para aplicar la partición a lo largo del eje esperado.

# For a 2D array indices = np.argpartition(arr, -N, axis=1)[:, -N:]

Y para agarrar los objetos:

x = arr.shape[0] arr[np.repeat(np.arange(x), N), indices.ravel()].reshape(x, N)

Pero tenga en cuenta que esto no devolverá un resultado ordenado. En ese caso, puede usar np.argsort() largo del eje deseado:

indices = np.argsort(arr, axis=1)[:, -N:] # Result x = arr.shape[0] arr[np.repeat(np.arange(x), N), indices.ravel()].reshape(x, N)

Aquí hay un ejemplo:

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]])


Si está trabajando con una matriz multidimensional, deberá aplanar y desentrañar los índices:

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)

Por ejemplo:

>>> 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])


Si no le importa el orden de los elementos K-th más grandes, puede usar argpartition , que debería funcionar mejor que una ordenación completa a través de 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])

Los créditos van a esta pregunta .

argpartition algunas pruebas y parece que argpartition supera a argsort medida que argsort el tamaño de la matriz y el valor de K.


Utilizar:

>>> import heapq >>> import numpy >>> a = numpy.array([1, 3, 2, 4, 5]) >>> heapq.nlargest(3, range(len(a)), a.take) [4, 3, 1]

Para las listas regulares de Python:

>>> a = [1, 3, 2, 4, 5] >>> heapq.nlargest(3, range(len(a)), a.__getitem__) [4, 3, 1]

Si usa Python 2, use xrange lugar de range .

Fuente: heapq - Algoritmo de cola de pila


Utilizar:

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

También funciona con matrices 2D. Por ejemplo,

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])


Utilizar:

from operator import itemgetter from heapq import nlargest result = nlargest(N, enumerate(your_list), itemgetter(1))

Ahora la lista de result contendría N tuplas ( index , value ) donde el value se maximiza.


bottleneck tiene una función de clasificación parcial, si el costo de ordenar la matriz completa solo para obtener los N valores más grandes es demasiado grande.

No sé nada de este módulo; Acabo de googled numpy partial sort .