2012-07-30 11 views
5

Ich versuche eine Funktion zu schreiben, die 2d-ndarray auf 2d-ndarray abbildet. Die Zeilen des Eingabe-Arrays können unabhängig verarbeitet werden und es muss eine 1: 1-Übereinstimmung zwischen den Zeilen der Eingabe und den Zeilen der Ausgabe bestehen. Für jede Zeile der Eingabe wird die Polynomausdehnung einer gegebenen Reihenfolge für die Zeile berechnet (siehe Beispiel für einen Docstring). Die aktuelle Implementierung funktioniert; es erfordert jedoch eine explizite Schleife über die Zeilen und eine Duplizierung von Zeilen in der "powerMatrix". Ist es möglich, mit einem einzigen Aufruf von numpy.power dasselbe Ergebnis zu erhalten? Btw .: die Reihenfolge der Einträge in den Ergebniszeilen ist mir egal.2d numpy.power für Polynom-Erweiterung

import numpy 
def polynomialFeatures(x, order): 
    """ Generate polynomial features of given order for data x. 

    For each row of ndarray x, the polynomial expansions are computed, i.e 
    for row [x1, x2] and order 2, the following row of the result matrix is 
    computed: [1, x1, x1**2, x2, x1*x2, x1**2*x2, x2**2, x1*x2**2, x1**2*x2**2] 

    Parameters 
    ---------- 
    x : array-like 
     2-D array; for each of its rows, the polynomial features are created 

    order : int 
     The order of the polynomial features 

    Returns 
    ------- 
    out : ndarray 
     2-D array of shape (x.shape[0], (order+1)**x.shape[1]) containing the 
     polynomial features computed for the rows of the array x 

    Examples 
    -------- 
    >>> polynomialFeatures([[1, 2, 3], [-1, -2, -3]], 2) 
    array([[ 1 3 9 2 6 18 4 12 36 1 3 9 2 6 18 4 12 
      36 1 3 9 2 6 18 4 12 36] 
      [ 1 -3 9 -2 6 -18 4 -12 36 -1 3 -9 2 -6 18 -4 12 
      -36 1 -3 9 -2 6 -18 4 -12 36]]) 
    """ 
    x = numpy.asarray(x) 
    # TODO: Avoid duplication of rows 
    powerMatrix = numpy.array([range(order+1)] * x.shape[1]).T 
    # TODO: Avoid explicit loop, and use numpy's broadcasting 
    F = [] 
    for i in range(x.shape[0]): 
     X = numpy.power(x[i], powerMatrix).T 
     F.append(numpy.multiply.reduce(cartesian(X), axis=1)) 

    return numpy.array(F) 

print numpy.all(polynomialFeatures([[1, 2, 3], [-1, -2, -3]], 2) == 
       numpy.array([[1, 3, 9, 2, 6, 18, 4, 12, 36, 1, 
           3, 9, 2, 6, 18, 4, 12, 36, 1, 3, 
           9, 2, 6, 18, 4, 12, 36], 
          [1, -3, 9, -2, 6, -18, 4, -12, 36, -1, 
           3, -9, 2, -6, 18, -4, 12, -36, 1, -3, 
           9, -2, 6, -18, 4, -12, 36]])) 

Danke, Jan

EDIT: Die fehlende Funktion kartesisch hier definiert ist: Using numpy to build an array of all combinations of two arrays

Antwort

3

Die Grundidee ist es, die Dimension zu bewegen (in Ihrem Fall, Dimension 0, die Anzahl der Zeilen) das ist für die Berechnung "aus dem Weg" in eine höhere Dimension irrelevant und wird dann automatisch darüber ausgestrahlt.

Ich bin nicht sicher, was Ihre cartesian Methode tut, aber hier ist eine Lösung, die np.indices Indizierung Tupeln über die X Matrix zu erzeugen, verwendet:

import numpy as np 
def polynomial_features(x, order): 
    x = np.asarray(x).T[np.newaxis] 
    n = x.shape[1] 
    power_matrix = np.tile(np.arange(order + 1), (n, 1)).T[..., np.newaxis] 
    X = np.power(x, power_matrix) 
    I = np.indices((order + 1,) * n).reshape((n, (order + 1) ** n)).T 
    F = np.product(np.diagonal(X[I], 0, 1, 2), axis=2) 
    return F.T 
+0

+1. [Eine dumme Bemerkung von mir gelöscht - ich hatte "[1,2,3]" an deine Funktion anstatt an [[1,2,3]] 'weitergegeben, was natürlich ebenso dumme Ergebnisse lieferte.] – DSM

+0

Danke a Viel, das hat's geklappt :-) – frisbee

+0

Das ist eine wirklich elegante Lösung! Ich möchte es in einem kleinen Projekt verwenden, an dem ich arbeite, wenn es Ihnen nichts ausmacht: https://github.com/dreamwalkerrr/mledu. (Wird dieser Algorithmus Ihnen zugeordnet, wenn Sie mit dieser Antwort verknüpfen, wenn das in Ordnung ist?). Kannst du mir bitte auch mitteilen, wie man die auf die 0-te Potenz gesteigerten Begriffe am besten ausschließt? – dreamwalker