を導き、これが
を満たすことを説明しました。ここで は点
における凸関数 f の曲率の上限です。
ところでメジャライザのノルム中の定ベクトルを
式(1)
と書けば
となります。
更にL1正則化問題の場合
なのでL1正則化問題の目的関数
に対するメジャライザは
となります。よってL1正則化問題の場合も上のメジャライザを最小化、その点でメジャライザを構築し直し最小化…を繰り返すことで最適解が得られます。ちなみにその際定数は何の寄与も持たないので
を最小化することになります。
ところで、この解は解析的に求められ
式(2)
となります。ここで は以下のsoft-threshold関数です。
以上からISTAのアルゴリズムは以下のように求められます。
===== ISTAのアルゴリズム =======
4. 収束判定クリアなら終了、そうでなければ2. へ
これがISTAの基本的な解析フローになります。
=======================================
これに基づいて、ISTAの1サイクルを実行する機能を持ったクラスをpythonで作成してみました(なお実効するには予め numpy (あとmatplotlib.pyplot)をインポートしておく必要が有ります)。
ここでは、データ y、伝達行列 X に対し以下を満たす β を求めるL1正則化問題を考えます。
このため目的関数
を最小化することを考えます。
この場合、これまで f(β) と表記していた損失関数とその微分は具体的に
式(3)
となります。
これをテストデータで動かしてみましょう。
n x n (下の場合 n = 100) のランダムな行列を X0 とし、真の解を
40 - 70番目の要素が 1、その他が 0
であるベクトル beta0 とします。
また入力データ y0 には X0.dot(beta0) を用います。
またISTAのアルゴリズムに乗せるため X0 は標準化、 y0 は中心化し、それぞれ X、yとしています。
こうして作成した X と y を入力としてISTAで beta0 の再現を試みました。
ここで定数 K をどうやって求めるか、ということが問題になります。
これまで説明してきたように K は 点βにおけるf(β)の曲率の上限値でした。
f が式(3)でかける場合、その曲率は
なのでこの行列の最大固有値(より少し大きな値)が曲率の上限になります。
そこで下では np.linalg.eig で X.T.dot(X) を固有値分解して最大値を求め、その ceil を K としています。
また正則化パラメータ λ は 0.01 として計算しました。
上の計算では epsilon = 1.e-5、maxniter = 1000 としています。
この計算により下の結果が得られました。
ここで横軸が β の要素番号、縦軸が β の各要素の値です。
青い点が真のモデル beta0、オレンジが得られた解(を、X の標準化の際 X の各列を規格化した効果を取り除いたもの) beta / w ( wは X の各列ベクトルのノルムを格納したもの)を表します。
オレンジが青を良く再現できているのが分かります。
なおこの計算でのイテレーション回数 (niter) は 620 回でした(乱数のseedを設定していないので毎回結果は異なりますが…)。
=======================================
さて、前回の記事に続き今回でISTAの概念的な解析フローとサンプルの愚直なpythonクラスを提示しました。
ところで、実用上では定数 K をどう求めるか、という事が問題になってきます。
上で述べたように今回は固有値分解のソルバーで直接 K を計算していますが、大規模問題ではここで大きな計算コストがかかる、或いは問題が大きすぎてそもそも求められない、といった場合も出てきます。
またこれまで軽く流していますが、この定数はLipschitz (リプシッツ)定数と呼ばれていて、本来 Lipschitz 連続(リプシッツ連続)という、関数の連続性の拡大解釈に基づき説明されます。
この辺りについての説明も、あまり理論に偏らない範囲で次回以降のどこかで説明したいと思っています(自分自身への備忘録的なドキュメントとして!)。

