Gradient mất bản lề


25

Tôi đang cố gắng thực hiện giảm độ dốc cơ bản và tôi đang thử nghiệm nó với chức năng mất bản lề, ví dụ: . Tuy nhiên, tôi bối rối về độ dốc của bản lề. Tôi có ấn tượng rằng nó làlhinge=max(0,1y xw)

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

Nhưng điều này không trả về một ma trận có cùng kích thước với x ? Tôi nghĩ rằng chúng tôi đang tìm cách trả về một vectơ có độ dài w ? Rõ ràng, tôi đã có một cái gì đó nhầm lẫn ở đâu đó. Ai đó có thể chỉ đúng hướng ở đây?

Tôi đã bao gồm một số mã cơ bản trong trường hợp mô tả nhiệm vụ của tôi không rõ ràng

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

Cập nhật: Mặc dù câu trả lời dưới đây đã giúp tôi hiểu vấn đề, đầu ra của thuật toán này vẫn không chính xác cho dữ liệu đã cho. Hàm mất mát giảm 0,25 mỗi lần nhưng hội tụ quá nhanh và trọng số kết quả không dẫn đến phân loại tốt. Hiện tại đầu ra trông như

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

Độ dốc là một vectơ vì hàm mất của bạn có giá trị thực.
Chảo

3
chức năng của bạn không phải là khác biệt ở mọi nơi.
cướp girard

2
Vì robin lưu ý mất bản lề không khác biệt ở x = 1. Điều này chỉ có nghĩa là bạn cần sử dụng thuật toán giảm độ dốc phụ
Alex Kreimer

Câu trả lời:


27

Để có được độ dốc, chúng tôi phân biệt sự mất mát đối với thành phần thứ của .wtôiw

Viết lại mất bản lề theo là trong đó vàf ( g ( w ) ) f ( z ) = tối đa ( 0 , 1 - y z ) g ( w ) = xwwf(g(w))f(z)=max(0,1y z)g(w)=xw

Sử dụng quy tắc chuỗi chúng tôi nhận được

wif(g(w))=fzgwi

Thuật ngữ phái sinh đầu tiên được đánh giá tại trở thành khi và 0 khi . Thuật ngữ phái sinh thứ hai trở thành . Vì vậy, cuối cùng bạn nhận được g(w)=xwyxw<1xw>1xi

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

Vì nằm trên các thành phần của , nên bạn có thể xem phần trên dưới dạng đại lượng vectơ và viết làm tốc ký choixw(w1,w2,)


Cảm ơn! Điều đó làm sạch mọi thứ cho tôi. Bây giờ tôi chỉ cần làm cho nó đúng trong một thiết lập thực tế. Bạn sẽ không biết tại sao đoạn mã trên không hoạt động? Nó dường như hội tụ trong 4 lần lặp với tổn thất bắt đầu từ 1 và giảm 0,25 mỗi lần và hội tụ ở mức 0. Tuy nhiên, các trọng số mà nó tạo ra có vẻ khá sai.
brcs

1
Bạn có thể kiểm tra những dự đoán nó mang lại cho dữ liệu đào tạo của bạn. Nếu tổn thất giảm xuống 0, tất cả các trường hợp nên được phân loại hoàn hảo
Yaroslav Bulatov

Đây là trường hợp để phân loại nhị phân. Bạn có thể vui lòng đưa ra đạo hàm cho độ dốc của phân loại nhiều lớp bằng cách sử dụng mất bản lề?
Shyamkkhadka

12

Điều này trễ 3 năm, nhưng vẫn có thể phù hợp với ai đó ...

SxiRdyi{1,1}w

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

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

Tôi đây là trường hợp để phân loại nhị phân. Bạn có thể vui lòng đưa ra đạo hàm cho độ dốc của phân loại nhiều lớp bằng cách sử dụng mất bản lề?
Shyamkkhadka

1

Tôi đã sửa mã của bạn. Vấn đề chính là định nghĩa của bạn về các chức năng bản lề và d_ Breathe. Chúng nên được áp dụng một mẫu tại một thời điểm. Thay vào đó, định nghĩa của bạn tổng hợp tất cả các mẫu trước khi lấy tối đa.

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

Tôi cần n = 10000 để hội tụ.

[1] "mất: 0,090000, xw: 1,08999999999995,0,909999999999,95, -1,100000000000008, 1 [[1] 1.34999999999995,1.1299999999999, -0.890000000000075, -1.41000000000011 "[1] "mất: 0,210000, xw: 0,94999999999948,0,839999999999,95, -1,31000000000007," 1.25999999999995,1.0099999999999, -1.04000000000008, -1.59000000000011 "[1]" mất: 0,00000000, xw: 1.25999999999995,1.0099999999999, -1.04000000000008, -1.59000000000011 "


3
Mọi người, độ dốc gốc chỉ là về thuật toán tối ưu hóa WORST có, và chỉ nên được sử dụng khi không có lựa chọn nào khác. Một thuật toán Quasi-Newton tìm kiếm vùng tin cậy, sử dụng giá trị hàm mục tiêu và độ dốc, sẽ thổi độ dốc xuống khỏi mặt nước và hội tụ đáng tin cậy hơn nhiều. Và đừng viết người giải quyết của riêng bạn trừ khi bạn biết bạn đang làm gì, điều mà rất ít người làm.
Mark L. Stone

2
Tôi đồng ý với cả hai tuyên bố. Tuy nhiên, việc giảm độ dốc với các hương vị khác nhau dễ thực hiện hơn trong môi trường phân tán, ít nhất là theo các thư viện nguồn mở có sẵn ngoài kia.
John Jiang
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.