2016-05-15 10 views
3

Ich versuche, die folgenden auf Numpy zu tun, ohne eine Schleife:Vectorize eine Operation in Numpy

  • Ich habe eine Matrix X der Dimension N * d und einen Vektor y der Dimension N. y ganze Zahlen enthält von 1 bis K.
  • Ich versuche, eine Matrix M der Größe K * d zu erhalten, wobei M [i,:] = np.mean (X [y == i,:], 0)

Kann ich dies ohne eine Schleife erreichen?

Mit einer Schleife würde es so etwas gehen.

import numpy as np 

N=3 
d=3 
K=2 

X=np.eye(N) 
y=np.random.randint(1,K+1,N) 
M=np.zeros((K,d)) 
for i in np.arange(0,K): 
    line=X[y==i+1,:] 
    if line.size==0: 
     M[i,:]=np.zeros(d) 
    else: 
     M[i,:]=mp.mean(line,0) 

Vielen Dank im Voraus.

+0

Ist K == N? Sind die Werte von y einzigartig? –

+1

Es wäre cool, wenn Sie Code zeigen würden. – Bonifacio2

+0

Nein und nein. Wenn zum Beispiel K = 2, X = np.eye (3), Y = [1 2 1], möchte ich, dass M gleich [[1/2 0 1/2], [0 1 0]] ist. – popuban

Antwort

3

Dies löst die Frage, aber erstellt eine intermediäre K × N-Boolesche Matrix und verwendet nicht die integrierte Mittelwertfunktion. Dies kann in einigen Fällen zu schlechterer Leistung oder schlechterer numerischer Stabilität führen. Ich lasse die Klassenaufkleber von 0 bis K-1 anstelle von 1 bis K reichen.

# Define constants 
K,N,d = 10,1000,3 

# Sample data 
Y = randint(0,K-1,N) #K-1 to omit one class to test no-examples case 
X = randn(N,d) 

# Calculate means for each class, vectorized 

# Map samples to labels by taking a logical "outer product" 
mark = Y[None,:]==arange(0,K)[:,None] 

# Count number of examples in each class  
count = sum(mark,1) 

# Avoid divide by zero if no examples 
count += count==0 

# Sum within each class and normalize 
M = (dot(mark,X).T/count).T 

print(M, shape(M), shape(mark)) 
3

Der Code ist das Sammeln grundsätzlich bestimmte Zeilen aus X und das Hinzufügen von ihnen, für die wir ein NumPy gebautet in np.add.reduceat haben. Also, mit diesem im Fokus, könnten die Schritte, um es in einer vektorisierten Art und Weise zu lösen, als nächstes -

# Get sort indices of y 
sidx = y.argsort() 

# Collect rows off X based on their IDs so that they come in consecutive order 
Xr = X[np.arange(N)[sidx]] 

# Get unique row IDs, start positions of each unique ID 
# and their counts to be used for average calculations 
unq,startidx,counts = np.unique((y-1)[sidx],return_index=True,return_counts=True) 

# Add rows off Xr based on the slices signified by the start positions 
vals = np.true_divide(np.add.reduceat(Xr,startidx,axis=0),counts[:,None]) 

# Setup output array and set row summed values into it at unique IDs row positions 
out = np.zeros((K,d)) 
out[unq] = vals 
sein
Verwandte Themen