2

Das Problem ist sehr einfach, es gibt nur 5 Proben.Warum benötigt eine einfache logistische Regression Millionen von Iterationen, um zu konvergieren?

Aber der Gradient Descent konvergiert extrem langsam, wie einige Millionen von Iterationen.

Warum, gibt es einen Fehler in meinem Algorithmus?

P.S. Der Julia-Code unten:

X = [ 
1.0 34.6237 78.0247; 
1.0 30.2867 43.895; 
1.0 35.8474 72.9022; 
1.0 60.1826 86.3086; 
1.0 79.0327 75.3444 
] 

Y = [0 0 0 1 1]' 

sigmoid(z) = 1/(1 + e^-z) 

# Cost function. 
function costJ(Theta, X, Y) 
    m = length(Y) 
    H = map(z -> sigmoid(z), (Theta' * X')')  
    sum((-Y)'*log(H) - (1-Y)'*log(1 - H))/m 
end 

# Gradient. 
function gradient(Theta, X, Y) 
    m = length(Y) 
    H = map(z -> sigmoid(z), (Theta' * X')')  
    (((X'*H - X'*Y)')/m)' 
end 

# Gradient Descent. 
function gradientDescent(X, Y, Theta, alpha, nIterations)  
    m = length(Y) 
    jHistory = Array(Float64, nIterations) 
    for i = 1:nIterations 
     jHistory[i] = costJ(Theta, X, Y)   
     Theta = Theta - alpha * gradient(Theta, X, Y)   
    end 
    Theta, jHistory 
end 

gradientDescent(X, Y, [0 0 0]', 0.0001, 1000) 
+4

Wie definieren Sie "Konvergenz"? Richtige Klassifizierung aller Proben? Kleine L2 Norm der Steigung? – lejlot

+1

Hmm, das ist eine gute Frage, ich denke, was ich meine - den minimalen Wert der Kostenfunktion nach einer angemessenen Anzahl von Iterationen zu finden :). Es scheint, dass in diesem Fall die angemessene Menge Hunderte oder Tausende, nicht Millionen betragen sollte. –

+2

In Ihrer Gradientenabstieg-Implementierung gibt es keine Pause. Sie sollten die Reduzierung der Kostenfunktion vergleichen, und wenn das klein genug ist, beenden Sie die Schleife und kehren Sie zurück. – niczky12

Antwort

4

Ich denke @ colinefang Kommentar kann die richtige Diagnose sein. Versuchen Sie, jHistory zu plotten - wird es immer kleiner?

Eine andere Sache, die Sie tun können, ist eine simple linesearch bei jeder Iteration hinzufügen, um sicherzustellen, sind die Kosten immer abnimmt, so etwas wie:

function linesearch(g, X, Y, Theta; alpha=1.0) 
    init_cost = costJ(Theta, X, Y) 

    while costJ(Theta - alpha*g, X, Y) > init_cost 
     alpha = alpha/2.0 # or divide by some other constant >1 
    end 

    return alpha 
end 

Dann leicht die Gradientenabfallsaktualisierung Funktion ändern auf jeder Iteration über Alpha suchen:

for i = 1:nIterations 
    g = gradient(Theta, X, Y) 
    alpha = linesearch(g,X,Y,Theta) 
    Theta = Theta - alpha * g 
end 

Es gibt verschiedene Leistungsverbesserungen, die Sie an dem obigen Code vornehmen können. Ich wollte dir nur den Geschmack zeigen.