2012-07-30 12 views
5

Próbuję napisać funkcję odwzorowującą 2d-ndarray na 2d-ndarray. Wiersze tablicy wejściowej mogą być przetwarzane niezależnie i powinna istnieć zgodność 1 do 1 między wierszami wejściowymi i wierszami wyjścia. Dla każdego rzędu danych wejściowych należy obliczyć wielomianowy rozkład danej rzędności dla danego wiersza (patrz przykład: docstring). Bieżąca implementacja działa; jednak wymaga to jawnej pętli nad wierszami i duplikowania wierszy w "powerMatrix"). Czy możliwe jest uzyskanie tego samego wyniku za pomocą pojedynczego połączenia z numpy.power? Btw .: kolejność wpisów w wierszach wyników nie ma dla mnie znaczenia.2d numpy.power dla wielomianowej rozbudowy

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

Dzięki Jan

EDIT: Funkcja brakującym kartezjański zdefiniowana jest tutaj: Using numpy to build an array of all combinations of two arrays

Odpowiedz

3

Podstawowym założeniem jest to, aby przesunąć wymiar (w przypadku, wymiar 0, liczba rzędów) nie ma znaczenia dla obliczeń "na uboczu" w wyższy wymiar, a następnie automatycznie nad nim transmitowane.

Nie jestem pewien, co metoda cartesian robi, ale tutaj jest to rozwiązanie, które wykorzystuje do generowania krotki np.indices indeksowania ponad matrycy X:

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. [Usunąłem swój głupi komentarz - przekazałem '[1,2,3]' do twojej funkcji zamiast '[[1,2,3]]', co oczywiście dało równie głupie wyniki.] – DSM

+0

Dzięki dużo, które wykonało zadanie :-) – frisbee

+0

To naprawdę eleganckie rozwiązanie! Chciałbym go użyć w małym projekcie, nad którym pracuję, jeśli nie masz nic przeciwko: https://github.com/dreamwalkerrr/mledu. (przydzieli ci ten algorytm do linku do tej odpowiedzi, jeśli to jest w porządku?). Czy mógłbyś mi również powiedzieć, jaki byłby najlepszy sposób na wykluczenie haseł podniesionych do potęgi 0? – dreamwalker

Powiązane problemy