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

25
OpenOpt の線形計画で 圧縮センシング 神嶌 敏弘 ( http://www.kamishima.net/ ) Tokyo.Scipy #3 (2012.03.18) 1

Upload: tosshihiro-kamishima

Post on 24-May-2015

15.509 views

Category:

Technology


4 download

DESCRIPTION

圧縮センシングの実装を具体例に,最適化エンジンの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

TRANSCRIPT

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

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

神嶌 敏弘 ( http://www.kamishima.net/ )Tokyo.Scipy #3 (2012.03.18)

1

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

自己紹介

•機械学習やデータマイニングが専門と名乗ってます• PRML本とか翻訳しましたが,変分ベイズとか,MCMC とか複雑なことは全然してません•手法を深掘りすることよりも,新しい問題設定を考えて,できるだけ簡単な方法で解くようにしたいと思ってます•教師ありクラスタリング,順序の予測・クラスタリング,推薦システム,転移学習,公正配慮型学習 と,問題設定を思いついたら節操なく研究対象は変えてます•圧縮センシングには関わりがないんですが,線形計画の機械学習関連での利用例として面白いかなぁ~と思って,今日の話題に選びました

2

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

事件は起きた…

3

お饅頭が2個なくなっている!

君たちの誰かが食べたんだよね?

ざゎ~

ざゎ~ざゎ~

ざゎ~

ざゎ~ ざゎ~

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

事情聴取

4

xA

y

入力ベクトル: 要素数は M饅頭を食べたら 1,でなければ 0

観測ベクトル要素数は N

大きさ N×M の変換行列だいたいなんでもOKだがここでは正規乱数で作った

知ってる知ってる

知らない

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

密談

5

変換行列 A は知られてるけど,乱数で決めた

入力ベクトル長 M は出力ベクトル長 N より大きい

未知数の数より方程式の数が少ないときは解は一意には決まらないだから,だれが饅頭を食べたかなんて分からない

中学レベルの簡単な問題,ふふふ…

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

陰謀

6

そう,普通の場合は N<M では解けない

入力ベクトルの非0要素がたかだか K 個の場合K-スパースといい,K≪M なら入力ベクトルを復元できるのだよ

ふふふっ…

だがしかし,こわい大人の世界には圧縮センシング (compressed sensing)

があるのだよ

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

結末

7

0 1 0 0 0 01

デコード結果

いや,全然怒ってないからだから,プレゼントに,ログインシェルを ipython にしておいたよ

喜んでくれるとうれしいなぁ~

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

OpenOptの線形計画を使った圧縮センシングの実装

8

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

圧縮センシングの解法

9

y=A x を満たす x のうち非0要素の数(L0ノルム)が最小のものˆ

x = argmin

x

kxk0 subject to y = Ax

L0ノルムの計算は大変なので,L1ノルムと置き換えるˆ

x = argmin

x

kxk1 subject to y = Ax

x と同じ大きさの補助ベクトル t を用いて線形計画問題に変換

O(K log(M/K)) < N ならば高い確率で x を復元可能

ˆ

x = argmin

x

Xti subject to � t x t, y = Ax

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

OpenOpt

10

• OpenOpt:ホームページ http://openopt.org•非常に多数の問題に対して共通の API を提供•計画問題:線形計画,2次計画,2次錐計画,半正定値計画…•非線形最適化:非線形計画,非線形最小2乗問題…•フリー・商用の多くのソルバーを共通のAPIで利用可能• scipy.optimize, glpk, CVXOPT, lpSolve, cplex…•残念ながらフリーの並列ソルバーはアカデミック限定のcplexのみ• BSDライセンス.GPL系のソルバーは別途インストールの必要•収束の様子の可視化や,関数処理 (FuncDesigner),数値微分 (DerApproximator) など便利な関連モジュールも充実

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

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 などの文字列で指定

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

圧縮センシングの実装

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 -> minf = np.zeros((n_inputs * 2), dtype=np.float)f[n_inputs:2 * n_inputs] = 1.0

Pi ti

未知数

ˆ

x = argmin

x

Xti subject to � t x t, y = Ax

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

圧縮センシングの実装

13

• x に対応する Aeq の左半分は変換行列 trans に,右半分は 0 消去•左辺の beq に対応するところは観測ベクトル y を示す x1 となる

等式の制約条件

# constraint: a x^T == ba_eq = np.zeros((n_outputs, 2 * n_inputs), dtype=np.float)a_eq[:, 0:n_inputs] = transb_eq = x1

y = Ax

不等式の制約条件 �t x t

•書き換え: �xi � ti 0, xi � ti 0, for i = 0, . . . ,M

# constraint: -t <= x <= ta = 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.0b = np.zeros(n_inputs * 2)

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

圧縮センシングの実装

14

問題の設定と求解

# solve linear programmingprob = 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: 1000Solver: Time Elapsed = 0.36 CPU Time Elapsed = 0.361499objFunValue: 1.6237004 (feasible, MaxResidual = 5.55112e-16)

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

FuncDesignerの紹介

15

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

FuncDesigner登場

16

でも,問題の書き換えを手作業で変換してプログラミングするのは面倒だよね…

そんなあなたに FuncDesigner !条件式の定義が簡単!

微分や積分だってできちゃう!

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

FuncDesigner

17

• FuncDesigner ホームページ: http://openopt.org/FuncDesigner• OpenOpt の最適化問題をより直感的に定義できるように工夫されたモジュール•実行手順の概要•変数に該当するオブジェクトを最初に定義•四則演算や初等関数が演算子オーバーロードされていて,自然に関数を定義•入力点を表す辞書型の変数を与えると,その点での関数値を得る•関数がそのまま保持されているので,数値微分ではなく,解析的に微分した結果を利用できる•定義した関数を使った数値積分や補間もできてしまう

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

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 がそれぞれ大きさの違うベクトルやスカラーである場合もありうる.

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

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 = 0for i in xrange(3): f = f + a[i]

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

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 + bIn [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 + bIn [32]: p = { a:1.0, b:np.array([10., 20., 30.]) }In [33]: f(p)Out[33]: array([ 11., 21., 31.])

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

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) # ほとんど 0In [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 ** 2In [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.]])}

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

圧縮センシング:FuncDesinger版

22

•変数の定義:元の未知数 x と,補助変数 t をベクトルとして定義# define variablet = fd.oovar('t', size=n_inputs)x = fd.oovar('x', size=n_inputs)

# objective to minimize: f x^T -> minobjective = fd.sum(t)

•目的関数の定義:補助変数 t の要素の和なので,単純に sum を適用

•制約の定義:制約の集合は python のリストを使って定義•リストの初期化

# init constraintsconstraints = []

• A x = y の制約は,fd.dot を適用するだけ# equality constraint: a_eq x^T = b_eqconstraints.append(fd.dot(trans, x) == x1)

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

圧縮センシング:FuncDesinger版

23

•不等式制約 -t ≦ x ≦ t はそのまま書けばよい# inequality constraint: -t < x < tconstraints.append(-t <= x)constraints.append(x <= t)

•初期値の設定:変数の大きさを知らせる必要があるので必要.線形計画は初期値は計算時間にしか影響しないので 0 でだいたいOK

# start_pointstart_point = {x:np.zeros(n_inputs), t:np.zeros(n_inputs)}

•線形計画の実行:目的関数,初期値,制約を与えて問題を定義.FuncDesingerなし版と同様にソルバーを適用すればよい

# solve linear programmingprob = LP(objective, start_point, constraints=constraints)result = prob.minimize('pclp')

•最小値を達成したときの変数の値は result の xf 属性に辞書の形で格納されている

hat_x = result.xf[x]

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

実行可能なソースコード

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 の範囲で変えてみて下さい

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

参考文献

• 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