2016-08-28 3 views
1

Übersetzen habe ich versucht, ein Stück Code von Matlab zu Python zu übersetzen und ich laufe in einige Fehler:eine lineare Regression von Matlab zu Python

Matlab:

function [beta] = linear_regression_train(traindata) 
y = traindata(:,1); %output 
ind2 = find(y == 2); 
ind3 = find(y == 3); 
y(ind2) = -1; 
y(ind3) = 1; 
X = traindata(:,2:257); %X matrix,with size of 1389x256 
beta = inv(X'*X)*X'*y; 

Python:

def linear_regression_train(traindata): 
     y = traindata[:,0] # This is the output 
     ind2 = (labels==2).nonzero() 
     ind3 = (labels==3).nonzero() 
     y[ind2] = -1 
     y[ind3] = 1 
     X = traindata[ : , 1:256] 
     X_T = numpy.transpose(X) 
     beta = inv(X_T*X)*X_T*y 
     return beta 

Ich erhalte einen Fehler: Operanden konnten nicht zusammen mit Formen (257,0,1389) (1389,0,257) auf der Linie, wo Beta berechnet wird, gesendet werden.

Jede Hilfe ist willkommen!

Danke!

+1

Bitte senden Sie den Fehler, den Sie erhalten. –

+0

@DineshPundkar Fehler hinzugefügt – Gary

Antwort

2

Das Problem ist, dass Sie mit numpy Arrays, nicht Matrizen wie in MATLAB arbeiten. Matrizen führen standardmäßig mathematische Matrixoperationen durch. Also X*Y tut eine Matrix-Multiplikation von X und Y. Bei Arrays werden jedoch standardmäßig Element-für-Element-Operationen verwendet. So multipliziert X*Y jedes entsprechende Element von X und Y. Dies entspricht dem .* von MATLAB.

Aber genauso wie die MATLAB-Matrizen Element-für-Element-Operationen ausführen können, können Numpys Matrizen eine Matrixmultiplikation durchführen. Was Sie also tun müssen, ist die Matrixmultiplikation von numpy anstelle der elementweisen Multiplikation. Für Python 3.5 oder höher (das ist die Version, die Sie für diese Art von Arbeit verwenden sollten), das ist nur der Operator @. So Ihre Linie wird:

beta = inv(X_T @ X) @ X_T @ y 

Oder, noch besser, können Sie die einfachere .T transponieren verwenden, die die gleiche wie np.transpose ist aber viel prägnanter (Sie der `np.transpose Linie befreien vollständig erhalten kann):

beta = inv(X.T @ X) @ X.T @ y 

für Python 3.4 oder früher, müssen Sie np.dot da diese Versionen von Python haben nicht den Operator @ Matrixmultiplikation verwenden:

beta = np.dot(np.dot(inv(np.dot(X.T, X)), X.T), y) 

Numpy hat ein Matrixobjekt, das standardmäßig Matrixoperationen wie die MATLAB-Matrix verwendet. Nicht benutzen! Es ist langsam, schlecht unterstützt und fast nie, was Sie wirklich wollen. Die Python-Community hat sich um Arrays herum standardisiert, also benutze diese.

Es kann auch einige Probleme mit den Abmessungen von traindata geben. Damit dies ordnungsgemäß funktioniert, sollte gleich 3 sein. Damit y und X 2D sind, sollte traindata3D sein.

Dies könnte ein Problem sein, wenn traindata 2D ist und Sie möchten, dass y MATLAB-Stil "Vektor" (was MATLAB nennt "Vektoren" sind nicht wirklich Vektoren). In Numpy reduziert die Verwendung eines einzelnen Index wie traindata[:, 0] die Anzahl der Dimensionen, während ein Slice wie traindata[:, :1] dies nicht tut. Um also y 2D zu behalten, wenn traindata 2D ist, mach einfach einen length-1 slice, traindata[:, :1]. Dies sind genau die gleichen Werte, aber dies hält die gleiche Anzahl von Dimensionen wie traindata.

Hinweise: Ihr Code wesentlich vereinfacht logische Indizierung werden können:

def linear_regression_train(traindata): 
    y = traindata[:, 0] # This is the output 
    y[labels == 2] = -1 
    y[labels == 3] = 1 
    X = traindata[:, 1:257] 
    return inv(X.T @ X) @ X.T @ y 
    return beta 

Auch Ihre Scheibe falsch ist, wenn X definieren. Python-Slicing schließt den letzten Wert aus. Um also eine 256 lange Slice zu erhalten, müssen Sie 1:257 ausführen, wie ich oben getan habe.

Schließlich, bitte beachten Sie, dass Änderungen an Arrays in Funktionen außerhalb der Funktionen übertragen, und Indexierung keine Kopie macht. Ihre Änderungen an y (setzen Sie einige Werte auf 1 und andere auf -1), beeinflussen traindata außerhalb Ihrer Funktion. Wenn Sie dies vermeiden möchten, müssen Sie eine Kopie erstellen, bevor Sie Ihre Änderungen vornehmen:

y = traindata[:, 0].copy()