Estoy tratando de implementar un descenso de gradiente básico y lo estoy probando con una función de pérdida de bisagra, es decir, . Sin embargo, estoy confundido sobre el gradiente de la pérdida de la bisagra. Tengo la impresión de que es
Pero, ¿no devuelve esto una matriz del mismo tamaño que ? Pensé que estábamos buscando devolver un vector de longitud ? Claramente, tengo algo confundido en alguna parte. ¿Alguien puede apuntar en la dirección correcta aquí?
He incluido un código básico en caso de que mi descripción de la tarea no estuviera clara
#Run standard gradient descent
gradient_descent<-function(fw, dfw, n, lr=0.01)
{
#Date to be used
x<-t(matrix(c(1,3,6,1,4,2,1,5,4,1,6,1), nrow=3))
y<-c(1,1,-1,-1)
w<-matrix(0, nrow=ncol(x))
print(sprintf("loss: %f,x.w: %s",sum(fw(w,x,y)),paste(x%*%w, collapse=',')))
#update the weights 'n' times
for (i in 1:n)
{
w<-w-lr*dfw(w,x,y)
print(sprintf("loss: %f,x.w: %s",sum(fw(w,x,y)),paste(x%*%w,collapse=',')))
}
}
#Hinge loss
hinge<-function(w,x,y) max(1-y%*%x%*%w, 0)
d_hinge<-function(w,x,y){ dw<-t(-y%*%x); dw[y%*%x%*%w>=1]<-0; dw}
gradient_descent(hinge, d_hinge, 100, lr=0.01)
Actualización: Si bien la respuesta a continuación me ayudó a comprender el problema, la salida de este algoritmo sigue siendo incorrecta para los datos dados. La función de pérdida se reduce en 0.25 cada vez, pero converge demasiado rápido y los pesos resultantes no resultan en una buena clasificación. Actualmente la salida se ve así
#y=1,1,-1,-1
"loss: 1.000000, x.w: 0,0,0,0"
"loss: 0.750000, x.w: 0.06,-0.1,-0.08,-0.21"
"loss: 0.500000, x.w: 0.12,-0.2,-0.16,-0.42"
"loss: 0.250000, x.w: 0.18,-0.3,-0.24,-0.63"
"loss: 0.000000, x.w: 0.24,-0.4,-0.32,-0.84"
"loss: 0.000000, x.w: 0.24,-0.4,-0.32,-0.84"
"loss: 0.000000, x.w: 0.24,-0.4,-0.32,-0.84"
...
fuente
Respuestas:
Para obtener el gradiente, diferenciamos la pérdida con respecto al componente de .wyo w
Reescribe la pérdida de la bisagra en términos de como donde yf ( g ( w ) ) f ( z ) = max ( 0 , 1 - y z ) g ( w ) = x ⋅ ww F( g( w ) ) F( z) = max ( 0 , 1 - y z) sol( w ) = x ⋅ w
Usando la regla de la cadena obtenemos
El primer término derivado se evalúa en convirtiéndose en cuando , y 0 cuando . El segundo término derivado se convierte en . Entonces, al final obtienes - y x ⋅ w < 1 x ⋅ w > 1 x i ∂ f ( g ( w ) )sol( w ) = x ⋅ w - y x ⋅w<1 x⋅w>1 xi
Como extiende sobre los componentes de , puede ver lo anterior como una cantidad vectorial y escribir como abreviatura dex ∂i x (∂∂∂w (∂∂w1,∂∂w2,…)
fuente
Esto lleva 3 años de retraso, pero aún puede ser relevante para alguien ...
Supongamos que denota una muestra de puntos y el conjunto de etiquetas correspondientes . Buscamos encontrar un hiperplano que minimice la pérdida total de la bisagra: Para encontrar tome la derivada de la pérdida total de la bisagra. El gradiente de cada componente es: x i ∈ R d y i ∈ { - 1 , 1 } w w ∗ = argmin w L h i n g e S ( w ) = argmin w ∑ i l h i n g e ( w , x i , y i ) = argmin w ∑ i max { 0 ,S xi∈Rd yi∈{−1,1} w w ∗ ∂ l h i n g e
El gradiente de la suma es una suma de gradientes. Ejemplo de Python, que usa GD para encontrar sigue el hiperplano de separación óptimo de pérdida de bisagra (probablemente no sea el código más eficiente, pero funciona)
fuente
Arregle tu código. El principal problema es su definición de funciones de bisagra y d_hinge. Estos deben aplicarse una muestra a la vez. En cambio, su definición agrega todas las muestras antes de tomar el máximo.
Necesito n = 10000 para converger.
[1] "pérdida: 0.090000, xw: 1.08999999999995,0.909999999999905, -1,19000000000008, -1,69000000000011" [1] "pérdida: 0.100000, xw: 1.33999999999995,1.1199999999999, -0,900000000000075, -1,42000000000011" [1] "pérdida: 0.230000, xw: .109. [1] "pérdida: 0.240000, xw: 1.49999999999995,1.2099999999999, -0.760000000000075, -1.33000000000011" [1] "pérdida: 0.080000, xw: 1.09999999999995,0.919999999999905, -1.18000000000007, -1.6800", 1: 800 ", 1: 800" 1.34999999999995,1.1299999999999, -0.890000000000075, -1.41000000000011 "[1] "pérdida: 0.210000, xw: 0.949999999999948,0.839999999999905, -1,31000000000007, -1,76000000000011" [1] "pérdida: 0.380000, xw: 1.65999999999995,1.2999999999999, -0,620000000000074, -1,24000000000011" [1] "pérdida: 0.000000, xw: 1.25999999999995,1.0099999999999, -1.04000000000008, -1.59000000000011 "[1]" pérdida: 0.000000, xw: 1.25999999999995,1.0099999999999, -1.04000000000008, -1.59000000000011 "
fuente