[PYTHON] Random.choice Gewichtung auch unter numpy v1.6

Numpy mit GAE / py

In der App Engine-Standardumgebung der Google Cloud Platform (GCP) mit Python Es gibt verschiedene Einschränkungen, aber Sie können numpy verwenden: + 1:

Die Version ist jedoch auf 1.6.1 festgelegt: schreien: (Spätestens zum 31. August 2017 ist 1.13.1?)

Daher sind möglicherweise verschiedene Funktionen nicht verfügbar, aber diesmal hatte ich Probleme, weil ich np.random.choice nicht verwenden konnte.

numpy.random.choice

Dies ist eine bequeme Funktion der zufälligen Extraktion, die in Version 1.7 und höher hinzugefügt wurde. numpy.random.choice

Grundfunktion

Grundsätzlich handelt es sich um eine Methode, die ein Array oder eine Array-Länge empfängt und ein Array-Element oder einen Index durch Zufallszahlen-Extraktion zurückgibt. Geben Sie im zweiten Argument (oder in der Größe) die zufällig zu extrahierende Zahl an. Die Größe ist 1, wenn nichts angegeben ist, und der Rückgabewert ist ein Element anstelle eines Arrays.

#Gibt den Index mit der Array-Länge zurück
>>> np.random.choice(5)
3
#Wenn Sie die Größe angeben, wird der Index als Array zurückgegeben
>>> np.random.choice(5, 3)
array([3, 2, 4])

#Geben Sie ein Array an und geben Sie das Element zurück
>>> np.random.choice(['alpha', 'beta', 'gamma'])
'alpha'
#Wenn Sie die Größe angeben, wird das Array-Element abgerufen und zurückgegeben.
>>> np.random.choice(['alpha', 'beta', 'gamma'], 2)
array(['alpha', 'beta'],
      dtype='|S5')

Tatsächlich unterstützen Größe und Arrays auch mehrere Dimensionen. Es scheint mühsam zu sein, dies ebenfalls auf 1.6 zu bringen. ..

Wenn es sich jedoch nur um eine Standardfunktion handelt, kann sie anscheinend unter vollständiger Verwendung von np.random.randint reproduziert werden. Da Randint den Bereich und die Größe des Arrays angeben kann, kann gesagt werden, dass der ausgewählte Teil der Indexauswahl üblich ist.

Optionale Funktion: Doppelte Steuerung

Duplikate sind standardmäßig für zufällig ausgewählte Inhalte mit einer bestimmten Größe zulässig.

#Die Standardeinstellung ist die doppelte Berechtigung, daher können Sie denselben Wert auswählen.
>>> np.random.choice(5, 3)
array([0, 0, 0])
>>> np.random.choice(['alpha', 'beta', 'gamma'], 2)
array(['gamma', 'gamma'],
      dtype='|S5')

# replace=Sie können die Duplizierung mit False verhindern.
>>> np.random.choice(5, 3, replace=False)
array([0, 1, 4])
>>> np.random.choice(['alpha', 'beta', 'gamma'], 2, replace=False)
array(['gamma', 'alpha'],
      dtype='|S5')

Ein Fehler tritt auf, wenn die Größe größer als die ausgewählte Array-Länge ist.

Dieses Mal war ich beunruhigt, weil es den Anschein hatte, dass dieses Duplizierungsverbot nicht umgesetzt wurde, wenn es np.random von 1,6 oder weniger war. Wenn Sie den Randint so schleifen, dass er sich nicht überlappt, dauert es außerdem lange, wenn Sie Pech haben. (Ich kenne die Pseudozufallszahl nicht, also ist das vielleicht nicht der Fall ...)

Dieses Mal werde ich also ein Beispiel für das Zufallsmodul von Python verwenden. random.sample kann ohne Duplizierung und mit Größenangabe aus dem Array extrahiert werden. Ich denke nicht, dass es genau das gleiche ist, weil die Methode zur Erzeugung von Zufallszahlen unterschiedlich sein kann, aber ...

Optionale Funktionen: Gewichtung

Sie kann gewichtet werden, indem ein Array mit dem Namen p und der gleichen Länge wie das Extraktionsziel übergeben wird. p ist eine Abkürzung für Wahrscheinlichkeit, und es scheint, dass die Summe 1 sein sollte. Standardmäßig ist es gleichmäßig verteilt.

#Es kann durch Gewichtung vorgespannt werden.
>>> np.random.choice(5, 3, p=[0.1, 0, 0.3, 0.6, 0])
array([3, 2, 3])
>>> np.random.choice(['alpha', 'beta', 'gamma'], 2, p=[0.1, 0.1, 0.8])
array(['gamma', 'gamma'],
      dtype='|S5')

#Wird in diesem Artikel nicht behandelt, kann aber mit Ersetzen verwendet werden
>>> np.random.choice(5, 3, p=[0.1, 0, 0.3, 0.6, 0], replace=False)
array([2, 3, 0])
>>> np.random.choice(['alpha', 'beta', 'gamma'], 2, p=[0.1, 0.1, 0.8], replace=False)
array(['gamma', 'alpha'],
      dtype='|S5')

Jemand hat diese Gewichtung im Stapelüberlauf abgefragt, also habe ich mir die Antwort auf diesen Thread ausgeliehen.

How do I “randomly” select numbers with a specified bias toward a particular number

Es ist nicht gut verstanden, aber es scheint, dass p in ein kumulatives Array konvertiert wird und gleichmäßig verteilte Zufallszahlen dort platziert werden, um die tatsächlichen Zufallszahlenwerte zu erhalten.

Implementierungsbeispiel

Es ist ein ziemlich beschissener bedingter Zweig, aber ich denke, dass er bei der Implementierung so aussehen wird. Da der Python-Zufall für die Extraktion ohne Duplizierung verwendet wird, kann es zu Leistungseinbußen und Zufallszahlenverzerrungen kommen. Bitte lassen Sie mich wissen, ob es eine bessere Implementierung gibt. (Tatsächlich scheint es sogar in der 1.6-Serie eine beträchtliche API zu geben)

Am besten verwenden Sie numpy 1.7 oder höher.

def numpy_choice(a, size=1, replace=True, p=None):
    # 1.Wenn es 6 ist, gibt es keine Wahl, also reproduzieren Sie es.Ersetzen ermöglicht das Duplizieren.p wird gewichtet
    #Bereich Array wenn Ganzzahl, sonst Array.
    values = np.arange(a) if isinstance(a, int) else np.asarray(a)
    if p:
        # TODO:Sie müssen die Länge von p und die Länge von a überprüfen.
        #Außerdem wird es in Kombination mit "Jetzt ersetzen" nicht unterstützt. ..(Ich brauchte es zufällig nicht)
        choiced = weighted_choice(values, p, size)
    else:
        length = len(values)
        if replace or size > length:
            #Wenn es Duplikate gibt, verwenden Sie Randint
            idx = np.random.randint(0, length, size)
        else:
            #Keine Duplizierung ist Python zufällig.Probe verwenden
            idx = random.sample(np.arange(length), size)
        choiced = values[idx]
    if size == 1 and len(choiced) == 1:
        #Bei Größe 1 wird das Element zurückgegeben
        return choiced[0]
    return choiced


def weighted_choice(values, p, size=1):
    #Gewichtete Wahl.Es bleibt Stapelüberlauf.
    values = np.asarray(values)

    cdf = np.cumsum(np.asarray(p))
    cdf /= cdf[-1]

    uniform_samples = np.random.sample(size)
    idx = cdf.searchsorted(uniform_samples, side='right')
    sample = values[idx]

    return sample

Aufgabe

Recommended Posts

Random.choice Gewichtung auch unter numpy v1.6
Über alles von numpy
Funktion von NumPy einstellen
NumPy-Nullen können auch bei einer Größe von 0 definiert werden