OpenOpt の線形計画で圧縮センシング

16,774
-1

Published on

圧縮センシングの実装を具体例に,最適化エンジンのpython用フロントエンドである OpenOpt と,その拡張パッケージである FuncDesigner の使い方を紹介します.

Tokyo.Scipy #3 http://partake.in/events/ac0fcc7d-a289-4e2a-bb8e-1965aab8b17b

Sample Code : https://github.com/tokyo-scipy/archive/tree/master/003/shima__shima

Published in: Technology
0 Comments
21 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
16,774
On Slideshare
0
From Embeds
0
Number of Embeds
5
Actions
Shares
0
Downloads
114
Comments
0
Likes
21
Embeds 0
No embeds

No notes for slide

OpenOpt の線形計画で圧縮センシング

  1. 1. OpenOpt の線形計画で 圧縮センシング 神嶌 敏弘 ( http://www.kamishima.net/ ) Tokyo.Scipy #3 (2012.03.18) 1
  2. 2. 自己紹介 • 機械学習やデータマイニングが専門と名乗ってます • PRML本とか翻訳しましたが,変分ベイズとか,MCMC とか複雑な ことは全然してません • 手法を深掘りすることよりも,新しい問題設定を考えて,できるだけ 簡単な方法で解くようにしたいと思ってます • 教師ありクラスタリング,順序の予測・クラスタリング,推薦システ ム,転移学習,公正配慮型学習 と,問題設定を思いついたら節操な く研究対象は変えてます • 圧縮センシングには関わりがないんですが,線形計画の機械学習関連 での利用例として面白いかなぁ∼と思って,今日の話題に選びました 2
  3. 3. 事件は起きた… 3 お饅頭が2個 なくなっている! 君たちの誰かが 食べたんだよね? ざ ざゎ∼ ざゎ∼ ざゎ∼ ざゎ∼
  4. 4. 事情聴取 4 x A y 入力ベクトル: 要素数は M 饅頭を食べたら 1,でなければ 0 観測ベクトル 要素数は N 大きさ N×M の変換行列 だいたいなんでもOKだが ここでは正規乱数で作った 知ってる 知ってる 知らない
  5. 5. 密談 5 変換行列 A は知られてるけど,乱数で決めた 入力ベクトル長 M は出力ベクトル長 N より大きい 未知数の数より方程式の数が少ないときは解は一意には決まらない だから,だれが饅頭を食べたかなんて分からない 中学レベルの簡単な問題,ふふふ…
  6. 6. 陰謀 6 そう,普通の場合は N<M では解けない 入力ベクトルの非0要素がたかだか K 個の場合 K-スパースといい,K M なら入力ベクトルを復元できるのだよ ふふふっ… だがしかし,こわい大人の世界には 圧縮センシング (compressed sensing) があるのだよ
  7. 7. 結末 7 0 1 0 0 0 01 デコード結果 いや,全然怒ってないから だから,プレゼントに,ログインシェルを ipython にしておいたよ 喜んでくれるとうれしいなぁ∼
  8. 8. OpenOptの線形計画を使った 圧縮センシングの実装 8
  9. 9. 圧縮センシングの解法 9 y=A x を満たす x のうち非0要素の数(L0ノルム)が最小のもの ˆx = arg min x kxk0 subject to y = Ax L0ノルムの計算は大変なので,L1ノルムと置き換える ˆx = arg min x kxk1 subject to y = Ax x と同じ大きさの補助ベクトル t を用いて線形計画問題に変換 O(K log(M/K)) < N ならば高い確率で x を復元可能 ˆx = arg min x X ti subject to t  x  t, y = Ax
  10. 10. OpenOpt 10 • OpenOpt:ホームページ http://openopt.org • 非常に多数の問題に対して共通の API を提供 • 計画問題:線形計画,2次計画,2次錐計画,半正定値計画… • 非線形最適化:非線形計画,非線形最小2乗問題… • フリー・商用の多くのソルバーを共通のAPIで利用可能 • scipy.optimize, glpk, CVXOPT, lpSolve, cplex… • 残念ながらフリーの並列ソルバーはアカデミック限定のcplexのみ • BSDライセンス.GPL系のソルバーは別途インストールの必要 • 収束の様子の可視化や,関数処理 (FuncDesigner),数値微分 (DerApproximator) など便利な関連モジュールも充実
  11. 11. OpenOpt で線形計画 11 定義:p = openopt.LP(問題の引数) 求解:r = p.minimize(ソルバーの指定) 線形計画問題の定義 線形計画問題の求解 線形計画問題は次の引数で指定.x は未知数のベクトルとする • f:fT x は最小化・最大化する目的関数 • Aeq, beq:Aeq x = beq で等式の制約を定義 • A, b:A x b の不等式制約 • lb, ub:lb x ub の x の範囲の制約 ※あと Awhole, bwhole, dwhole という引数があるが用途不明 使い方の基本形 問題オブジェクトのメソッドによって解を求める • 最小化の p.minimize と最大化の p.maximize がある • ソルバーは pclp, glpk, lpSolve などの文字列で指定
  12. 12. 圧縮センシングの実装 12 • 定義:n_outputs(=N), n_inputs(=M), trans(=A), 入力ベクトル x1 • ベクトル x と t も共に長さ n_inputs のベクトル,x のあとに t を連 結した長さ 2 n_inputs のベクトルを考える 目的関数 • は ベクトル t と1ベクトルの内積と等価なので • 目的関数の係数ベクトル f は,未知ベクトルの前半 x に対応する部 分は全て 0 に,後半の t に対応する部分は全て 1 にする # objective to minimize: f x^T -> min f = np.zeros((n_inputs * 2), dtype=np.float) f[n_inputs:2 * n_inputs] = 1.0 P i ti 未知数 ˆx = arg min x X ti subject to t  x  t, y = Ax
  13. 13. 圧縮センシングの実装 13 • x に対応する Aeq の左半分は変換行列 trans に,右半分は 0 消去 • 左辺の beq に対応するところは観測ベクトル y を示す x1 となる 等式の制約条件 # constraint: a x^T == b a_eq = np.zeros((n_outputs, 2 * n_inputs), dtype=np.float) a_eq[:, 0:n_inputs] = trans b_eq = x1 y = Ax 不等式の制約条件 t  x  t • 書き換え: xi ti  0, xi ti  0, for i = 0, . . . , M # constraint: -t <= x <= t a = np.zeros((2 * n_inputs, 2 * n_inputs), dtype=np.float) for i in xrange(n_inputs): a[i, i] = -1.0 a[i, n_inputs + i] = -1.0 a[n_inputs + i, i] = 1.0 a[n_inputs + i, n_inputs + i] = -1.0 b = np.zeros(n_inputs * 2)
  14. 14. 圧縮センシングの実装 14 問題の設定と求解 # solve linear programming prob = openopt.LP(f=f, Aeq=a_eq, beq=b_eq, A=a, b=b) result = prob.minimize('pclp') • 問題を設定するには今まで作った配列を代入する • 最小化を付属の pclp ソルバーで実行.glpk や lpSolve も使えれば 解と実行結果 • result.ff と result.xf は最小化したときの目的関数の値と未知数の値 ------------------------- OpenOpt 0.37 ------------------------- solver: pclp problem: unnamed type: LP goal: minimum iter objFunVal log10(maxResidual) 0 0.000e+00 0.17 1 1.624e+00 -15.26 istop: 1000 Solver: Time Elapsed = 0.36 CPU Time Elapsed = 0.361499 objFunValue: 1.6237004 (feasible, MaxResidual = 5.55112e-16)
  15. 15. FuncDesignerの紹介 15
  16. 16. FuncDesigner登場 16 でも,問題の書き換えを手作業で変換して プログラミングするのは面倒だよね… そんなあなたに FuncDesigner ! 条件式の定義が簡単! 微分や積分だってできちゃう!
  17. 17. FuncDesigner 17 • FuncDesigner ホームページ: http://openopt.org/FuncDesigner • OpenOpt の最適化問題をより直感的に定義できるように工夫された モジュール • 実行手順の概要 • 変数に該当するオブジェクトを最初に定義 • 四則演算や初等関数が演算子オーバーロードされていて,自然に関 数を定義 • 入力点を表す辞書型の変数を与えると,その点での関数値を得る • 関数がそのまま保持されているので,数値微分ではなく,解析的に微 分した結果を利用できる • 定義した関数を使った数値積分や補間もできてしまう
  18. 18. FuncDesignerの使用法 18 import • 付属サンプルでは from FuncDesigner import * だが,ここでは 変数の定義 • 変数オブジェクトは fd.oovar で定義する • 定義した関数の中で変数に特に名前を付ける v = fd.oovar('speed') import FuncDesigner as fd a = fd.oovar() • 変数はスカラーの場合も,ベクトルの場合もある.ベクトルのときは 大きさを指定することもできる x = fd.oovar(size=100) • 複数の変数をまとめて定義するときには fd.oovars を使う • 名前が a b c の変数オブジェクト a, b, c を定義している a, b, c = fd.oovars('a', 'b', 'c') ※勘違いポイント:これは三つの値を持つベクトルではない.a, b, c がそれぞれ大きさの違うベクトルやスカラーである場合もありうる.
  19. 19. FuncDesignerの使用法 19 関数の定義 ※勘違いポイント:関数を定義するだけで,評価は行われない. lambda で定義しているイメージ. ※以下の説明では a, b, c や x, y, z はここでは変数オブジェクトです • 四則演算の演算子はオーバーロードされてるのでそのまま書けばOK f = a * b + x / y • 初等関数は FuncDesigner のものを使えばよい f = fd.sin(x) g += c g = fd.log(y) • ベクトルになっている変数オブジェクトには内積や総和も使える f = fd.dot(a, b) g = fd.sum(x) • ベクトルなら添え字も可能 • これは sum と等価だが,sum の方が速い f = 0 for i in xrange(3): f = f + a[i]
  20. 20. FuncDesignerの使用法 20 • 値の代入には辞書を使う • 変数オブジェクトをキーとし,その変数 に代入する値を辞書の値に設定 関数の評価 ※勘違いポイント:lambda で定義した関数 とは違って,引数の形で呼び出すとエラー になる In [10]: a = fd.oovar() In [12]: f = fd.sin(a) In [13]: f(1) AttributeError In [20]: a, b = fd.oovars(2) In [21]: f = a + b In [22]: p = { a:1, b:10 } In [23]: f(p) Out[23]: array(11.0) •変数にベクトル値を設定すると, ベクトルとして評価される In [30]: a, b = fd.oovars(2) In [31]: f = a + b In [32]: p = { a:1.0, b:np.array([10., 20., 30.]) } In [33]: f(p) Out[33]: array([ 11., 21., 31.])
  21. 21. FuncDesignerの使用法 21 関数の微分 • 数値微分ではなく,解析的に微分した関数の評価が可能 • 定義した関数オブジェクトに D メソッドを適用するだけ In [10]: x = fd.oovar() In [11]: f = fd.sin(x) In [12]: f({x:np.pi}) Out[12]: array(1.2246467991473532e-16) # ほとんど 0 In [13]: f.D({x:np.pi}) Out[13]: {unnamed_oofun_11: -1.0} # sin'(π) = cos(π) = -1.0 • ベクトルで微分するとヤコビ行列として評価される In [20]: x = fd.oovar() In [21]: f = 2 * x ** 2 In [22]: p = {x:np.array([1., 2., 3.])} In [23]: f(p) Out[23]: array([ 2., 8., 18.]) In [24]: f.D(p) Out[24]: {unnamed_oofun_13: array([[ 4., 0., 0.], [ 0., 8., 0.], [ 0., 0., 12.]])}
  22. 22. 圧縮センシング:FuncDesinger版 22 • 変数の定義:元の未知数 x と,補助変数 t をベクトルとして定義 # define variable t = fd.oovar('t', size=n_inputs) x = fd.oovar('x', size=n_inputs) # objective to minimize: f x^T -> min objective = fd.sum(t) • 目的関数の定義:補助変数 t の要素の和なので,単純に sum を適用 • 制約の定義:制約の集合は python のリストを使って定義 • リストの初期化 # init constraints constraints = [] • A x = y の制約は,fd.dot を適用するだけ # equality constraint: a_eq x^T = b_eq constraints.append(fd.dot(trans, x) == x1)
  23. 23. 圧縮センシング:FuncDesinger版 23 • 不等式制約 -t x t はそのまま書けばよい # inequality constraint: -t < x < t constraints.append(-t <= x) constraints.append(x <= t) • 初期値の設定:変数の大きさを知らせる必要があるので必要.線形計 画は初期値は計算時間にしか影響しないので 0 でだいたいOK # start_point start_point = {x:np.zeros(n_inputs), t:np.zeros(n_inputs)} • 線形計画の実行:目的関数,初期値,制約を与えて問題を定義. FuncDesingerなし版と同様にソルバーを適用すればよい # solve linear programming prob = LP(objective, start_point, constraints=constraints) result = prob.minimize('pclp') • 最小値を達成したときの変数の値は result の xf 属性に辞書の形 で格納されている hat_x = result.xf[x]
  24. 24. 実行可能なソースコード 24 • 今回のソースコードは Tokyo.Scipy の github レポジトリで配布 • https://github.com/scipy-japan/tokyo-scipy/tree/master/003/shima__shima • numpy / scipy の他に,OpenOpt のインストールは • easy_install -U openopt • easy_install -U FuncDesigner • 実行できるファイルは • 直接実行する 版: compressed_sensing.py • FuncDesigner 版: compressed_sensing2.py • メインルーチンの n_outputs が観測変数の数なので,2∼7 の範囲で 変えてみて下さい
  25. 25. 参考文献 • OpenOpt ホームページ • http://openopt.org • 和田山 正 圧縮センシングの理論とその展開 第13回情報論的学習理 論ワークショップ (2010) • http://ibisml.org/ibis2010/session/ibis2010wadayama.pdf • 田中 利幸 圧縮センシングの数理 IEICE Fundamentals Review, vol.4, no.1, pp.39-47 (2010) • http://www.jstage.jst.go.jp/article/essfr/4/1/4_39/_article/- char/ja/ 25
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×