回帰で扱う代理損失

回帰で扱う代理損失

入力をxXx \in \mathcal{X},出力をyRy \in \mathbb{R}とする.分類問題と違って,mmの定義の仕方に工夫が必要.例えば以下のようにmmを定義する.

m=ϵyf(x) \begin{aligned} m = \epsilon - |y - f(x)| \end{aligned}

ただし,ϵ0\epsilon \geq 0.そうすると,

I[m<0] \begin{aligned} \mathbb{I}\left[m < 0\right] \end{aligned}

で不正解となる.分類問題と同じ代理損失が使える.

max{0,1ϵ+yf(x)} \begin{aligned} \max\{0, 1 - \epsilon + |y - f(x)|\} \end{aligned}

これは,ϵ\epsilon-insensitive lossと呼ばれる.

Written with StackEdit.

分類問題で扱う代理損失

分類問題で扱う代理損失

入力をxXx \in \mathcal{X},出力をy{1,1}y \in \{-1, 1\}とする.f(x)0f(x) \geq 0のときは正例と,f(x)<0f(x) < 0のときは負例と予測する分類器を考える.m=yf(x)m = yf(x)とすると,m0m \geq 0のとき正解で,m<0m < 0のとき,不正解となる.不正解のときは11を,正解の時は00になるような損失関数を以下のように定義する.

I[m<0] \begin{aligned} \mathbb{I}\left[m < 0\right] \end{aligned}

ただし,I\mathbb{I}は指示関数である.有名な損失関数として,hinge lossや,exponential lossがある.

hinge=max{0,1m}exp=exp(m) \begin{aligned} \ell_{hinge} &= \max\{0, 1 - m\}\\ \ell_{exp} &= \exp \left(- m\right) \end{aligned}

流れ的には,目的関数を指示関数を使って上のように定義して,代理損失で置き換えるって感じかな.

Written with StackEdit.

ヒンジ損失の劣勾配

ヒンジ損失の劣勾配

ヒンジ損失の劣勾配を求めようと思う.と言っても,[1]のPointwise maximumのテクニックを使えば一発なのだが.まずはこれを示そう.以下の関数を考える.

f(x)=maxi=1,,mfi(x) \begin{aligned} f(x) = \max_{i=1,\ldots,m} f_i(x) \end{aligned}

あるxxに対して,f(x)=fk(x)f(x) = f_k(x)だったとする.gfk(x)g \in \partial f_k(x)とする.

f(y)fk(y)fk(x)+gT(yx)=f(x)+gT(yx) \begin{aligned} f(y) \geq f_k(y) \geq f_k(x) + g^T (y - x) = f(x) + g^T (y - x) \end{aligned}

より,gf(x)g \in \partial f(x)である.
以下で定義されるヒンジ損失を考える.

hinge(w)=max{0,1ywTx} \begin{aligned} \ell_{hinge}(\bm{w}) = \max\{0, 1 - y \bm{w}^T \bm{x}\} \end{aligned}

上記の事実を踏まえると,

g={0d(1ywTx0)yx(1ywTx<0) \begin{aligned} \bm{g} = \left\{\begin{array}{ll} \bm{0}_d & (1 - y \bm{w}^T \bm{x} \geq 0) \\ -y \bm{x} & (1 - y \bm{w}^T \bm{x} < 0) \end{array}\right. \end{aligned}

となる.

  1. https://see.stanford.edu/materials/lsocoee364b/01-subgradients_notes.pdf

Written with StackEdit.

L1-Normの劣微分

l1_subgradient_2

前にL1-Normの劣微分
について書いたが,間違っていたので修正.

[1]のPointwise maximumの項に書いてあるテクニックを使う.xRd\bm{x} \in \mathbb{R}^dとして,x1\|\bm{x}\|_1を以下のように表す(結構感動的).

f(x)=x1=max{sTxs{1,1}d} \begin{aligned} f(\bm{x}) = \|\bm{x}\|_1 = \max\{\bm{s}^T \bm{x} \vert \bm{s} \in \{-1, 1\}^d\} \end{aligned}

x\bm{x}に対して,x1=sTx\|\bm{x}\|_1 = \bm{s}^T \bm{x}となったとする.この時,s\bm{s}は以下のようになる.

sj={1(xj>0)1(xj<0)1 or 1(xj=0) \begin{aligned} s_j = \left\{\begin{array}{ll} 1 & (x_j > 0) \\ -1 & (x_j < 0) \\ -1 \ \text{or} \ 1 & (x_j = 0) \end{array}\right. \end{aligned}

sTx\bm{s}^T \bm{x}のsubgradientをg\bm{g}とすると,gf(x)\bm{g} \in \partial f(\bm{x})である.最後に,g=s\bm{g} = \bm{s}である.

参考:

  1. https://see.stanford.edu/materials/lsocoee364b/01-subgradients_notes.pdf

Written with StackEdit.

劣勾配法(Lasso)

lasso

今回は劣勾配法を使って,L1正則化最小二乗学習(Lasso)を実装してみたいと思う.最適化問題を,以下のように定義する.

minw 12i=1n(yiwTxi)2+λw1 \begin{aligned} \min_{\bm{w}} \ \frac{1}{2} \sum_{i=1}^n \left(y_i - \bm{w}^T \bm{x}_i\right)^2 + \lambda \|\bm{w}\|_1 \end{aligned}

第一項はwjw_jで微分可能なので,その勾配を使い,第二項は列勾配を使う.これで更新式を出すと,

wjwjη(i=1n(yiwTxi)xij+λsgn(wj)) \begin{aligned} w_j \leftarrow w_j - \eta \left(- \sum_{i=1}^n (y_i - \bm{w}^T \bm{x}_i) x_{ij} + \lambda sgn(w_j)\right) \end{aligned}

となる.まとめると,

wwη(XT(yXw)+λsgn(w)) \begin{aligned} \bm{w} \leftarrow \bm{w} - \eta \left(- \bm{X}^T \left(\bm{y} - \bm{X} \bm{w}\right) + \lambda sgn(\bm{w})\right) \end{aligned}

となる.これを実装したクラスが以下.

class Lasso(object):

    def __init__(self, eta=1e-4, reg=1, max_iter=1000):
        self.eta = eta
        self.reg = reg
        self.max_iter = max_iter

    def fit(self, X, y):
        w = np.zeros(X.shape[1])
        for _ in range(self.max_iter):
            g = - X.T.dot(y - X.dot(w)) + self.reg * np.sign(w)
            w = w - self.eta * g
        self.w = w
        return self

    def predict(self, X):
        return X.dot(self.w)

1-d example

1次元で実験してみる.

import numpy as np
import matplotlib.pyplot as plt

random_state = 0
rnd = np.random.RandomState(random_state)

n, d = 100, 2
sigma = 0.5
x = np.linspace(-2, 2, n)
y = x + rnd.normal(0, sigma, size=n)

model = Lasso()
model.fit(np.c_[x], y)

y_pred = model.predict(np.c_[x])
plt.scatter(x, y)
plt.plot(x, y_pred, "r-", linewidth=3)

結果は以下.きちんと学習されているっぽい.

100-d example

次にL1正則化を施したことにより,解がスパースになることを確認するために,100次元のデータで実験する.コードは例えば以下.

from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error

X, y = make_regression(n_samples=500, n_features=100, n_informative=10, random_state=random_state)

X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=random_state)

model = Lasso()
model.fit(X_train, y_train)

y_pred = model.predict(X_test)

print(np.sqrt(mean_squared_error(y_test, y_pred))) # 0.008980784567524594

きちんと解がスパースになっていることを確認してみる.例えば,

np.around(model.w, 3)

とすると,

array([ 0.   , -0.   , -0.   ,  0.   , -0.   ,  0.   ,  0.   , -0.   ,
       -0.   ,  0.   ,  0.   , -0.   ,  0.   ,  0.   , -0.   , -0.   ,
        0.   ,  0.   , -0.   ,  0.   ,  0.   , -0.   , 99.673,  0.   ,
        0.   , -0.   ,  0.   ,  0.   , -0.   ,  0.   , 41.788,  0.   ,
       -0.   , -0.   ,  0.   , -0.   ,  0.   , -0.   ,  0.   , -0.   ,
       -0.   , 74.23 , -0.   ,  0.   ,  0.   ,  0.   ,  0.   ,  0.   ,
       -0.   , -0.   ,  0.   , -0.   ,  0.   ,  0.   ,  0.   ,  0.   ,
       -0.   , -0.   ,  0.   , -0.   ,  0.   , 37.469, -0.   ,  0.   ,
        0.   ,  0.   ,  0.   ,  0.   ,  0.   ,  0.   , -0.   , -0.   ,
       30.374, 44.89 ,  0.   , 50.938,  0.   ,  0.   , -0.   , -0.   ,
       -0.   ,  0.   ,  0.   , 98.669, -0.   ,  0.   , 27.71 ,  0.   ,
        0.   , -0.   , -0.   , -0.   , -0.   , 86.562, -0.   ,  0.   ,
       -0.   , -0.   ,  0.   ,  0.   ])

となって,n_informativeの数だけ非ゼロになっている.

Written with StackEdit.

機械学習の問題設定

機械学習の問題設定 機械学習の問題設定を見直したのでメモ. ( Ω , F , P ) (\Omega, \mathcal{F}, P) ( Ω , F , P ) : ベースとなる確率空間 ( X , F X ) (\mathcal...