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 Nvalores máximos.
Por ejemplo, si tengo una matriz, [1, 3, 2, 4, 5], function(array, n=3)volvería los índices [4, 3, 1]que corresponden a los elementos [5, 4, 3].
python
numpy
max
numpy-ndarray
Alexis Métaireau
fuente
fuente

array([5, 1, 5, 5, 2, 3, 2, 4, 1, 5]), pizcan= 3? ¿Cuál de todas las alternativas, como[0, 2, 3],[0, 2, 9],...sería la correcta? Por favor, explique más sobre sus requisitos específicos. Graciasargsortpodría ser una alternativa viable si no le importa el orden de las devoluciones devueltas. Vea mi respuesta a continuación.Respuestas:
Lo más simple que he podido encontrar es:
Esto implica un tipo completo de la matriz. Me pregunto si
numpyproporciona una forma integrada de hacer una clasificación parcial; Hasta ahora no he podido encontrar uno.Si esta solución resulta ser demasiado lenta (especialmente para los pequeños
n), puede valer la pena buscar codificar algo en Cython .fuente
arr.argsort()[-1:-4:-1]? Lo probé en el intérprete y aparece el mismo resultado, pero me pregunto si no está roto por algún ejemplo.np.argsort(-arr)[:3], que me parece más legible y al grano.arr.argsort()[::-1][:n]es mejor porque regresa vacío para enn=0lugar de la matriz completaLas versiones más recientes de NumPy (1.8 y superiores) tienen una función llamada
argpartitionpara esto. Para obtener los índices de los cuatro elementos más grandes, hagaA diferencia
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 la evaluacióna[ind]. Si también lo necesitas, clasifícalos después:Para obtener los elementos top- k en orden ordenado de esta manera se necesita tiempo O ( n + k log k ).
fuente
argpartitionejecuta en tiempo lineal, O (n), utilizando el algoritmo de introselección . La clasificación posterior solo maneja k elementos, de modo que se ejecuta en O (k log k).np.argpartitiony su algoritmo hermano,np.partitionhay una explicación más detallada en la pregunta vinculada: stackoverflow.com/questions/10337533/…a=np.array([9, 4, 4, 3, 3, 9, 0, 4, 6, 0])porque las listas normal de Python no son compatibles con la indexación de las listas, a diferencia denp.arraynp.argpartitiontoma unaxisargumento opcional . Para encontrar los índices de los valores n superiores para cada fila:np.argpartition(a, -n, axis=1)[-n:]Más simple aún:
donde n es el número de valores máximos.
fuente
arr[arr.argsort()[-n:]]en lugar de negar la matriz, acaba de tomar una rebanada de los últimos elementos nUtilizar:
Para listas regulares de Python:
Si usa Python 2, use en
xrangelugar derange.Fuente: heapq - Algoritmo de cola de montón
fuente
heapq.nlargest(3, xrange(len(a)), a.take). Para las listas de Python podemos usar en.__getitem__lugar de.take.Aen general:heapq.nlargest(3, range(len(A.ravel())), A.ravel().take). (Espero que esto solo funcione en vistas, ver también (ravel vs flatten] ( stackoverflow.com/a/28930580/603003 )).Si está trabajando con una matriz multidimensional, deberá aplanar y desentrañar los índices:
Por ejemplo:
fuente
Si no le importa el orden de los elementos K-th más grandes que puede usar
argpartition, que deberían funcionar mejor que una clasificación completaargsort.Los créditos van a esta pregunta .
Ejecuté algunas pruebas y parece que tiene un
argpartitionrendimiento superior aargsortmedida que aumenta el tamaño de la matriz y el valor de K.fuente
Para las matrices multidimensionales, puede usar la
axispalabra clave para aplicar la partición a lo largo del eje esperado.Y para agarrar los artículos:
Pero tenga en cuenta que esto no devolverá un resultado ordenado. En ese caso, puede usar a lo
np.argsort()largo del eje previsto:Aquí hay un ejemplo:
fuente
np.take_along_axis(que probablemente no existía cuando respondió esta pregunta)Esto será más rápido que una clasificación completa, dependiendo del tamaño de su matriz original y el tamaño de su selección:
Por supuesto, implica la manipulación de su matriz original. Lo que puede solucionar (si es necesario) haciendo una copia o reemplazando los valores originales. ... lo que sea más barato para su caso de uso.
fuente
argmax(.)no es ambigua también. (En mi humilde opinión, intenta seguir algún tipo de lógica de cortocircuito, pero desafortunadamente no proporciona un comportamiento universalmente aceptable). GraciasEl método
np.argpartitionsolo devuelve los k índices más grandes, realiza una ordenación local y es más rápido quenp.argsort(realizar 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 orden ascendente estricto de k índices superiores,
np.argpartitionno le devolverá lo que desea.Además de hacer una clasificación manual después de np.argpartition, mi solución es usar PyTorch,
torch.topkuna herramienta para la construcción de redes neuronales, que proporciona API similares a 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 matriz / vector.El estricto código de los principales índices de ascenso / descenso será:
Tenga en cuenta que
torch.topkacepta un tensor de antorcha y devuelve los valores k superiores y los índices k superiores en tipotorch.Tensor. Similar a np, torch.topk también acepta un argumento de eje para que pueda manejar matrices / tensores multidimensionales.fuente
Utilizar:
Ahora la
resultlista contendría N tuplas (index,value) dondevalueestá maximizada.fuente
Utilizar:
También funciona con matrices 2D. Por ejemplo,
fuente
bottlenecktiene una función de ordenación parcial, si el gasto de ordenar la matriz completa solo para obtener los N valores más grandes es demasiado grande.No sé nada sobre este módulo; Yo solo busqué en Google
numpy partial sort.fuente
La siguiente es una manera muy fácil de ver los elementos máximos y sus posiciones. Aquí
axisestá el dominio;axis= 0 significa número máximo de columna yaxis= 1 significa número máximo de fila para el caso 2D. Y para dimensiones superiores depende de ti.fuente
Lo encontré más intuitivo de usar
np.unique.La idea es que el método único devuelve 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.
fuente
Creo que la forma más eficiente de tiempo es iterar manualmente a través de la matriz y mantener un montón mínimo de tamaño k, como han mencionado otras personas.
Y también se me ocurre un enfoque de fuerza bruta:
Establezca el elemento más grande en un valor negativo grande después de usar argmax para obtener su índice. Y luego la próxima llamada de argmax devolverá el segundo elemento más grande. Y puede registrar el valor original de estos elementos y recuperarlos si lo desea.
fuente
Este código funciona para una matriz de matriz numpy:
Esto produce una indexación de matriz n_largest verdadero-falso que también funciona para extraer elementos n_largest de una matriz de matriz
fuente