NumPy schlägt eine Möglichkeit vor, den Index des Maximalwerts eines Arrays über abzurufen np.argmax
.
Ich möchte etwas Ähnliches, aber die Indizes der N
Maximalwerte zurückgeben.
Wenn ich ein Array zum Beispiel haben, [1, 3, 2, 4, 5]
, function(array, n=3)
würde die Indizes zurück [4, 3, 1]
, die den Elementen entsprechen [5, 4, 3]
.
python
numpy
max
numpy-ndarray
Alexis Métaireau
quelle
quelle
array([5, 1, 5, 5, 2, 3, 2, 4, 1, 5])
, Whitn= 3
? Welche von allen Alternativen, wie[0, 2, 3]
,[0, 2, 9]
,...
wäre die richtige? Bitte erläutern Sie Ihre spezifischen Anforderungen. Dankeargsort
Dies ist möglicherweise eine praktikable Alternative, wenn Sie sich nicht um die Reihenfolge der zurückgegebenen Indeces kümmern. Siehe meine Antwort unten.Antworten:
Das einfachste, was ich mir vorstellen konnte, ist:
Dies beinhaltet eine vollständige Art des Arrays. Ich frage mich, ob es
numpy
eine eingebaute Möglichkeit gibt, eine Teilsortierung durchzuführen. Bisher konnte ich keinen finden.Wenn sich herausstellt, dass diese Lösung zu langsam ist (insbesondere für kleine
n
), lohnt es sich möglicherweise, etwas in Cython zu codieren .quelle
arr.argsort()[-1:-4:-1]
? Ich habe es im Dolmetscher versucht und es kommt zum gleichen Ergebnis, aber ich frage mich, ob es nicht durch ein Beispiel gebrochen wird.np.argsort(-arr)[:3]
, was ich besser lesbar und auf den Punkt finde.arr.argsort()[::-1][:n]
ist besser, weil es leer fürn=0
anstelle des vollständigen ArraysNeuere NumPy-Versionen (1.8 und höher) haben eine dafür aufgerufene Funktion
argpartition
. Um die Indizes der vier größten Elemente zu erhalten, tun Sie diesIm Gegensatz
argsort
dazu läuft diese Funktion im schlimmsten Fall in linearer Zeit, aber die zurückgegebenen Indizes werden nicht sortiert, wie aus dem Ergebnis der Auswertung hervorgehta[ind]
. Wenn Sie das auch brauchen, sortieren Sie sie anschließend:Um die top- zu bekommen k Elemente in sortierter Reihenfolge auf diese Weise nimmt O ( n + k log k ) Zeit.
quelle
argpartition
läuft in der linearen Zeit O (n) unter Verwendung des Introselect- Algorithmus. Die nachfolgende Sortierung behandelt nur k Elemente, sodass diese in O (k log k) ausgeführt werden.np.argpartition
und wie der Schwesteralgorithmusnp.partition
funktioniert, finden Sie in der verknüpften Frage eine ausführlichere Erklärung: stackoverflow.com/questions/10337533/…a=np.array([9, 4, 4, 3, 3, 9, 0, 4, 6, 0])
weil normale Python-Listen im Gegensatz zunp.array
np.argpartition
ein optionalesaxis
Argument. So finden Sie die Indizes der obersten n Werte für jede Zeile:np.argpartition(a, -n, axis=1)[-n:]
Noch einfacher:
Dabei ist n die Anzahl der Maximalwerte.
quelle
arr[arr.argsort()[-n:]]
anstatt das Array zu negieren, nehmen Sie einfach ein Stück der letzten n ElementeVerwenden:
Für reguläre Python-Listen:
Wenn Sie Python 2 verwenden, verwenden Sie
xrange
anstelle vonrange
.Quelle: heapq - Heap-Warteschlangenalgorithmus
quelle
heapq.nlargest(3, xrange(len(a)), a.take)
. Für Python-Listen können wir.__getitem__
anstelle von verwenden.take
.A
im Allgemeinen :heapq.nlargest(3, range(len(A.ravel())), A.ravel().take)
. (Ich hoffe, dies funktioniert nur mit Ansichten, siehe auch (ravel vs flatten
] ( stackoverflow.com/a/28930580/603003 )).Wenn Sie zufällig mit einem mehrdimensionalen Array arbeiten, müssen Sie die Indizes reduzieren und entwirren:
Zum Beispiel:
quelle
Wenn Sie sich nicht für die Reihenfolge der K-ten größten Elemente interessieren, die Sie verwenden können
argpartition
, sollte diese besser funktionieren als eine vollständige Sortierungargsort
.Credits gehen an diese Frage .
Ich habe ein paar Tests durchgeführt und es sieht so aus
argpartition
,argsort
als ob es besser abschneidet, wenn die Größe des Arrays und der Wert von K zunehmen.quelle
Bei mehrdimensionalen Arrays können Sie das
axis
Schlüsselwort verwenden, um die Partitionierung entlang der erwarteten Achse anzuwenden.Und für das Ergreifen der Gegenstände:
Beachten Sie jedoch, dass dies kein sortiertes Ergebnis zurückgibt. In diesem Fall können Sie
np.argsort()
entlang der vorgesehenen Achse verwenden:Hier ist ein Beispiel:
quelle
np.take_along_axis
(was wahrscheinlich nicht existierte, als Sie diese Frage beantworteten)Dies ist schneller als eine vollständige Sortierung, abhängig von der Größe Ihres ursprünglichen Arrays und der Größe Ihrer Auswahl:
Es geht natürlich darum, Ihr ursprüngliches Array zu manipulieren. Was Sie (falls erforderlich) beheben können, indem Sie eine Kopie erstellen oder die ursprünglichen Werte ersetzen. ... je nachdem, was für Ihren Anwendungsfall günstiger ist.
quelle
argmax(.)
auch als eindeutig betrachten. (IMHO versucht es, einer Art Kurzschlusslogik zu folgen, liefert aber leider kein allgemein akzeptables Verhalten). DankeDie Methode gibt
np.argpartition
nur die k größten Indizes zurück, führt eine lokale Sortierung durch und ist schneller alsnp.argsort
(vollständige Sortierung), wenn das Array ziemlich groß ist. Die zurückgegebenen Indizes sind jedoch NICHT in aufsteigender / absteigender Reihenfolge . Sagen wir mit einem Beispiel:Wir können sehen, dass wenn Sie eine streng aufsteigende Reihenfolge der Top-k-Indizes
np.argpartition
wünschen , nicht das zurückgegeben wird, was Sie wollen.Abgesehen von der manuellen Sortierung nach np.argpartition besteht meine Lösung darin, PyTorch zu verwenden
torch.topk
, ein Tool für den Aufbau neuronaler Netzwerke, das NumPy-ähnliche APIs sowohl mit CPU- als auch mit GPU-Unterstützung unterstützt. Es ist so schnell wie NumPy mit MKL und bietet einen GPU-Boost, wenn Sie große Matrix- / Vektorberechnungen benötigen.Der strikte Code für aufsteigende / absteigende Top-k-Indizes lautet:
Beachten Sie, dass
torch.topk
ein Brennertensor akzeptiert wird und sowohl Top-k-Werte als auch Top-k-Indizes vom Typ zurückgegeben werdentorch.Tensor
. Ähnlich wie bei np akzeptiert torch.topk auch ein Achsenargument, damit Sie mehrdimensionale Arrays / Tensoren verarbeiten können.quelle
Verwenden:
Jetzt würde die
result
Liste N Tupel (index
,value
) enthalten , wobeivalue
maximiert wird.quelle
Verwenden:
Es funktioniert auch mit 2D-Arrays. Zum Beispiel,
quelle
bottleneck
hat eine partielle Sortierfunktion, wenn der Aufwand für das Sortieren des gesamten Arrays, um die N größten Werte zu erhalten, zu hoch ist.Ich weiß nichts über dieses Modul; Ich habe nur gegoogelt
numpy partial sort
.quelle
Das Folgende ist eine sehr einfache Möglichkeit, die maximalen Elemente und ihre Positionen anzuzeigen. Hier
axis
ist die Domain;axis
= 0 bedeutet spaltenweise maximale Anzahl undaxis
= 1 bedeutet zeilenweise maximale Anzahl für den 2D-Fall. Und für höhere Dimensionen hängt es von Ihnen ab.quelle
Ich fand es am intuitivsten zu bedienen
np.unique
.Die Idee ist, dass die eindeutige Methode die Indizes der Eingabewerte zurückgibt. Aus dem maximalen eindeutigen Wert und den Angaben kann dann die Position der ursprünglichen Werte neu erstellt werden.
quelle
Ich denke, der Weg mit der größten Zeiteffizienz besteht darin, das Array manuell zu durchlaufen und einen Min-Heap in k-Größe beizubehalten, wie andere bereits erwähnt haben.
Und ich habe mir auch einen Brute-Force-Ansatz ausgedacht:
Setzen Sie das größte Element auf einen großen negativen Wert, nachdem Sie argmax verwendet haben, um seinen Index abzurufen. Und dann gibt der nächste Aufruf von argmax das zweitgrößte Element zurück. Sie können den ursprünglichen Wert dieser Elemente protokollieren und bei Bedarf wiederherstellen.
quelle
Dieser Code funktioniert für ein Numpy-Matrix-Array:
Dies erzeugt eine wahr-falsch-n_largest-Matrixindizierung, die auch dazu dient, n_largest-Elemente aus einem Matrixarray zu extrahieren
quelle