JupyterCon 振り返り勉強会に参加してきた
先週 JupyterCon 振り返り勉強会 に参加した時のメモ.個人的には知らないキーワードも色々と拾えてとても参考になりました. 殴り書きで全然整理してないけど,放っておくとメモを無くしそうなのでブログに上げておこうと思います.
JupyterCon 2017 概括
JupyterLab
- 2017年中にβリリース
- 開発者向けのAPI整理はβ〜1.0にかけて行われる
- エンドユーザー的にはUIが変わっただけっぽく見えるけど, 内部で使われているウェブ技術がごっそり入れ替わって,時代についていけるようになったらしい
JupyterHub
- Jupyter Notebookをspawnしてマルチユーザー対応したもの
- JupyterLabをspawnするようなトピックはなかった → jupyterlab-hubというOSSあるらしい
- セキュリティ確保,認証機構などはこれから.5〜6人の組織ではめっちゃ使える
- Dockerのイメージもあるよ (環境構築不要!)
Reproducibility, Collaboration
- FAIRの原則が守られているか
- Findable, Accessible, Interoperable(共通仕様に従う.オレオレ仕様の排除), Reusable
- Jupyterで論文を書く時代?
- Apache Arrowは要ウォッチ.インメモリデータでシステムが繋がる時代
Pandas, Binder, GeoNotebook, IPySigma 作者の発表
- https://conferences.oreilly.com/jupyter/jup-ny/public/schedule/proceedings
- https://qiita.com/kozo2/items/49bbc217e2a771df320e
Data science without borders
- https://conferences.oreilly.com/jupyter/jup-ny/public/schedule/detail/59937
- PandasのCreator,Wesの資料 (ゲストスピーカー)
- SILO: コラボレーションできない要因となっているもの
- Shared DataFrame Runtime => Pandas
- Portable Data Science => Apache Arrow
Making science happen faster
- Jeremy Freeman (Chan Zuckerberg Initiative)
- Binder (DockerからJupyter環境を提供するサービス) の作者のひとり
- ある一定期間だけ使える使い捨ての環境ができる
- 例えば論文で言及されたソフトウェアが再現できるか,などの用途など
ちなみにBinderについて
- Dockfileを最初に見に行く.なければpipのrequirements.txtを見に行く
- ちなみにBinderのサービスのコアはBinderHubがベース
- https://github.com/jupyterhub/binderhub
- repo2dockerとJupyterHubの組み合わせか?
- repo2dockerでDockerイメージを生成し,JupyterHubでNotebook管理
GeoNotebook: An extension to the Jupyter Notebook for exploratory geospatial analysis
Beautiful networks and network analytics made simpler with Jupyter
- https://conferences.oreilly.com/jupyter/jup-ny/public/schedule/detail/59874
- グラフの可視化ライブラリ
- Binderにかけて見たけど動かなかった...
懇談会的な雑談でのキーワード
CourseraのMachine Learningコースを修了した
SICPを読み終えてからやると決めていた機械学習の勉強について、 まずはAndrew Ng先生のCoursera Machine Learningのコースを修了しました。 コースの途中、Pokemon GOにハマって危なかったけれど何とかクリア!
コースの内容
全11週に渡って講義と課題がみっちりとあります。 僕の場合、2016年5月末から受講して8月15日に修了しました。
最終的なデッドラインはジャスト12週で設定されているので、 うまく時間を取って課題をこなさないと修了できないようになっています。
コンテンツ
- Lecture Videos and Texts
- Quiz & Programming Assignments
- Course Wiki
- 週ごとに要点がまとめてある。Octave Tutorialが便利
- Discussion Forums
- 質問するとMentorがフォローしてくれるみたい
- 個人的にはOctaveのコードが動かない時にちょっと覗いたくらいであまり使わなかった
講義のビデオは日本語の字幕が付いているけど、 課題は英語オンリーなので、ビデオの内容はしっかりとノートにとりました。 (でないと課題の英語解読で相当辛くなる..)
それとCourseraのスマートフォンアプリがあって、 講義ビデオはアプリ内にダウンロードできるので、 通勤電車の中でビデオを消化して、 課題は週末に取り組むといったルーチンで進めました。
主な内容
前述の通り全11週に渡って行うだけあってボリュームたっぷりです。
初学者向けのコースのため古典的な手法が多いですが、 機械学習の基礎的な考え方がじっくり学べてとてもよかったと思います。
- Introduction (week 1)
- Supervised/Unsupervised LearningやRegression/Classificationの違いなど
- Linear Algebra Review (week 1)
- Linear Regression (week 1-2)
- 1週目はー変量、2週目は多変量の線形回帰。勾配法と正規方程式について
- Octave/MATLAB Tutorial (week 2)
- Logistic Regression (week 3)
- ロジスティック回帰による分類問題について
- Neural Networks (week 4-5)
- BPのモデリングと学習、手書き数字識別への応用
- Evaluating a Learning Algorithm, Bias vs. Variance (week 6)
- Support Vector Machines (week 7)
- SVMsのアルゴリズムと分類問題への適用
- K-Means (week 8)
- 教師なし学習の例としてK-Meansによる分類問題
- Principal Component Analysis (week 8)
- 特徴量の次元圧縮・復元やvisualizationへの応用
- Anomaly Detection (week 9)
- 一変量および多変量正規分布による異常検定
- Collaborative Filtering (week 9)
- 協調フィルタリングによる推薦システムの構築
- Large Scale Machine Learning (week 10)
- 確率的勾配法やオンライン学習、Map-Reduce的な分散システムについて
- Photo OCR (week 11)
- 画像中の文字認識を例に、 機械学習システムのパイプライン構築やリソース配分の考え方について
具体的な内容は以下が詳しいです。
修了証
$79でCourseraからデジタルのCertificateが発行されます。
少々値が張りますが、コースの内容がとてもよかったので
Andrew先生やCourseraへの感謝の意味も込めて購入しました。
($79で書籍を買ってもこの内容を勉強しようと思ったら11週じゃ絶対無理!)
Pythonでの復習レーン
コースは修了したものの急ピッチかつプログラミング課題も穴埋めだったため、 消化不良というかスクラッチで機械学習の実装できそうな感がないです。
そこでPythonを使った復習レーンを進めていますが、 これがとても楽しくてハマってます!Pythonすばらしすぎる!
https://github.com/uents/coursera-ml
こちらもおいおいブログでまとめて行きたいと思います。
計算機プログラムの構造と解釈(SICP)を読み終えて
SICPようやく読み終わりました。
2014年5月から読み始めたので、 足かけ丸2年。愛娘も1才から3才に成長。
練習問題やブログの記事を上げていたGitHubのコミットグラフを見ると、 サボっていた期間も結構あり、実働は1年ちょっとくらいかな。
他のSICPブログを見ると、ほぼ全問解きながら3.5ヶ月や 6ヶ月で読み終えた方もいるようなので、決してペースは早くもないし、 練習問題も特に§5の後半は全然解けていないですが、 社会人で仕事・家事・育児をこなしつつ、通勤時間・深夜・たまの有休を 使っての活動だったので、結構頑張ったかなという感はあります。
SICPで学んだこと
過去の記事を見返しながら列挙してみました。◎,△は僕の理解度です。
- ◎ 変数の束縛と代入の違い、環境との関係を理解した
- ◎ 関数がファーストクラスである言語の実装の考え方を理解した
- ◎ 再帰呼び出しや高階関数が自然と使えるようになった。末尾再帰を意識するようになった
- ◎ 関数適用や評価の順序を意識しながら実装できるようなった
- ◎ データ主導やメッセージパッシングの戦略の違い理解した
- ◎ 型変換の動機と過程を理解した
- ◎ 局所状態とクロージャによる抽象化の構築を理解した
- ◎ ストリームと遅延評価を理解した
- △ 字句解析、構文解析を実装できるようになった (BNFコンバータまでは使ってないので△)
- ◎ Schemeインタプリタをフルスクラッチで実装した
- ◎ 継続や非決定性計算の概念を理解できた
- △ レジスタマシンで動作するインタプリタ、コンパイラの構造を理解した (練習問題を解いていないので△)
さらに発展的なものとして、
- 万能機械の概念を知り、ユーザープログラムであれ処理系であれ 解くことのできる問題もそうでない問題も同じ、というメタな視点が得られた
- プログラムはある意味全て処理系、という考え方に至るようになった
副次的なものとして、
- 社会人での継続学習、ブログを書く習慣が定着した
- GitやGitHubが使えるようになった
- わからなくても書いて動かせば道は開ける、と思えるようになった。 まずは手を動かすことが大事!
ざっとあげてこんなところかな。
読み始めの頃といまの比較
読み始めた頃の自分といまの自分を比較してみました。
読み始めたころの自分 | いまの自分 |
---|---|
関数型言語を習得したい | SICPは関数型言語を習得する本ではないが、 高階関数やクロージャあたりは自然と使えるようになり、めちゃめちゃ楽しい! |
情報工学へのコンプレックス | インタプリタ、コンパイラの学習を通して、全く無くなりました! |
単なる力試しがしたい | 学生の頃の自分と今の自分は全く別。 自分自身でも成長が感じられた! |
プロブラマーとしてもっと飛躍したい | 2年前とは全く違う景色は見えている気がする (これはこれからのお楽しみ!) |
まとめ
長い時間はかかりましたが、間違えなくその価値はあったと断言できます。
やはりSICPは計算機科学の入門書でした。 こうして読み終えたいま、改めて学生時代に読んでおくべきだったと感じてます。 (大学時代のボスに言われたことは正しかった..)
それでも、得たものを大きさをこうやってまとめると、 社会人である程度のキャリアを積んだいまでも、読み切ることができて良かったです。
最後に、RacketやGaucheのような素晴らしい処理系、 ウェブで公開されている原文、和田先生やその他有志の方の翻訳版、 練習問題の回答など今ではとっかかりがたくさんあるし、 昔に比べてSICPの敷居はずいぶん下がったように思います。
これらが無ければ絶対に完走することはできなかったでしょう。 先人のみなさま方、ほんとうにありがとうございました。
SICP 読書ノート#79 - 5.5 翻訳系(4) (pp.362-366)
いよいよ最後のセクション。練習問題はやってないです。
5.5.7 翻訳したコードと評価器のインターフェース
(compile)
でコンパイルしたコードを積極制御評価器で動作させる。
いつものように、まずはRacketで動かせるようにした。
https://github.com/uents/sicp/tree/master/ch5.5.7-interfacing-compiler-to-evaluator
評価器のトレースを有効にして、かんたんな手続きをコンパイルしてみる。
eceval-compiler.scm<feff>> (eceval 'trace-on) eceval-compiler.scm<feff>> (compile-and-go '(define (add1 x) (+ x 1))) '(label = controller) '(inst = (assign compapp (label compound-apply))) '(inst = (branch (label external-entry))) '(label = external-entry) '(inst = (perform (op initialize-stack))) '(inst = (assign env (op get-global-environment))) '(inst = (assign continue (label print-result))) '(inst = (goto (reg val))) '(inst = (assign val (op make-compiled-procedure) (label entry1) (reg env))) '(inst = (goto (label after-lambda2))) '(label = after-lambda2) '(inst = (perform (op define-variable!) (const add1) (reg val) (reg env))) '(inst = (assign val (const ok))) '(inst = (goto (reg continue))) '(label = print-result) '(inst = (perform (op print-stack-statistics))) '(total-pushes = 0 max-depth = 0 curr-depth = 0) '(inst = (perform (op announce-output) (const ";;; EC-Eval value:"))) ;;; EC-Eval value: '(inst = (perform (op user-print) (reg val))) ok ;; (snip ...)
(assign val (op make-compiled-procedure) (label entry1) (reg env)))
で 戻り先はentry1
となるよう手続きをコンパイルし、その実体をval
に格納(perform (op define-variable!) (const add1) (reg val) (reg env)))
で コンパイル済みの手続きをadd1
という変数に束縛val
に'ok
を格納してREPLに戻る
といった流れ。
次に、コンパイル済みの手続きを実行してみる。
出だしの処理はこれまで見てきた内容と同じなので詳細は割愛するが、
ev-application
以降の処理で
proc
とargl
に手続きと引数が格納され、apply-dispatch
へジャンプする
;;; EC-Eval input: (add1 5) '(inst = (assign env (op get-global-environment))) '(inst = (assign continue (label print-result))) '(inst = (goto (label eval-dispatch))) '(label = eval-dispatch) ;; (snip ...) '(label = ev-appl-accum-last-arg) '(inst = (restore argl)) '(inst = (assign argl (op adjoin-arg) (reg val) (reg argl))) '(inst = (restore proc)) '(inst = (goto (label apply-dispatch)))
apply-dispatch
からこのセクションで追加したcompiled-apply
へジャンプ。
さらに先程のentry1
へとジャンプする。
'(label = apply-dispatch) '(inst = (test (op primitive-procedure?) (reg proc))) '(inst = (branch (label primitive-apply))) '(inst = (test (op compound-procedure?) (reg proc))) '(inst = (branch (label compound-apply))) '(inst = (test (op compiled-procedure?) (reg proc))) '(inst = (branch (label compiled-apply))) '(label = compiled-apply) '(inst = (restore continue)) '(inst = (assign val (op compiled-procedure-entry) (reg proc))) '(inst = (goto (reg val))) ;;=> ここで`entry1`へジャンプ
すでにproc
にはコンパイル済みの手続き
(この場合はCompound Procedureのような複合手続き)が格納されているため、
それに対してargl
の非演算子を適用する。
返り値はval
に格納され、REPLへと戻る。
'(label = entry1) '(inst = (assign env (op compiled-procedure-env) (reg proc))) '(inst = (assign env (op extend-environment) (const (x)) (reg argl) (reg env))) '(inst = (assign proc (op lookup-variable-value) (const +) (reg env))) '(inst = (assign val (const 1))) '(inst = (assign argl (op list) (reg val))) '(inst = (assign val (op lookup-variable-value) (const x) (reg env))) '(inst = (assign argl (op cons) (reg val) (reg argl))) '(inst = (test (op primitive-procedure?) (reg proc))) '(inst = (branch (label primitive-branch3))) '(label = primitive-branch3) '(inst = (assign val (op apply-primitive-procedure) (reg proc) (reg argl))) '(inst = (goto (reg continue))) '(label = print-result) '(inst = (perform (op print-stack-statistics))) '(total-pushes = 5 max-depth = 3 curr-depth = 0) '(inst = (perform (op announce-output) (const ";;; EC-Eval value:"))) ;;; EC-Eval value: '(inst = (perform (op user-print) (reg val))) 6 ;; (snip ...)
細かくは理解できていないけど、target
とlinkage
をうまく使うことで、
積極制御評価器とコンパイル済みコードを繋ぐことができる。
解釈と翻訳
まとめるとこんな感じでしょうか。
解釈系と翻訳系の利点の違い
異なるマシンアーキテクチャへの言語の移植戦略
§4の超循環評価器から§5かけて、処理系の中へ中へと入っていくと、 様々な観点でインタプリタとコンパイラの本質が浮き彫りになって理解が深まる。
というわけで、やっと読み終わりました。最後にまとめたいと思います。
SICP 読書ノート#78 - 5.5 翻訳系(3) (pp.360-362)
今回は「5.5.6 文面アドレス」から。
5.5.6 文面アドレス
「文面」とはlexicalの直訳のよう。
これまでの評価機は変数の値を探す際に、実行時にenv
フレームを
都度探索していたので、それなりに計算コストがかかっていたはず。
Schemeはレキシカルスコープなので、コンパイル時にアドレッシングを済ませといて コンパイル時環境(compile-time environment)として管理できれば、 実行時の変数探索のための計算コストを省けて、最適化できるのでは? というお話だと思う。
で、練習問題を解こうと思ったけど、手元のソースコードでは 環境フレームを以下のようにRacketのHash Tableで作り変えていたため、 そのままではアドレッシングの実装ができない。
(define (make-frame vars vals) (let ((frame (make-hash))) (map (lambda (var val) (hash-set! frame var val)) vars vals) frame)) (define (extend-environment vars vals env) (with-handlers ([exn:fail? (lambda (exn) (error "extend-environment: arguments error:" vars vals))]) (cons (make-frame vars vals) env))) ;; ...
環境フレームの実装をSICPのテキスト通りに戻すと
set-car!
、set-cdr!
を使う必要が出てくるので、
R5RSモードに切り替えてmutable pairsを使えるようにしたが、
今度はレジスタ計算機シミュレータの方に影響が出てうまく動かない。
RacketでSICPをやるとやっぱここがいちばん辛いな、と改めて思う。
最初から全部 #lang r5rs
でやれば良かったのかもしれない。
http://docs.racket-lang.org/r5rs/r5rs-mod.html
これ以上頑張って直す元気もないので、あきらめて次に進みます。残念..