23
Sized Linear Algebra Package のチュートリアル 2016/7/9 ML勉強会 2016/7/7 A.J.A.勉強会

Sized Linear Algebra Package のチュートリアル

Embed Size (px)

Citation preview

Page 1: Sized Linear Algebra Package のチュートリアル

Sized Linear Algebra Packageのチュートリアル

2016/7/9 ML勉強会2016/7/7 A.J.A.勉強会

Page 2: Sized Linear Algebra Package のチュートリアル

自己紹介

● 名前:阿部晃典

● Twitter:@ackey_65535● 興味:プログラミング言語理論、機械学習

○ 幽霊型を使った線形代数ライブラリ Sized Linear Algebra Package (SLAP)■ http://akabe.github.io/slap/

○ 幽霊型トリック集 @ML Advent Calendar 2015■ http://akabe.github.io/2015/12/PhantomTypeTricks

○ EvilML (a compiler from ML to C++ template)■ http://akabe.github.io/evilml/

Page 3: Sized Linear Algebra Package のチュートリアル

SLAP (Sized Linear Algebra Package)● 行列演算の次元の整合性を幽霊型で保証

○ 例:2次元と3次元のベクトルを足すと型エラー

○ ほとんどの行列演算を検査可能(行列積、固有値分解、最小二乗法など)

○ ファイルから読み込んだ行列などもサイズ検査可能

● 割と実用的 (cf. Abe & Sumii, EPTCS’15 post-proccedings of ML/OCaml)● ドキュメントも(研究で作ったライブラリにしては)多い

○ チュートリアルやデモもあるよ!

● 今日は、SLAP のチュートリアルと宣伝が目的

○ 幽霊型?ブログ読んでね

Page 4: Sized Linear Algebra Package のチュートリアル

おしながき● 環境構築

● 簡単なベクトル・行列演算の紹介

● ファイルから読み込んだベクトルのサイズ検査

● LAPACK 関数の紹介

● 実用的なプログラムの紹介

Page 5: Sized Linear Algebra Package のチュートリアル

ことはじめ

$ wget https://raw.github.com/ocaml/opam/master/shell/opam_installer.sh -O - | sh -s /usr/local/bin$ eval `opam config env`

$ opam install slap utop

● お好みの BLAS, LAPACK をインストール

○ オーソドックスな本家も良し!ATLAS 等で最適なコードを錬成するも良し!

● OPAM のインストール(OCaml のパッケージマネージャ)

● SLAP をインストール(ついでに utop もあると良い)

○ utop:OCaml の高級対話環境

Page 6: Sized Linear Algebra Package のチュートリアル

対話環境で SLAP を読み込む

$ utoputop # #use “topfind”;;utop # #use “slap”;;utop # #use “slap.top”;;utop # #use “slap.ppx”;;utop # open Slap.D;;utop # open Slap.Common;;

プロンプト

Page 7: Sized Linear Algebra Package のチュートリアル

ベクトルとか行列を作ってみる

Page 8: Sized Linear Algebra Package のチュートリアル

ベクトル

utop # open Slap.Size;;utop # open Slap.D;;utop # let x = [%vec [1.0; 2.0; 3.0; 4.0]];;val x : (four, 'a) vec = R1 R2 R3 R4 1 2 3 4 ベクトルの中身ベクトルのサイズを表す型

utop # let y = Vec.cons 5.0 x;;val x : (four s, 'a) vec = R1 R1 R2 R3 R4 5 1 2 3 44 + 1 = 5 次元ベクトル

utop # dot x x;;- : float = 30.

Page 9: Sized Linear Algebra Package のチュートリアル

違う次元のベクトルの内積を取ると型エラー

utop # dot x y;;Error: This expression has type (four s, 'a) vec = (four s, float, rprec, 'a) Slap_vec.tbut an expression was expected of type (four, 'b) vec = (four, float, rprec, 'b) Slap_vec.tType four s is not compatible with type four = z s s s sType four = z s s s s is not compatible with type z s s sType z s is not compatible with type z

「4 次元 ≠ 5 次元 だからエラー」と言っている

val x : (four, ‘a) vecval y : (four s, ‘a) vecval dot : (‘n, _) vec → (‘n, _) vec → float

Page 10: Sized Linear Algebra Package のチュートリアル

utop # Vec.get_dyn x 2;;- : float = 2.

SLAP の静的サイズ検査でできないこと

● 基本的に、サイズの等しさのみ検査

○ 線形代数だと等しさだけでも結構しっかり検査できる

● 計算結果が等しいか検査するのは苦手

○ 多少はできるけど、加算の交換則、分配則などは扱えない

● 大小比較は検査しない

○ 検査する方法もあるが、複雑なので諦めている

○ 具体例:

■ 添字アクセスなどの低級操作

■ LAPACK 関数の作業用メモリサイズの検査

■ orgqr (QR分解), syevr (上位固有値計算)

動的にサイズ検査する関数は _dyn がついている

Page 11: Sized Linear Algebra Package のチュートリアル

行列

utop # let a = [%mat [1.0, 2.0, 3.0; 4.0, 5.0, 6.0]];;val a : (two, three, 'a) mat = C1 C2 C3 R1 1 2 3 R2 4 5 6

行列の中身2 ✕ 3 行列

utop # open Slap.Common;;utop # gemm ~transa:normal ~transb:trans a a;;- : (two, two, 'a) mat = C1 C2 R1 14 32 R2 32 77行列 ✕ 行列演算

左項の行列は非転置

右項の行列は転置

= A AT

Page 12: Sized Linear Algebra Package のチュートリアル

行列演算でも次元の不整合を静的に検出できる

やってみて!

Page 13: Sized Linear Algebra Package のチュートリアル

ファイルから読み込んだって大丈夫

Page 14: Sized Linear Algebra Package のチュートリアル

ファイルからベクトルを読み込む

utop # module X = Vec.Of_list(struct let value = load_list “hoge.txt” end);;module X : sig type n val value : (n, 'cnt) vec endutop # X.value;;- : (X.n, ‘a) vec = R1 R2 R3 … R98 R99 R100 1.982 2.234 8 … 9.273 -1.293 3.202

(* ファイルからリスト or 配列を読む関数は自作してください *)val load_list : string -> float list

次元が(コンパイル時に)不明だった

※ X.n は生成的な幽霊型 cf. http://akabe.github.io/2015/10/GenerativePhantomTypes

Page 15: Sized Linear Algebra Package のチュートリアル

違うファイルから読み込んだベクトルは違う次元utop # module X = Vec.Of_list(struct let value = load_list “hoge.txt” end);;utop # module Y = Vec.Of_list(struct let value = load_list “fuga.txt” end);;utop # dot X.value Y.value;;Error: This expression has type (Y.n, 'a) vec = (Y.n, float, rprec, 'a) Slap_vec.tbut an expression was expected of type (X.n, 'b) vec = (X.n, float, rprec, 'b) Slap_vec.tType Y.n is not compatible with type X.n

※ 仮にファイル名が同じでも、読込中に更新されるかもしれないので、型エラーになる

Page 16: Sized Linear Algebra Package のチュートリアル

LAPACK 関数の紹介

Page 17: Sized Linear Algebra Package のチュートリアル

getri:逆行列 (LU 分解ベース)● getrf (LU 分解) の結果を元に逆行列を計算

● 求めた逆行列は引数の行列に破壊的に代入

utop # let a = [%mat [3.0, 2.0, -1.0; 1.0, 4.0, 0.0; -3.0, 5.0, 2.0]];;val a : (three, three, 'a) mat = C1 C2 C3 R1 3 2 -1 R2 1 4 0 R3 -3 5 2utop # getri a;;- : unit = ()utop # a;;- : (three,three, 'a) mat = C1 C2 C3 R1 2.66667 -3 1.33333 R2 -0.666667 1 -0.333333 R3 5.66667 -7 3.33333

これが逆行列

Page 18: Sized Linear Algebra Package のチュートリアル

syev:対称行列の固有値分解

● 対称行列:A = AT、直交行列:V VT = E、対角行列:対角成分以外ゼロ

● 固有値分解:A = V D VT (V は直交行列、D は対角行列)

utop # let a = [%mat [3.0, 2.0, -1.0; 2.0, 4.0, 0.0; -1.0, 0.0, -2.0]];;val a : (three, three, 'a) mat = C1 C2 C3 R1 3 2 -1 R2 2 4 0 R3 -1 0 -2utop # syev ~vectors:true a;;- : (three, ‘a) vec = R1 R2 R3 -2.21856 1.60627 5.6123utop # a;;- : (three, three, 'a) mat = C1 C2 C3 R1 0.213021 -0.750591 -0.625487 R2 -0.0685114 0.62713 -0.775896 R3 0.974643 0.208135 0.082168

固有値(D の対角成分)

直交行列

Page 19: Sized Linear Algebra Package のチュートリアル

その他、愉快な仲間たち

● LU 分解、コレスキー分解

● QR 分解

● 連立方程式の求解、線形最小二乗法

● ランク計算

● 行列・ベクトルのノルム

● 固有値分解(一般行列、正定値対称行列など)

● 特異値分解

Page 20: Sized Linear Algebra Package のチュートリアル

もう少し実用的な例

Page 21: Sized Linear Algebra Package のチュートリアル

2層ニューラルネット(順伝搬、逆伝搬)

● 機械学習のモデルの1つ(重要な部分だけ紹介)

● http://qiita.com/akabe/items/b930e94543f2fa81570futop # let exec w1 w2 b1 b2 x = let y = sigmv (gemv ~trans:normal w1 x ~beta:1.0 ~y:(Vec.copy b1)) in let z = sigmv (gemv ~trans:normal w2 y ~beta:1.0 ~y:(Vec.copy b2)) in z;;val exec : ('a, 'b, 'c) mat → ('d, 'a, 'e) mat → ('a, 'f) vec → ('d, 'g) vec → ('b, 'h) vec → ('d, 'i) vec = <fun>utop # let train eta w1 w2 b1 b2 x t = let y = sigmv (gemv ~trans:normal w1 x ~beta:1.0 ~y:(Vec.copy b1)) in let z = sigmv (gemv ~trans:normal w2 y ~beta:1.0 ~y:(Vec.copy b2)) in let delta2 = Vec.mul (Vec.sub z t) (sigmdv z) in let delta1 = Vec.mul (gemv ~trans:trans w2 delta2) (sigmdv y) in ignore (ger ~alpha:(~-. eta) delta2 y w2); ignore (ger ~alpha:(~-. eta) delta1 x w1); axpy ~alpha:(~-. eta) b2 ~x:delta2; axpy ~alpha:(~-. eta) b1 ~x:delta1;;

順伝搬(予測)

逆伝搬(学習)

Page 22: Sized Linear Algebra Package のチュートリアル

準ニュートン法 (Quasi-Newton method)● 最適化問題の数値解法の1つ(重要な部分だけ紹介)

● http://akabe.github.io/slap/demo-gradopt.htmlutop # let update_h ?up h y s = let rho = 1. /. dot y s in let hy = symv ?up h y in ignore (ger ~alpha:(~-. rho) hy s h); (* h := h - rho * hy * s^T *) ignore (ger ~alpha:(~-. rho) s hy h); (* h := h - rho * s * hy^T *) ignore (syr ?up ~alpha:((1. +. dot y hy *. rho) *. rho) s h);;val update_h : ?up:bool → ('a, 'a, 'b) mat → ('a, 'c) vec → ('a, 'd) vec → unitutop # let quasi_newton ~loops df f x0 = let h = Mat.identity (Vec.dim x0) in (* an approximated inverse Hessian *) let rec aux i x df_dx = if i <= loops then begin let s = symv ~alpha:(-1.) h df_dx in (* search direction *) scal (wolfe_search df f s x) s; let x' = Vec.add x s in let df_dx' = df x' in let y = Vec.sub df_dx' df_dx in if dot y s > 1e-9 then begin update_h h y s; aux (i + 1) x' df_dx' end end in aux 1 x0 (df x0);;

Page 23: Sized Linear Algebra Package のチュートリアル

まとめ

● 結論「SLAP 使ってほしいなぁ〜」

今日の内容:

● 幾つかの関数の使い方を説明

○ 他の関数は http://akabe.github.io/slap を参照してください

● ファイルから読み込んだベクトルでも静的サイズ検査できる

● ちょっと複雑な線形代数のプログラムを紹介した

○ でも、型注釈は書いてない

○ 行列のサイズは自動的に型推論される