トップ 最新 追記

日々の流転


2013-12-03 [長年日記]

λ. 自動微分でロジスティック回帰

自動微分を使って線形回帰をしてみる」と「nonlinear-optimizationパッケージで遊ぶ」で線形回帰をして遊んでみたので、次は予定通り自動微分でロジスティック回帰を試してみることに。 例として何を使おうか悩んでいたのだけれど、たまたま ロジスティック回帰で分類を試す - Negative/Positive Thinking (2013-11-29) という記事を(@chezouさんのtweetで)見かけたので、これと同じデータで試してみることにした。

使用するデータ

というわけで、使用するデータはこれ。

コード

実装にはnonlinear-optimizationパッケージを、自動微分を行うadパッケージと組み合わせて便利に使うための、拙作のnonlinear-optimization-adパッケージを使用。

コスト関数としては Courseraの Machine Learning のコースで扱った形の、正則化なしのコスト関数と、L2正則化を行うコスト関数の場合の両方を試す。

import Control.Monad
import Data.Map (Map)
import qualified Data.Map as Map
import Data.Set (Set)
import qualified Data.Set as Set
import qualified Numeric.Optimization.Algorithms.HagerZhang05.AD as CG
import Text.Printf

main :: IO ()
main = do
  trainingData <- liftM parse $ readFile "a9a"
  testData     <- liftM parse $ readFile "a9a.t"

  let features :: Set String
      features = Set.unions [Map.keysSet fs | (_, fs) <- trainingData]

      cost, costReg :: RealFloat a => Map String a -> a
      cost theta    = sum [ if y then - log p else - log (1 - p)
                          | (y,x) <- trainingData, let p = h theta (fmap realToFrac x) ]
                      / fromIntegral (length trainingData)
      costReg theta = cost theta + (lambda / (2 * fromIntegral (length trainingData))) * sum [x**2 | (feat,x) <- Map.toList theta, feat/=""]

      params = CG.defaultParameters
               { CG.printFinal  = True
               , CG.printParams = True
               , CG.verbose     = CG.Verbose
               , CG.maxItersFac = 50 / fromIntegral (1 + Set.size features)
               }
      grad_tol = 0.00001
      theta0 = Map.fromAscList [(feat,0) | feat <- Set.toAscList (Set.insert "" features)]

  (theta1, _result1, _stat1) <- CG.optimize params grad_tol theta0 cost
  (theta2, _result2, _stat2) <- CG.optimize params grad_tol theta0 costReg

  forM_ [("without regularization", theta1), ("with regularization", theta2)] $ \(s, theta) -> do
    printf "[%s]\n" s
    forM_ [("training set", trainingData), ("test set", testData)] $ \(name, samples) -> do
      let correct  = filter (\(y,x) -> predict theta x == y) samples
          accuracy :: Double
          accuracy = fromIntegral (length correct) / fromIntegral (length samples)
      printf "  %s accuracy: %d/%d = %f %%\n" name (length correct) (length samples) (100*accuracy)

-- regularization parameter
lambda :: Num a => a
lambda = 1

-- hypothesis
h :: RealFloat a => Map String a -> (Map String a -> a)
h theta x = sigmoid $ sum [(theta Map.! feat) * val | (feat, val) <- ("", 1) : Map.toList x]

predict :: Map String Double -> (Map String Double -> Bool)
predict theta x = h theta x > 0.5

sigmoid :: RealFloat a => a -> a
sigmoid x = 1 / (1 + exp (-x))

parse :: String -> [(Bool, Map String Double)]
parse = map f . lines
  where
    f l = (readInt w > 0, Map.fromList [(name, read val) | s <- ws, let (name,_:val) = break (':'==) s])
      where
        (w:ws) = words l
        readInt :: String -> Int
        readInt ('+':s) = read s
        readInt s = read s

ちょっと試してみたところなかなか収束しなかったので、参照したブログと同じくイテレーション回数50回で打ち切ることに。これは、nonlinear-optimizationパッケージのoptimize関数は、イテレーション回数の指定がパラメータ数に対する倍率になっていて、ちょっと面倒だった。

結果

結果は以下のとおりで、参照したブログの数字ともほぼ一緒だし、まあこんなものだろう。

[without regularization]
  training set accuracy: 27644/32561 = 84.89911243512176 %
  test set accuracy: 13846/16281 = 85.04391622136232 %
[with regularization]
  training set accuracy: 27648/32561 = 84.91139707011456 %
  test set accuracy: 13850/16281 = 85.06848473680978 %

2013-12-31 [長年日記]

λ. 2013年振り返り

2014年を迎えるにあたって、2013年を簡単に振り返ってみる。

月毎の主なイベント

1月
Coursera での学習を開始。昨年末に買ったNexus7で初めてのAndroid経験&初代iPadから乗り換え。
2月
スキーで転けて靭帯損傷。
3月
『型システム入門 プログラミング言語と型の理論』出版と出版記念トークイベントMax-SAT Evaluation 2013 に参加。
4月
特になし
5月
Haskellで計算機代数勉強会を開催。Google Code Jam 2013 は去年に引き続いて今年も体調的に微妙で微妙。
6月
某自社の株主総会見てきた。
7月
スカイツリー昇った。ICSE'13勉強会でT芝チームとして発表。 奥歯抜歯Coursera MeetUp Tokyo に参加。
8月
ICFP Contest 2013 に例によって Team Sampou で参加。引越しと一人暮らし開始。SPLC2013の併設ワークショップFMSPLE 2013で発表。
9月
ウサギと同居開始。
10月
結婚(といっても婚姻届を出しただけで、結婚式はまだ)
11月
電機連合第34回技術者フォーラムに参加。2013川崎国際多摩川マラソンに参加。
12月
川崎グランシティモール実証実験開始

Coursera

前から少し気になっていたCourseraを1月に試してみて、最終的に以下の9コースを履修。

  1. Computing for Data Analysis by Roger D. Peng @ Johns Hopkins University
  2. Data Analysis by Jeff Leek @ Johns Hopkins University
  3. Linear and Discrete Optimization by Friedrich Eisenbrand @ École Polytechnique Fédérale de Lausanne
  4. Machine Learning by Andrew Ng @ Stanford University
  5. Developing Innovative Ideas for New Companies: The First Step in Entrepreneurship by James V. Green @ University of Maryland, College Park
  6. Model Thinking by Scott E. Page @ University of Michigan
  7. Maps and the Geospatial Revolution by Anthony C. Robinson @ The Pennsylvania State University
  8. Introduction to Computational Finance and Financial Econometrics by Eric Zivot @ University of Washington
  9. Introduction to Recommender Systems by Joseph A Konstan and Michael D Ekstrand @ University of Minnesota

自分のスキルのポートフォリオに追加したいと考えたものを中心に、それなりに戦略的に学習してみたつもり。上手くいった部分もあればそうでない部分もあるけれど。自分はデータ分析や統計に関しては大学1年のときに、ほぼ必修の位置づけだった「データ分析」の授業を途中で飽きて切ってしまってから、ほとんど学習しないままになってしまっていたので、その辺りを補完できたのは良かった。

そして、7月にCoursera MeetUp Tokyoに参加したところ、その縁で、メディアで取り上げらることになったのは、なかなか貴重な体験だった。

ルポ MOOC革命――無料オンライン授業の衝撃(金成 隆一)

新しいプログラミング言語、環境

「毎年少なくとも一つの言語を学習する」という話があるけれど、今年は Coursera のコースで割と色々な言語を学べた。 Computing for Data AnalysisData AnalysisIntroduction to Recommender Systems では R を、Linear and Discrete Optimization ではPython (とSymPy)を、Machine Learningでは MATLAB/Octave に触れることができた。その後、そのうちのRとPythonは仕事でもそれなりに使うようになったので、結構役立っている。

それから、言語というほどではないけれど、Model Thinking では NetLogo に、Maps and the Geospatial Revolution では ArcGIS Online に触った。 あと、Introduction to Recommender Systems で使った LensKit は、アノテーションなどを活用したJavaの今風なDIを使ってて、ちょっとおぉと思ったりなんかもした。

『型システム入門 プログラミング言語と型の理論』出版

Benjamin C. Pierce の Types and Programming Languages (TAPL) の訳書『型システム入門 プログラミング言語と型の理論』を出版。前回のAlloy本こと『抽象によるソフトウェア設計−Alloyではじめる形式手法』が終わり、2011年9月からTAPL翻訳が本格始動したのだけれど、それから1年半ほどかかって、ついに出版にこぎ着いたのがこの3月で、非常に感慨深かった。また、共訳者、監訳者、編集者、レビュワー、皆素晴らしい人達ばかりで一緒に仕事をできて光栄だった。出版記念トークイベントという珍しい体験もしてしまったし。

型システム入門 −プログラミング言語と型の理論−(Benjamin C. Pierce/住井 英二郎/遠藤 侑介/酒井 政裕/今井 敬吾/黒木 裕介/今井 宜洋/才川 隆文/今井 健男) Types and Programming Languages(Benjamin C. Pierce)

靭帯損傷

2月にスキーで転けて靭帯損傷。内側側副靭帯損傷の2度で、MRIを初体験したり、しばらくギプス(正確にはギプスシーネ)と松葉杖で不便な生活をしたり、さらに結構な間リハビリをしたりとか。 ギブスしてると、立ってても座っててもバランスが悪くて、体中凝って仕方なかったのが辛かった。 後、しばらくギプスとサポーターをしてるだけで、関節って本当に曲がらなくなるんだなぁ。リハビリしてだんだん動くようになって、人間の関節や筋肉って本当によくできてるなぁと思った。 大変な体験だったけれど、周囲からは非常によくしてくれたし、結構学ぶことのあった体験だったと思う。

ランニング

ランニングは500kmの目標を立てていたけど、途中怪我で数ヶ月走れなかったこともあって、320kmほどに留まった。でも、我ながらよく続いたなぁと思うし、自分を誉めてあげたい。 また、大会に参加するという目標は2013川崎国際多摩川マラソンに参加するという形で達成。 目標がハーフマラソンだったのに対して8kmになってしまったので、ハーフマラソンを走るのは2014年の目標に持ち越し。

あと、昨年末にちゃんとしたランニングシューズを買ったけれど、今年は心拍計 Wahoo Blue HR とか、活動量計 Misfit Shine とか、ランニング用のスポーツタイツのCW-Xとか色々と買ってしまった。

お仕事

Courseraで学んだデータ分析・機械学習系の知識を活かして、これまでとちょっと違った方面の仕事に挑戦してみた1年で、川崎グランシティモール実証実験 なんかにも関われて、まだまだこれからだけれど、面白い仕事ができた。

その他にはFMSPLEで発表したりとか。

計算機代数

代数的実数や量化子除去に関して勉強したり簡単な実装をしたりしていたので、思いきって Haskellで計算機代数勉強会という勉強会をゴールデンウィークに開催。結構マニアックなトピックにも関わらず参加者20人以上も集まり、なかなか楽しかった。 その後も、Berlekamp-Zassenhaus アルゴリズムを理解して実装したりとちょっとは進めた。あと、これまでなんとなくしか理解できていなかった sugar flavor とか syzygy とかについて、計算機代数勉強会での@mr_konnさんの発表で理解できて、自分でも実装してみようと思っていたけれど、これは実装しないままになってしまったなぁ……

Max-SAT Evaluation 2013

昨年は Pseudo Boolean Competition 2012 に参加したが、今年は開催されなかったので、代わりに Max-SAT Evaluation 2013 に参加。 今回は自分のtoysatに加えて、GLPKSCIP に簡単なフロントエンドを付けたもので参加。

自作のtoysatの方は、昨年の Pseudo-Boolean Competition 2012 ではそれなりに健闘した(と思ってる)けれど、今回はあまり振るわなかったねぇ。 まあ、色々とやりたいことはあったけれど、結局、目的関数値の線形探索ベースの単純なアルゴリズムのやつで投稿してしまったからなぁ……

SCIPの方は、SCIP本体のバグが見つかって、SCIP開発者に報告・修正してもらったものを再投稿させてもらったりと、意外と大変だったけれど、その甲斐もあって Partial Max-SAT 部門の Crafted ベンチマークで2位に入賞して嬉しかった。(別にフロントエンドを書いただけの自分がすごい訳ではないのだけれど)

英語

英語は今年はあんまり頑張れなかった。 Courseraでは英語を使って学習してはいたし、日本開催の国際会議SPLC2013の併設ワークショップFMSPLE 2013で発表はしたものの、海外には一回も行かなかったし。それに、レアジョブも後半は殆どやらなくなってしまったしなぁ。2014年はその辺りもっと頑張りたいところ。

関連エントリ