ヒンジ損失の勾配


25

基本的な勾配降下を実装しようとしていますが、ヒンジ損失関数、つまり。ただし、ヒンジ損失の勾配については混乱しています。私はそれがあるという印象を受けていますlhinge=max(0,1y xw)

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

しかし、これは\ boldsymbol {x}と同じサイズの行列を返しませんxか?長さ\ boldsymbol {w}のベクトルを返そうとしていると思いましたwか?明らかに、どこかで混乱しているものがあります。ここで誰かが正しい方向を指すことができますか?

タスクの説明が明確でない場合に備えて、いくつかの基本的なコードを含めました

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

更新:以下の回答は問題の理解に役立ちましたが、このアルゴリズムの出力は特定のデータに対してまだ正しくありません。損失関数は毎回0.25ずつ減少しますが、収束が速すぎて、結果の重みが適切な分類になりません。現在、出力は次のようになります

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

損失関数には実数値があるため、勾配はベクトルです。

3
あなたの機能はどこでも微分可能ではありません。
ロビンギラード

2
ロビンが指摘しているように、ヒンジ損失はx = 1で微分できません。これは、サブ勾配降下アルゴリズムを使用する必要があることを意味します
Alex Kreimer

回答:


27

勾配を得るには、番目の成分に関して損失を区別します。iw

に関するヒンジ損失をとして書き換えます。ここで、およびwf(g(w))f(z)=max(0,1y z)g(w)=xw

チェーンルールを使用して取得する

wif(g(w))=fzgwi

一次導関数項がで評価されているなって場合、及び0とき。2次微分項はなります。したがって、最終 g(w)=xwyxw<1xw>1xi

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

はの成分に及ぶため、上記をベクトル量として表示し、を省略形として書くことができます。ixw(w1,w2,)


ありがとう!それは私のために物事をクリアします。今、私はちょうど実用的な設定でそれを正しくする必要があります。上記のコードが機能しない理由がわからないでしょうか?4回の反復で収束し、損失は1から始まり、毎回0.25に下がり、0で収束するように見えます。しかし、生成される重みはまったく間違っているようです。
brcs

1
トレーニングデータに与える予測を確認できます。損失がゼロになった場合、すべてのインスタンスを完全に分類する必要があります
ヤロスラフブラトフ

これは、バイナリ分類の場合です。ヒンジ損失を使用したマルチクラス分類の勾配の導出を教えてください。
Shyamkkhadka

12

これは3年遅れていますが、それでも誰かに関係があるかもしれません...

LET点のサンプル示すとラベル対応の集合。総ヒンジ損失を最小化する超平面を検索します: を見つけるには、総ヒンジ損失の導関数を取ります。各コンポーネントの勾配は次のとおりです: SxiRdyi{1,1}w

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

合計の勾配は、勾配の合計です。 GDを使用して検索するPythonの例ヒンジ損失の最適な分離超平面が続きます(おそらく最も効率的なコードではありませんが、機能します)

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

これは、バイナリ分類の場合です。ヒンジ損失を使用したマルチクラス分類の勾配の導出を教えてください。
Shyamkkhadka

1

あなたのコードを修正しました。主な問題は、ヒンジとd_hinge関数の定義です。これらは一度に1つのサンプルに適用する必要があります。代わりに、定義は最大値を取得する前にすべてのサンプルを集約します。

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

収束するにはn = 10000が必要です。

[1] "損失:0.090000、xw:1.08999999999995,0.909999999999905、-1.19000000000008、-1.69000000000011" [1] "損失:0.100000、xw:1.33999999999995,1.1199999999999、-0.900000000000075、-1.42000000000011" [1] "損失:0.230000、xw: 0.939999999999948,0.829999999999905、-1.32000000000007、-1.77000000000011 "[1]"損失:0.370000、xw:1.64999999999995,1.2899999999999、-0.630000000000075、-1.25000000000011 "[1]"損失:0.000000、xw:1.24999999999995,0.999999999999905、-1.05000000000008、-1.60000000000011 " [1] "損失:0.240000、xw:1.49999999999995,1.2099999999999、-0.760000000000075、-1.33000000000011" [1] "損失:0.080000、xw:1.09999999999995,0.919999999999905、-1.18000000000007、-1.68000000000011" [1] "損失:0.110000、xw: 1.34999999999995,1.1299999999999、-0.890000000000075、-1.41000000000011 "[1] "損失:0.210000、xw:0.949999999999948,0.839999999999905、-1.31000000000007、-1.76000000000011" [1] "損失:0.380000、xw:1.65999999999995,1.2999999999999、-0.620000000000074、-1.24000000000011" [1] "損失:0.000000、xw: 1.25999999999995,1.0099999999999、-1.04000000000008、-1.59000000000011 "[1]"損失:0.000000、xw:1.25999999999995,1.0099999999999、-1.04000000000008、-1.59000000000011 "


3
人々、勾配降下は、最悪の最適化アルゴリズムとほぼ同じであり、選択肢がない場合にのみ使用する必要があります。目的関数の値と勾配を使用した信頼領域またはラインサーチ準ニュートンアルゴリズムは、勾配降下を水から吹き飛ばし、より確実に収束します。また、自分が何をしているのかがわからない限り、自分でソルバーを作成しないでください。
マークL.ストーン

2
私は両方の声明に同意します。ただし、少なくとも利用可能なオープンソースライブラリによれば、さまざまなフレーバーを使用した勾配降下は、分散環境での実装がはるかに簡単です。
ジョンジャン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.