Menteşe kaybının gradyanı


25

Temel degrade inişini uygulamaya çalışıyorum ve bunu bir menteşe kaybı fonksiyonu ile test ediyorum, yani lhinge=max(0,1y xw) . Ancak, menteşe kaybının derecesi hakkında kafam karıştı. Olduğu izlenimi altındayım

wlhinge={y xif y xw<10if y xw1

Fakat bu, \ boldsymbol {x} ile aynı boyutta bir matris döndürmüyor xmu? Bir uzunluk vektör döndürmek istediğimizi sanıyordum w ? Açıkçası, bir yerlerde kafam karıştı. Birisi burada doğru yöne işaret edebilir mi?

Görev tanımının net olmadığı durumda bazı temel kodları ekledim.

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

Güncelleme: Aşağıdaki cevap sorunu anlamada yardımcı olurken, bu algoritmanın çıktısı verilen veriler için hala yanlış. Kayıp fonksiyonu her seferinde 0.25 azalır, ancak çok hızlı bir şekilde birleşir ve sonuçta ortaya çıkan ağırlıklar iyi bir sınıflandırma ile sonuçlanmaz. Şu anda çıktı gibi görünüyor

#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"
...  

Degrade, kayıp işleviniz gerçek değerlere sahip olduğundan bir vektördür.
Wok

3
işleviniz her yerde ayırt edilemez.
Robin Girard

2
Robin'in belirttiği gibi, menteşe kaybı x = 1'de ayırt edilemez. Bu sadece alt gradyan iniş algoritması kullanmanız gerektiği anlamına geliyor
Alex Kreimer

Yanıtlar:


27

Biz göre kaybı ayırt gradyanı elde etmek inci bileşeni .ağırlıkiw

Açısından menteşe kaybı yeniden yazma olarak burada vef ( g ( w ) ) f ( z ) = maks ( 0 , 1 - y z ) g ( w ) = xwwf(g(w))f(z)=max(0,1y z)g(w)=xw

Zincir kuralı kullanarak

wif(g(w))=fzgwi

İlk türev terimi değerlendirilir haline zaman , 0 olduğunda . İkinci türev terimi olur . Sonunda - y xw < 1 xw > 1 x i f ( g ( w ) )g(w)=xwyxw<1xw>1xi

f(g(w))wi={y xiif y xw<10if y xw>1

Yana bileşenleri üzerinde aralıkları , bir vektör miktar olarak yukarıda görüntüleyebilir ve yazma için kısaltma olarakx ix (w(w1,w2,)


Teşekkürler! Bu benim için her şeyi temizler. Şimdi sadece pratik bir ortamda doğru almalıyım. Yukarıdaki kodun neden çalışmadığı hakkında hiçbir fikriniz olmaz mı? 4 yinelemede, 1'de başlayan ve her defasında 0,25'e düşen ve 0'da yaklaşan kayıp ile birleştiği görülmektedir. Ancak, ürettiği ağırlıklar oldukça yanlış görünmektedir.
brcs

1
Egzersiz verilerinize hangi tahminleri verdiğini kontrol edebilirsiniz. Eğer kayıp sıfıra düşerse, tüm örnekler mükemmel bir şekilde sınıflandırılmalıdır
Yaroslav Bulatov

İkili sınıflandırma için durum budur. Menteşe kaybı kullanarak çoklu sınıflandırma gradyanı için türetme yapabilir misiniz?
Shyamkkhadka

12

Bu 3 yıl gecikti, ama yine de biriyle alakalı olabilir ...

Let noktaları bir örnek göstermek ve karşılık gelen etiket grubu . Toplam menteşe kaybını en aza indirecek bir düzlemi bulmak için arama yapıyoruz : bulmak için toplam menteşe kaybının türevini alın. Her bileşenin : x iR d y i{ - 1 , 1 } ağırlık ağırlık * = argmin  ağırlık L h i n g E S ( W ) = argmin  ağırlık Σ i l h ı n g E ( w , x i , y ı ) = argmin  w i max { 0 ,SxiRdyi{1,1}ww * l h ı n gr e

w=argmin wLShinge(w)=argmin wilhinge(w,xi,yi)=argmin wimax{0,1yiwx}
w
lhingew={0yiwx1yixyiwx<1

Toplamın gradyanı, gradyanların toplamıdır. Python örneği, bulmak için GD’yi kullanır menteşe kaybı en uygun ayrıştırma hiper uçağı aşağıdaki gibidir (muhtemelen en verimli kod değildir, ancak çalışır)

LShingew=ilhingew
import numpy as np
import matplotlib.pyplot as plt

def hinge_loss(w,x,y):
    """ evaluates hinge loss and its gradient at w

    rows of x are data points
    y is a vector of labels
    """
    loss,grad = 0,0
    for (x_,y_) in zip(x,y):
        v = y_*np.dot(w,x_)
        loss += max(0,1-v)
        grad += 0 if v > 1 else -y_*x_
    return (loss,grad)

def grad_descent(x,y,w,step,thresh=0.001):
    grad = np.inf
    ws = np.zeros((2,0))
    ws = np.hstack((ws,w.reshape(2,1)))
    step_num = 1
    delta = np.inf
    loss0 = np.inf
    while np.abs(delta)>thresh:
        loss,grad = hinge_loss(w,x,y)
        delta = loss0-loss
        loss0 = loss
        grad_dir = grad/np.linalg.norm(grad)
        w = w-step*grad_dir/step_num
        ws = np.hstack((ws,w.reshape((2,1))))
        step_num += 1
    return np.sum(ws,1)/np.size(ws,1)

def test1():
    # sample data points
    x1 = np.array((0,1,3,4,1))
    x2 = np.array((1,2,0,1,1))
    x  = np.vstack((x1,x2)).T
    # sample labels
    y = np.array((1,1,-1,-1,-1))
    w = grad_descent(x,y,np.array((0,0)),0.1)
    loss, grad = hinge_loss(w,x,y)
    plot_test(x,y,w)

def plot_test(x,y,w):
    plt.figure()
    x1, x2 = x[:,0], x[:,1]
    x1_min, x1_max = np.min(x1)*.7, np.max(x1)*1.3
    x2_min, x2_max = np.min(x2)*.7, np.max(x2)*1.3
    gridpoints = 2000
    x1s = np.linspace(x1_min, x1_max, gridpoints)
    x2s = np.linspace(x2_min, x2_max, gridpoints)
    gridx1, gridx2 = np.meshgrid(x1s,x2s)
    grid_pts = np.c_[gridx1.ravel(), gridx2.ravel()]
    predictions = np.array([np.sign(np.dot(w,x_)) for x_ in grid_pts]).reshape((gridpoints,gridpoints))
    plt.contourf(gridx1, gridx2, predictions, cmap=plt.cm.Paired)
    plt.scatter(x[:, 0], x[:, 1], c=y, cmap=plt.cm.Paired)
    plt.title('total hinge loss: %g' % hinge_loss(w,x,y)[0])
    plt.show()

if __name__ == '__main__':
    np.set_printoptions(precision=3)
    test1()

Ben ikili sınıflandırma için durum budur. Menteşe kaybı kullanarak çoklu sınıflandırma gradyanı için türetme yapabilir misiniz?
Shyamkkhadka

1

Kodunu düzelttim. Asıl sorun menteşe ve d_hinge fonksiyon tanımınızdır. Bunlar bir seferde bir örnek uygulanmalıdır. Bunun yerine tanımınız, maksimum almadan önce tüm örnekleri toplar.

#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<-t(t(c(1,1,-1,-1)))
    w<-matrix(0, nrow=ncol(x))


    print(sprintf("loss: %f,x.w: %s",sum(mapply(function(xr,yr) fw(w,xr,yr), split(x,row(x)),split(y,row(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(mapply(function(xr,yr) fw(w,xr,yr), split(x,row(x)),split(y,row(y)))),paste(x%*%w,collapse=',')))
    }
}

#Hinge loss
hinge<-function(w,xr,yr) max(1-yr*xr%*%w, 0)
d_hinge<-function(w,x,y){ dw<- apply(mapply(function(xr,yr) -yr * xr * (yr * xr %*% w < 1),split(x,row(x)),split(y,row(y))),1,sum); dw}
gradient_descent(hinge, d_hinge, 100, lr=0.01)

Birleşmek için n = 10000 lazım

[1] "kaybı: 0.090000, xw: 1.0899999999999995,0.909999999999905, -1.19000000000008, -1.69000000000011" [1] "kaybı: 0.100000, xw: 1.0099009999, 1.19999999, -000000999999999999999999; 0,9399999999999999948,0,829999999999905, 09900990099009900; [1] "zarar: 0.240000, xw: 1.4999999999999995,1.2099999999999, -0.760000000000075, -1.3300000000000011" [1] "zarar: 0.080000, xw: 1.099999999999999999999995, -1. 1.34999999999995,1.1299999999999, -,890000000000075, -1,41000000000011"[1] "zarar: 0.210000, xw: 0.94999999999999948,0.839999999999905, -1.31000000000007, -1.7600000000000011" [1] "zarar: 0.380000, xw: 1.6599999999, 99999999, -0.6200000000000000000000000000000000000000000000000000000000000000000000000000. 1.25999999999995,1.0099999999999, -1.04000000000008, -1.59000000000011 "[1]" zarar: 0.000000, xw: 1.25999999999995,1.0099999999999, -1.04000000000008, -1.59000000000011 "


3
Halklar, gradyan iniş var sadece WORST optimizasyon algoritması ile ilgili ve sadece bir seçenek olmadığı zaman kullanılmalıdır. Bir güven bölgesi veya çizgi araması Quasi-Newton algoritması, nesnel işlev değeri ve gradyanı kullanarak, sudan gradyan inişini üfler ve çok daha güvenilir bir şekilde birleşir. Ve ne yaptığınızı, çok az kişinin yaptığı şeyi bilmediğiniz sürece kendi çözümleyicinizi yazmayın.
Mark L. Stone,

2
Her iki ifadeye de katılıyorum. Bununla birlikte, çeşitli lezzetlere sahip gradyan inişlerinin, en azından oradaki açık kaynak kütüphanelerine göre, dağınık bir ortamda uygulanması çok kolaydır.
John Jiang,
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.