macOSでoptionキーをメタキーとして使う

今までエディタを自分オリジナルにカスタマイズするとき、各エディタごとにoptionキーに役割を当ててたりしたのだが、ターミナルの環境設定のところからoptionキーをメタキーに割り当てるという設定を発見した。

f:id:komi1230:20200129133826p:plain
画像の右下の部分

今までエディタはずっとEmacsを使っていたのだけれど、最近ちょっとLemが気になってきて前に少し触ってみた。

キーバインドEmacsライクなのでCtrlキーが命なのだけれど、Ctrlキーはちゃんと動く。

しかしOptionキーをメタキーに割り当てる方法を色々ググっていたのだけれど、LemのIssueには上がっていなくて、なので諦めていた。

今回optionキーをメタキーに当てる方法が見つかったのでこれからLemを使ってみようと思う。

Common LispでHTMLファイルをブラウザで見る

なんかバタバタしてて久しぶりな更新な気がする。

前にはブラウザを立ち上げる方法について簡単に調べたのだけど、結局Pythonで確認しただけでCommon Lispでどうなってるのかについては試してなかった。

komi.hatenadiary.com

で、このあと色々試したのだけど、どうやら色々勘違いをしていたというか、もっと根本的に掘り下げる必要があったのが発覚した。

というのも、基本的にコードからHTMLファイルをブラウザで開くような操作をするにはUnixコマンドのopenコマンドを直接叩くというのが主流らしい。

これの裏付けとして、Pythonの言語側のWeb Browser Driverの実装を眺めているとしっかりopenコマンドを叩きにいってる。

github.com

他にもJuliaとかもそんな具合だった。

さて、前回の記事でcl-selenium-webdriverがいい感じかもしれないというような言及をしたが、これについては半分正解で半分間違いという具合。

github.com

このライブラリのうまみは何かというと、ブラウザを開くという所作ではなくコードから直接HTTP通信ができるという点らしい。

それの副次的な作用がブラウザを開くという帰結であり、今回自分はローカルに置いたHTMLファイルを開くことさえできれば良いので、まあ言ってしまえばオーバーキル感があるのである。

方針は決まった

以上、色々と試行錯誤したが、結局のところローカルにあるHTMLファイルをブラウザで開くにはCommon LispソースコードからUnixコマンドを叩きさえすればいい。

(defun system (cmd-str)
  (trivial-shell:shell-command cmd-str))

(defun open-browser ()
  (let ((path-to-html (check-file-exist "index.html")))
    #+darwin
    (system (format nil "open ~A" path-to-html))
    #+linux
    (system (format nil "xdg-open ~A" path-to-html))
    #+win32
    (system (format nil "start ~A" path-to-html))))

Unixコマンドへのアクセスは処理系依存なところがあり、これをここで細かく書いてると色々ゴチャゴチャしてきて本来やりたいことできなくなってしまうので、Common LispソースコードからUnixコマンドへのアクセスに関してはtrivial-shellを利用した。

ちなみにこのコードはいつぞや立ち上げたプロジェクトであるKaiの一部切り出し。

github.com

Kaiの現在の進捗

12月に始めたKaiプロジェクトであるが、現在のところコード自体については遅々ながらも徐々に進んでいる。

もともとバックエンドにはOpenGLを採用していたのだが、使っていたライブラリがバージョンが弱いやつだったのか知らないがあまり描画能力が高く、フォントも汚かったので、このままでは将来性が無いということでバックエンドを別に切り替えることにした。

バックエンドの選定にはJuliaのPlotsを参考にし、PlotlyとGRの2つにすることにしている。

本心としてはPyplotが使いたいところだったのだけれど、実装を眺めてみるとどの言語からも触れるようなAPIが提供されているわけではなくC言語からゴリゴリにPythonのラッパーを書いていて、Common Lispに移植するのは簡単ではなさそうだったのでまた来世ということに。

Plotlyは描画媒体がブラウザということもあって、Common LispからPlotlyを触るにはJavaScriptのコードへ変換するようなマクロを提供するだけで解決する。

で、そんなわけでKaiを作り続けているのだけど、現在の進捗としてはJavaScriptへの変換マクロさえ書いてしまえばKaiのPlotlyをバックエンドとしたバージョンは完成という状況となっている。

Plotlyを利用する際のフローとして、

  1. ホームディレクトリの~/.cache/にKaiのディレクトリを切る
  2. ダウンロードクライアントを用いてPlotlyのjsファイルを取ってくる
  3. Common LispからPlotlyのためのJavaScriptコードを生成
  4. index.htmlを生成
  5. HTMLファイルをブラウザで開く

という形式をとっている。

で、真ん中のJavaScriptのコードジェネレータ以外は完成しているという具合。

すぐに残りの文を完成させたいのだけど、その前準備として今はPlotlyのAPIを眺めながらどういう風に実装するのが良いか悩んでいる。

さっさと仕上げてデモを公開したいところ。

これからもがんばるぞい。

『ベイズ深層学習』が最高すぎた

今回は書評エントリー。

ちょうど今日の午前中に須山さんの『ベイズ深層学習』を読み終えた。

ものすごく良かったのでここで全力で宣伝しようと思う。

概要

本書はベイズ統計と深層学習の組み合わせについて詳説した一冊で、頻度論に基づく線形回帰と確率分布の基礎の解説から始まり、そこから線形回帰やニューラルネットワークベイズ的にどのように説明できるかについて展開、そこから深層学習のベイズ的な説明をしてガウス過程へとたどり着く構成となっている。

本書の魅力はなんといってもそのボリュームにある。

本来であればこのレベルのコンテンツは3, 4冊に分かれていてもおかしくない量と濃さであるにも関わらず、これらの内容を簡潔に解説して1冊にまとまっている。

帯の「欲張り本」という表現は非常に的を射ていると思う。

ただ、この本のすごいところは、解説の丁寧さとわかりやすさにある。

数式を用いて厳密な説明をしているが、一方で非常にわかりやすく書かれているため、疑似コード等は書かれていないものの数式と説明を読んで容易に実装のイメージがつくようになっている。

また、各アルゴリズムのわかりやすさのためにアルゴリズムを実装して可視化したグラフも豊富に用いられている。

ここまで解説を丁寧にしつつわかりやすさと内容の濃さを実現したこの一冊は、他に類を見ないと思う。

感想

だんだんと機械学習という単語が民主化してきて「AI」がバズワードとなって久しいが、それに応じてなんちゃってAI解説本が出てきて書店の棚にも怪しい本が立ち並ぶ中、このような強烈に素晴らしい本が出てきたことが非常に素晴らしいと思う。

かつて、日本語の書籍でベイズ機械学習の勉強をしようと思うのならPRMLの和訳版の一択であると個人的に考えていたが、今後はPRMLより『ベイズ深層学習』を勧めたいと思っている。

もちろんPRMLは良い本だと思うが、内容が出版されてからだいぶ時間も経っている(2006年出版)ために深層学習の周辺についてカバーし切れていないというのも事実だと思う。

その点で、PRMLよりもコンパクトに、かつ要点をしっかり押さえた上で深層学習までカバーするという意味では『ベイズ深層学習』の方が良いような気がする。

もちろん、PRMLにも良さはあって、本書がカバーし切れていない部分(時系列解析など)がある。

個人的にベイズ機械学習の導入については『ベイズ深層学習』の方が簡潔だと感じているため、今後はベイズ機械学習の勉強のロードマップでは最初に『ベイズ深層学習』を読んだあとにPRMLを読んだ方が最終的に理解度合いが深まるのではないかと思っている。

なんとなく書店で本書を手にとって読み始めたのだが、個人的にここ最近で一番の当たりだと思っているので、機械学習の勉強をこれからするという人にはぜひともオススメしたい一冊である。

コードからブラウザへジャンプする

2020年初の更新。

最近色々コード書いているのだが、ソースコードからHTMLファイルを生成してそれをブラウザで起動するというようなことをしたくなった。

経緯

Common LispのプロッターとしてKaiを作っており、OpenGLをラップしたCL-OpenGLを用いていたのだけれど、見た目は拡張性の問題からバックエンドを別のものへ移植しようと考えている。

実際のところ今のままでも開発は進められるのだけれど、少々機能が弱すぎるのとフォントが汚い、線の描画が弱すぎる、APIが使いにくい、OpenGLのバージョンが古すぎて参照できるドキュメントが死にすぎているなどの問題がある。

そこでバックエンドの移植を考えているのだけれど、移植先として今のところ考えているのはGRかPlotlyの2つ。

GRはGKS(Graphical Kernel System)とOpenGLをもとにしたグラフィックライブラリであり、重いがデスクトップ上で動き、デザインに関しては非常に良い。

PlotlyはWebGLをベースにしたグラフィックライブラリもといブラウザ上で動くプロッターであるが、これは基本的なプロット機能はすでに実装してあるのでCommon Lisp用のプロッターとして仕上げる場合はPlotlyとCommon Lispの間を繋ぐミドルウェアを作ることが目標になる。

そんなこんなでまずはPlotlyから着手しようと考え、Plotlyを動かすにはソースコードからブラウザを起動できる必要があり、そんなこんなで今回の記事に至ったわけである。

Python

環境はmacOSなのだが、Pythonでは以下のようなコードで実行ができる。

import webbrowser

# HTMLのファイルがある場所へのパス
path = "file://" + "/Users/komi/test/index.html"

webbrowser.open(path)

拡張子が.htmlの場合はブラウザが、これを.mdのようにしたらXcodeが開く。

ちなみに正式には使用するブラウザを指定してから実行する必要があるらしい。

import webbrowser

# MacOS
chrome_path = 'open -a /Applications/Google\ Chrome.app %s'

# Windows
# chrome_path = 'C:/Program Files (x86)/Google/Chrome/Application/chrome.exe %s'

# Linux
# chrome_path = '/usr/bin/google-chrome %s'

webbrowser.get(chrome_path).open(url)

Common Lisp

Common LispではCL-Selenium-WebDriverというのが存在するらしく、以下のリポジトリに従ってやればCommon Lispのコードからブラウザを叩けるらしい。

github.com

これについては未確認なので後日試してみる。

ただ、こいつに関しては最後のコミットが数年前なので少々不安なところである。

終わりに

GUIアプリの云々やグラフィックライブラリの諸々を調べていたところ、どうやら非常に混沌としているような印象を受けた。

パッと見、どのライブラリがどこまでカバーしているのか謎なのだけれど、とりあえずGRとPlotlyがある程度新しくて安心して使えそうなグラフィックライブラリだと思われる。

2020年も開発をがんばっていきたい。

京都大学理学部という自由の楽園で過ごした4年間

Kyoto University Advent Calendar 2019の24日目の記事。

世間はクリスマス一色に染まって大学の同期たちも浮き足立っている様子なのだが、自分は今日も静かに一人でパソコンの画面に向き合っている。

そんな具合でブログ更新。

もともとこの京大のアドベントカレンダーでは彼女ができないという非リアネタを爆発させつつ好きなプログラミング言語であるLispについて語るというのを予定していたのだけれど、流石にそれをやってしまうと今後の人生に強烈なタトゥーを刻み込んでしまうのと同時に全く情報系の人以外に全く伝わらないという悲劇が起きてしまうので、このアドベントカレンダーではもっと優しいネタにしようと思う。

ではどうするかというと、京大理学部という自由の楽園で過ごした4年間について語るという内容。

ネタとしては割といくらでもあったのだけれど、なぜこの内容に絞ったかというと来年からとうとう社会人になってしまうから。

大学に入学したての頃は社会人になるなんて遥か遠い先のことだろうと考えていたのだけれど、気がつけばもう4回生であと数ヶ月後には都内の一部上場企業でバリバリの社会人というところまで来ていて、大学4年間を総括するにはちょうどいい時期だし京大アドベントカレンダーという良いイベントに乗っかることで他の京大生(特に後輩)に何かしら良い影響を与えられる(悪い影響を与える可能性もある)という動機でこの内容でいくことにした。

自己紹介

恐らくこの記事を読んでる人の多くはツイッターとかなんなりで自分のことを知っているのだろうけど、ひょっとしたらこのブログで初めましてという方もいるかもしれないので簡単に自己紹介をしておこうと思う。

自分は京大理学部生物系に所属している4回生で、ツイッターはコミさん(@komi_edtr_1230)というアカウントでやっている。

コンテンツとしてはAI系とか情報系のことによく言及していて、理学部生物系という所属でありながら機械学習の人とか情報系の人という認知のされ方がよくされている。

ちなみに生物科学については全くと言っていいほど知識がないので、細胞とかタンパク質、動物の行動などの話には全く対応できない。(なぜ生物系という所属なのに生物科学についての知識がほぼゼロなのかについては後述していこうと思う)

また、定期的に目立つ行動や表現の悪い主張などをやってしまったりしていてよく炎上している人とか炎上芸人という認知も結構されている。

過去にやった(やってしまった)炎上の例として、

などがある。

ちなみにこの2つは両方とも今年の話で、自分でもびっくりするくらい燃え盛った。

名誉(不名誉)あることに後者の記事に関しては今週のはてなブログの2019年11月第1週にて第8位にランクインしてしまった。

自分はこんな感じの人間なのだけれど、京大理学部での4年間をどんな過ごし方をしたらこんな人間が爆誕したかについて振り返ってみようと思う。

(注. 京大理学部自体は非常に良い環境です。それを逆手にとった結果が自分です。)

京大理学部はどんなところか

自分の所属している京大理学部とは何なのか。

Wikipediaには非常に詳しい説明があり、引用すると

京都大学理学部(きょうとだいがくりがくぶ、英称:Faculty of Science)は、京都大学に設置される学部の一つである。(wikipediaより)

とある。

京大理学部について特筆すべきこととして色々挙げられるが、その中でも京大のあらゆる学部の中でもダントツとも言える圧倒的な自由さがある。

最近では天下の京大も文科省からの天下りで来たお役所出身のお偉いさんのおかげでいわゆる京大らしさというものが徐々に失われていっているのだけれど、京大理学部に関しては変わらず京大らしさをキープし続けている。

世間一般では京大に関する言及として

  • 変人が多い
  • めちゃくちゃ自由
  • 天才がいる

などがあるが、もはやこのイメージを形成してるのは京大理学部にあると言っても過言でもない。

同時に、京大理学部の内部の人間から見てこれらの言及は紛れもない事実である。

変人や天才に関しては今回の記事ではスコープ外になるので割愛。

履修と進級の話

例えば授業の履修の話で、他の大学や京大の他学部では必修の専門の授業があるが京大理学部の必修は1回生の時の英語の授業だけである。

もちろんこの分野の授業はn単位分取りましょうというのはあるが、どの授業を履修するかの強制が無く、好きな授業の履修ができてしまう。

これに関して、いわゆる上回生配当の授業も自由に履修することができ、1回生で4回生配当の授業を履修することも可能である。

事実、自分は1回生のときに2回生配当や3回生配当の授業を履修しまくっていた。

さて、この履修の制限が特にないことによって何が起きるかというと、理論上では2回生の前期の時点で卒業研究以外で卒業に必要な授業分の単位(約130単位)を集めることができる。

ちなみに自分は3回生の前期の時点で残り必要な単位は卒業研究だけという状況になっていて、3回生の後期は単位や留年の心配をすることなくのんびりスイスへ留学していた。

このように履修はかなり自由であるので、上記のように授業の単位を取りまくれる一方でめちゃくちゃ怠けることもできる。

聞いた話だと、昔はあまりにも自由だったせいか3人に1人が留年していたらしい。

それを見かねたせいか、現在は少人数担任制度というものが存在し、教授職が学生15人程度を担当して毎期末ごとに面談をして最近どう?的な話を聞く機会を作って学生の進路相談などを行っている。

現在はその少人数担任制度のおかげもあって現在は留年率が5人に1人にまで落ちたらしい。

そうそう、理学部の学生の所属は正式には理学部理学科で、いわゆる数学科や物理学科などの〇〇学科はなく、理学部理学科の中で数学系や物理系のような系が存在する。

これは学生は一つの分野に固執することなく分野を横断して好きなことを勉強してほしいという願いからこのような形式を取っているらしい。

なので自分の所属の正式名称は京都大学理学部理学科生物系だったりする。

この系登録は2回生から3回生になるタイミングに行われるのだが、このタイミングである程度の単位数を集めておかないと系登録が認められず留年する。

余談だが、自分の今住んでいるマンションの1階上には理学部の同期が住んでおり、彼は留年中でまだ系登録ができておらず、彼の母親は流石に現状を見かねて現在は彼と彼の母親が2人で住んでいて、たまに作りすぎた夕飯のおかずをお裾分けしてもらえる。先日もおでんをいただいた。おいしかった。

系登録は2回生から3回生になるタイミングで行われるが、系登録後は各系での演習型の授業がある。

化学系だと実験があるし生物系ではフィールドワーク、物理系では演習がある。

ちなみにこれらの演習などは履修を推奨されているが必修ではない。

お察しの通り、自分は履修していない。

研究室配属は3回生から4回生になるタイミングで行われるが、研究室配属後については単位を与えるかどうかは各教授に委ねられていて、ここらへんについては他の大学などと大して変わらないだろう。

授業の話

先述にて自分は生物系という所属であるが生物科学の知識がほぼゼロとあったが、これは主に履修していた授業が生物系以外が約半分を占めていたからである。

自分が履修したのは統計力学数値計算、データ解析、微分方程式論などで、生物系の授業についてはかなり消極的であった。

もちろん、全てが生物系以外の授業というわけではなく生物系の授業もいくつか履修していたのだが、特に授業には出席していなかった。

生物系の授業については、履修しては学期間中は別のことを勉強し、期末だけ生物系の勉強をして乗り切っていた。(あまり良いことではない)

この点について絶対に言及しておかねばならないのだが、京大理学部は授業に出席しなければならないという考え方を極端に嫌っている

というのも、形として授業に出席することよりもちゃんと学んでいるかということを重視しており、特に数学系の教授に関しては一切出欠確認をしない。

要するに期末のテストやレポートができていれば良いのである。

この件に関して、かつての伝説のシステムとして二重登録や三重登録があった。

履修登録制度がウェブ上で行われるようになるまでは履修登録は紙で行っていたのだが、(バグなのか仕様なのかわからないが)同じコマに複数の授業を履修することができ、ある授業を履修するだけして他の授業に出席し、期末にテストを受けるだけでそのコマの複数授業分の単位を取得するという荒技を行うことができたのである。

現在はできなくなってしまったのは非常に悔やまれることである。

さて、そのような具合で理学部は自由で良いところなのだが、それを上手いこと活用することで自分は今までなんとかやりくりしていた。

研究室の話

今自分がいる研究室は特にコアタイムが存在せず、月曜の午前中に1時間と水曜の午後に2時間だけ集まりがあるだけで、それ以外は基本的に自由となっている。

もちろん毎日研究室に来ることが推奨されているが、絶対ではないので自分は基本的にバイトに行っている。

自分の研究室は特に厳しい感じではなく、学部4回生についてはめちゃくちゃ緩く扱われており、その中でも学部就職組については更に緩い。

その象徴として、まず卒論が無く、期末にまとめ発表をやるだけとなっている。

他にも、研究室での発表は英語で行われるが、4回生は日本語で良い。

自分が発表する際はボスから英語でやらへんの?wと煽られるので仕方なく英語で発表しているが、留学していたおかげもあってこの点に関しては大してストレスがない。

とりあえず今の研究室はこんな具合となっている。

自由の楽園で何をしてきたか

京大理学部は上記のような具合で本当に自由な世界となっており、何をするかは本当に学生本人に委ねられている。

サークルや部活、バイト、趣味、勉強など自分の好きなことに取り組むことができる。

勉強とツイッター

さて、自分は何をしてきたかというとひたすらプログラミング関係と統計学機械学習を独学で学んでいた

大学に入学する前後でプログラミングを始め、そこから今まで一貫してひたすらプログラミング関係をやってきている。

ここで重要なのが独学というポイントである。

自分の所属は理学部であるわけだけれど、周りの人間の多くは理学(数学や物理学、地学、生物学)に興味がある一方で工学に興味がある人間は多くない。

なので工学である情報系についての勉強内容を学部の同期と共有することは特にないのである。

ではどうするかというと、ツイッターが勉強の共有相手となる。

ツイッターは入学前からやっていたのだけれど、情報系の云々を垂れ流していた結果、工学部の友達がめちゃくちゃ増えた。

現在ツイッターで繋がっていて交流のある京大の同期のほとんどが工学部(特に電電が多い)なのは自分の持っているコンテンツが今も昔も情報系だからというのが起因している。(理学部の同期は一応FF関係にあるがリプやファボのやり取りはほぼない、恐らくミュートされていると思われる)

さて、最初は京大生コミュニティをメインでやっていたツイッターだったが、勉強内容をシェアし続けていると次第に同じことを勉強している他大学の人や社会人にも繋がっていった。

自分がいわゆるAI系の勉強を始めたときはまだメディア等でAIがバズりまくる一歩手前くらいの時期で、今ほど参入してくる人が多くなかったのもあって当時では若干レアキャラみたいなところがあったと思う。

なので勉強内容の共有相手というのがそもそも多くないので、ツイッターで繋がる先が京大生コミュニティに閉じなかったのはある意味自然だったのかもしれない。

自分のやったことについて誰かから反応がもらえるとやはり嬉しいもので、そうすると更にがんばろうという気持ちになる。

ツイッターでは反応が非常に色々もらえるしフィードバックや強い人からのアドバイスやブーメランをたくさんもらえるので勉強が更に捗るのである。

この点については自分が尊敬しているTJOさん(@TJO_datasci)が言う炎上ラーニングに近しい何かなのかもしれない。

このような具合で形成されていったのが今のアカウントなのだが、現在自分の見ているタイムラインは

  • 社会人エンジニア、データサイエンティスト (50%)
  • 情報系の学部生、大学院生、教授 (30%)
  • 経営者 (10%)
  • 理学部同期(5%)
  • その他 (5%)

というような構成比となっている。

様々な機会に恵まれた

今までの大学4年間を振り返ってみると自分は機会に恵まれていたなぁとよく思う。

自分はずっとAI系の勉強をしてきたのだけれど、学部2回生の頃から日立製作所の基礎研究所にて研究に携わらせてもらい、これは非常に大きかったと思う。

本来なら大学院生や社会人で学ぶようなこと(発表の仕方やドキュメントの書き方、コーディングスタイル、社会人でのビジネスマナーなどなど)を色々教えてもらうことができた。

f:id:komi1230:20191221024335j:plain
日立の基礎研での自分のデスク。デュアルディスプレイだった。

他にも友人の紹介でアジア情報学セミナーという国際セミナーに参加した。

f:id:komi1230:20191221024906j:plain
飛び込み参加だったが色々発表を聞いた

AI系以外で言えば、なんとなく履修していた授業が非常に少人数で、その先生に気に入ってもらってオオサンショウウオの生態調査に連れて行ってもらい一緒に捕獲作業をさせてもらったこともある。

f:id:komi1230:20191221024130j:plain
9.8Kgの大物を捕獲した。

こうしたことは普通に大学生をやっていたら絶対にあり得ないことなので、自分はチャンスに恵まれたんだと思う。

大学生活を通して学んだこと

こうして色々振り返ってみると、私大文系でサークルに入って云々みたいな量産型大学生に比べて自分はかなりイレギュラーでクレイジーな大学生活を送っていたと思う。

多分これの背景としてあるのは、なんやかんやで勉強が好きだったこと自発的にチャンスに飛びついていく図太さの2点が大きいのかなと考えたり。

やっぱり受身な姿勢をとっているとその果ては普通か普通未満しかないような気がしている。

引き寄せの法則じゃないけど、チャンスが巡ってくるのは結局チャンスを欲してる人間なのかなと。

もちろん、チャンスを得るために自分から色々行動することめちゃくちゃ大切で、堂々としていること行動力はかなり重要だと思う。

これは良くないことなのかもしれないけど、時にはハッタリをかますこともやり方としてはアリだと考えている。

自分の場合、基本的にだいたいハッタリかイキリで、それでチャンスを掴んでから実力を後から間に合わせるというようなやり方をかなりやってきた。

浪人からツイッターで繋がっている超優秀な東大の友人がこんな良いことを言っていたので引用しておこうと思う。

先にイキっといて実力後から間に合わせるぐらいじゃないと人生足りないことに少し前に気付いた

本当にこれに尽きる。

実力のある人間にはチャンスが降ってきてそのチャンスを活かして更に実力を高めていっており、世の中の構図というか周りの人間を見ていて思うのは、基本的に実力とチャンスは相互に正のフィードバックがかかっていて、このループ状態に入るための初動としてハッタリやイキリは必要なんだと思う。

どこまで自分の人生に対して主体的になって図太くなれるかがある意味勝負。

実際、学部2回生とか3回生から教授にアピールして研究室にデスクを用意してもらって3回生とか4回生で国際学会に論文を通すような人もいる。

インターンの獲得とかについても同様。

もちろん、これ以前の話で自分が何に興味があるのかとか何が好きなのかを明確化させることもかなり重要なんだけれど、このステップにおいてもとりあえず色んなことにチャレンジしてみないと自分がそれが好きなのかわからないので、やっぱりとりあえず動いてみるというのが結局重要だと思う。

京大理学部という最強に自由で自主性が全てを左右する環境で生きてきて、自主性を発揮して行動を起こすこと、これが自分が京大で学んだことだと言える。

終わりに

長い長い人生なので今後自分がどこに向かっていくかについて明確な言明はできないけど、大学で学んだことはきっと活きてくるはずなので、そこらへんうまいことやっていくつもりである。

何がどうなったせいかわからないけどすでにソフトバンクの社員からの期待値がすごいことになっているので、来年の入社後なんとか期待に応えられるように今のうちに実力を高めていこうと思う。

まあ、これもイキリとハッタリによって集めた期待で、すでに新入社員代表でイベントに登壇したり諸々の代表を努めさせていただいており、どうやら実力とチャンスのループには入り込めているっぽいので、今まで通り今後も迫りくるチャンスに間に合うように実力を高めていこうと思う。

大学生活ももうすぐ終わり。

数ヶ月後は社会人の世界にHello Worldをする。

これからもがんばっていこう。

Common LispのソースコードからUnixコマンドを叩く

やや久しぶりの更新。

最近はあまりLispを書いてなくて、ずっとベイズ深層学習の勉強をしている。

先日なんとなく書店をフラフラしていたところコンピュータサイエンス系の棚にて須山さんの『ベイズ深層学習』を発見し、勢いで購入したのだけれどこれがなかなか面白い。

いわゆる頻度論的なアプローチとベイズ的なアプローチをうまく対比させていて、どう異なっていてどう共通部分を見出せるかについてかなり簡潔に説明されており、ベイズについては1年前にPRMLを読んだだけだったので久しぶりにしっかり手を動かして読み進めている。

そういえばCommon Lispベイズ系のライブラリは無かった気がするので実装しようかなという構想がある。

ベイズ推論は尤度関数などをしっかり計算しようとするとなかなか計算量がハードで、ベイズ推論パッケージであるStanは記述されたモデルを一度C++にトランスレートして計算しているので、C並みの速度が出るCommon Lispならマクロなどを活用することでCommon Lispネイティブで実装ができると踏んでいる。

Common Lispでやりたいことはたくさんあるのだけれど、時間が空き次第しっかり開発に着手しようと思う。

さて、本題へ。

ソースコードからUnixコマンド

PythonなどでUnixコマンドを叩こうとする際は subprocess を使うことでなんとかできる。

import subprocess as sp

sp.call("pwd")
# => "/path/to/your/current/directory"

引数ありのUnixコマンドを叩く際は、引数にリストとして入れてあげればできる。

import subprocess as sp

sp.call(["ls", "Desktop"])

このようにソースコードからUnixコマンドを叩くことができると色々なツールのラッパーを簡単に作成することができる。(例えばGnuplotとか)

さて、こうしたUnixコマンドをソースコードから叩くのをCommon Lispでやるのはややめんどくさい。

というのも処理系依存だからである。

例えば自分が普段から使っているSBCLsb-ext:run-program で、

(sb-ext:run-program "/bin/ls" '("Desktop") :output t) 

という具合になる。

しかしこれはSBCLの場合で、CLISPやCCLとなるとまた変わってくる。

ちなみにSBCLではこの sb-ext:run-program によって解決できるが、SLIMEでこれを使おうとするとまた別の問題が起こり、標準出力ができずに失敗するのでstreamとして渡してあげる必要がある。

まあ要するに汎用的なコードを書くには問題だらけなのである。

trivial-shellという選択

さて、Common Lispには trivial-shell というライブラリがある。

これは上記の問題を解決するために用意されたもので、簡単に使える。

例えば

(ql:quickload :trivial-shell)

(defun system (cmd-str)
 (trivial-shell:shell-command cmd-str))

とすれば (system "ls") のようにして使え、Pythonsubprocess とほぼ同様のインターフェースが実現できる。

この trivial-shell は上記のSLIMEでの問題も解決している。

f:id:komi1230:20191223214536p:plain
SLIMEでの動作確認

だいたいはこれで問題なさそう。

ただ一つ文句をつけるとすれば、ls での結果表示が #\Newline によって改行されており、結果をリストとして表示するにはちょっと一手間を加える必要がある。

自分は上記の画像の通り、以下のようなやり方で解決している。

(ql:quickload :trivial-shell)

(defun system (cmd-str)
 (trivial-shell:shell-command cmd-str))

;; split関数を用意
(defun split (x str)
  (let ((pos (search x str))
        (size (length x)))
    (if pos
      (cons (subseq str 0 pos)
            (split x (subseq str (+ pos size))))
      (list str))))

;; split関数によって改行でリストごとに切っていく
(split (string #\Newline) (system "ls"))

これで良さげ。

終わりに

自分は今のところCommon LispUnixコマンドが欲しくなることはあまり無かったのだけど(せいぜいカレントディレクトリを見るくらいで sb-posix:getcwd で解決する)、今日後輩からその手の質問をされて気になったので自分で今回調べてみた。

自分はCommon Lispではアルゴリズムについてよく考える一方でシステムについてあまり触らないので、たまにはこういうのも面白いかもなと思ったり。

勉強になった。

自作OSSとしてCommon Lisp用の描画ツールKaiを作っています

f:id:komi1230:20191206222039j:plain

Softbank AI部 Advent Calendar 2019の7日目。

まず始めに、今回一緒にアドベントカレンダーを回していってくれている社員の皆さんと内定者に感謝。

というのも、このSB AI部のアドベントカレンダーの企画を立ち上げたのは自分だからである。

先日より内定してちょこちょこ社員や内定者と交流するイベントに出たりしているのだけれど、縁あってSB AI部(社員の方で構成されている部活)のSlackに招待してもらった。

SB AI部については@kmotohasが書かれた2日目の記事に詳細があるので適宜参照。

ちょうど11月の上旬くらい、ツイッターを見てると色々な会社が社内アドベントカレンダーをやっていて(しかも結構楽しそう)、もしかしてソフトバンクもやっているのかな?と思ってSlackをバーっと確認。

どうも見た感じ特にその手のやりとりは無かったので、randomのチャンネルで質問してみる。

f:id:komi1230:20191206221846p:plain
実は自己紹介以外でSlackで発言するのが初めてだった。

そうすると、社員の方の何人かが面白そう!とかやってみよ!というような反応をしてくださった。

これはイケるやつだ!ということで、勢いでアドベントカレンダーを作成。

最初は2, 3枠しか埋まらず、入社前から早速やらかしたやつかぁ...と心配していたのだけれど、だんだんと勢いが出てきて、最終的にはビッシリ埋まった。

adventar.org

本当に社員の皆さんと内定者には感謝である。

Lisp人工知能

さてさて、前置きはこのくらいにして7日目の記事の本題へ。

AIもとい人工知能は少し前から話題になっていて、ソフトバンクの注力事業であるわけだけど、この人工知能は最近になってポッと出てきたものではなく昔から長いこと研究されている領域だったりする。

では人工知能はいつから研究されているかというと、1950年台に遡り、1956年にAIに関する世界初の国際会議(ダートマス会議)が主催された。

世界で初めて実用デジタルコンピューターが作られたのが1940年代で、世界で初めての高水準プログラミング言語であるFortranができたのが1954年、これらのことを考えてみればコンピューターの黎明期に人工知能という概念が誕生したと言える。

ちなみに余談として、FortranはFormula Translation(式変形)の略で、昔はマシン言語を直接書いてコンピューターに計算をさせていたのだけど、Fortranはより人間に近い言語をマシン言語に変換する役割(いわゆるコンパイラ)として登場し、「これからの時代はプログラミングをやる必要はない!全てコンピューターが自動でやってくれる!」という強烈な宣伝文句とともに一世風靡し、当時では画期的なものであった。 (出典 : 『プログラマーのジレンマ 夢と現実の狭間』スコット・ローゼンバーグ著)

さて、そんな時代の中で開催された国際会議で、ジョン・マッカーシーという数学者が世界で初めて「人工知能」という言葉を定義した。

このジョン・マッカーシー人工知能やコンピューターサイエンスにおいて偉大な貢献をした人であり、実は「人工知能の父」と称されるあのマービン・ミンスキーもこの会議を機にAI研究者を志し、その3年後にはMITでマッカーシーを師事することになった。

さて、この人工知能という言葉を生み出したマッカーシーこそ同時にLispを生んだ人物なのである。(Lisperの間ではマッカーシーLispを"発見した"と言う)

この初めてLispを提案したのがこの論文

マッカーシーの数多くの貢献の中でも特に有名なものとして、現在ほとんどのプログラミング言語で実装されているif文やガベージコレクションなどがある。(実はかつてのFortranにはif文がなくgoto文しかなかった)

if文もガベージコレクションも、高水準プログラミング言語として初めて実装されたのはLispなのである。

これ以外に、マッカーシーはタイムシェアリングシステムというものも提案しており、これは何かというと現在でのアプリケーションサービスプロバイダ、つまりSaaSで、現在流行っているビジネスモデルを半世紀以上前にマッカーシーは実現可能だと提案していた。

...とまあマッカーシーがすごいという話はある程度にしておいて、人工知能の歴史やLispがどのような興隆を経てきたかという話については以下の記事が非常によくまとまっているのでぜひ読んでもらいたい。

tech.dely.jp

人工知能は2回の冬の時代を経て現代でまた興隆を極めているのだけれど、現代の人工知能技術の中核をなす技術であるディープラーニングは膨大な数値計算によって成立している。

かつての人工知能は記号推論によって解決しようとしていたのだが、現実世界でも適用可能な妥当なルールベースを作りこむことが難しいことが分かってきたので、その後は大量のデータからボトムアップ的に学習して自動的に知識表現を獲得してやろうという流れになり、ニューラルネットなどの機械学習手法が発達した。

なので大きな枠組みで見れば現在のディープラーニングも知識をどのように計算機で実現するかという話であり、それを抽象的なレイヤで行うかボトムアップ的に行うかでアプローチが異なるだけだったりして、本質的には変わらなかったりする。

もうPython卒業しようよ

コンピュータの性能向上に伴い、プログラミング言語にはアルゴリズムの表現力と開発効率が要求されてくるようになった。

それにより、今はPythonが最も注目される言語となった。

ただPython単体だとスクリプト型言語のために実行速度が非常に遅く、ディーブラーニングのような膨大な量のパラメータを逐次更新していくようなアルゴリズムに対しては実行が遅すぎるので、ライブラリとして一部の処理をC言語のような高速な言語に実行させることによってアルゴリズムの表現力を保持しつつ実行速度の担保をするような手法が取られるようになってきているのが昨今の流れとなっている。

ここでのライブラリというのがTensorFlowだったりPytorch、Keras、今は亡きTheanoやCaffeなどである。

パッと見だとこれらのアプローチは良さげだと思われるが、例えばエッジコンピューティングのような組み込みなどのものだとPythonを主軸にしたやり方ではメモリを圧迫しすぎてしまうのでプログラムを乗せることができず、結局アルゴリズムの実装しやすさと開発効率を重視したのに最終的にC言語で実装し直すという本末転倒的なことになる。

一応PythonをネイティブコードへコンパイルするCythonというものもあったりするが、結局Python本来が持つアルゴリズムの実装しやすさに制限をかけることになり、結局何がしたかったんだろうという感じになってしまう。

このような考えのもと、機械学習アルゴリズムの社会実装への需要が高まっている昨今でいつまでもディープラーニングアルゴリズムの実装はPythonで実装するしかないというのは少々前時代的という考え方にすら至りうる。

現在ではプログラミング言語も様々な開発が進んでおり、個人的にはJuliaという言語に注目していて、Python以上に柔軟な文法を持ちながら高速である(少なくともPythonの10倍くらい)

このような背景も考えるとPythonに頼り続けるのは限界があると思うし、次の時代を見据えるならPython以外の言語に視野を広げる必要があると思う。

Lispという一つのアプローチ

さて、ここで一つの解決法として自分はLispはアリなのではないかと考えている。

Lispはもともと超絶柔軟な文法を持っており(もはや文法が存在しないと言っていい)、強力な抽象化機構を持っているのでアルゴリズムの表現性という点ではあらゆる言語の中で強力なものである。

柔軟な文法とはどういうことかというと、Lisp自分で構文を定義することができるのである。

例えば、Pythonでは関数を定義する際に

def hoge(x, y):
    return x + y

のように関数を定義することはできるが、このPython本体がもともと持っている関数定義defを自分で定義することはできず、my-defmy-ifのようなオリジナルの構文を作ることはできない。

Lispはマクロという機能を使うことによって自身の構文を定義することができ、言ってしまえばその場で自分オリジナルのプログラミング言語を作ることができる。

具体的に、Lispのマクロを使えばSQLやHTMLなどもLispのコードとして実装することができる。

どの言語を使うかで何を言えるかが変わってくる。

Lispは主に関数型プログラミングパラダイムを採用していて、高階関数ラムダ式をサポートしているため、Lisp本来が持つ柔軟さもあって一つにアルゴリズムを実装するにしてもC言語Lispではコードの量が10倍以上違ってくる。

このようなLispではあるが、速度はどうかというと、C言語並みか場合によってはCより速くなる。

今はLispはあまり有名な言語ではないが、かつてはコンパイラの研究でLispが先頭を走っており、Lispマシンというものも存在したほどであり、昔から高速なプログラミング言語の部類にある。

中には強烈な名言もあり

Cで書くコードの方がCommon Lispで書くより速いって人がいたら、それは彼のCの技量が高すぎるってことだね。

“If you can't outperform C in CL, you're too good at C.” — Eric Naggum

Lispが高速な言語であることを物語っている。

このCより高速なLispのコードを書くことについては以下の深町さんの記事が非常に面白いので参照。

blog.8arrow.org

Lispの高速さを物語るプロダクトとして、この深町さんが実装したWooというHTTPサーバーはあらゆるHTTPサーバーの中でも最高クラスの速度を誇っている。

f:id:komi1230:20191207001656p:plain

Lispがこのような高速さを担保している理由として、OSSSBCLというネイティブコードまでコンパイルする超優秀なコンパイラがあり、これに最適化オプションをつけることによって超高速なコードを書くことができる。(自分はSBCLのコミッター)

最適化に際して、Lispの処理系にはプロファイラという機能がついており、プログラムのどの部分が時間がかかっているかを調べることができるのでボトルネックの発見に役立つ。

そうしてこの時間がかかっているブロックに対して細かく最適化オプションをつけることができ、他のプログラミング言語に比しても最適化を軽快に行うことができる。

この最適化については前に記事を書いた。

komi.hatenadiary.com

このようにLispは速度も高速で柔軟性を持っている言語だが、もう一つ絶対に語っておかなければいけないのがSLIMEという開発支援ツールである。

Lispの特徴として括弧がたくさん現れるが、Lispでは括弧の塊それぞれが一つのソースコードとなっている。

これの何がすごいかというと、ソースコードの一部だけをコンパイルして実行することができる。

f:id:komi1230:20191207003351p:plain

この機能があると、手元で書いたソースコードを即時コンパイルしてその場でテストすることができ、実装からテストまでのサイクルを高速で回せるようになるのである。

以上、Lispは高速で柔軟な文法を持ち強力な開発支援ツールを持ったすごい言語だと言える。

なぜLispは人気がないのか

このようなプログラミング言語として強力過ぎる魅力を持った言語であるのに、なぜLispはユーザーが少なく人気がないのか。

これに関してはさっぱりわからない。

自分はLispを書き始めて数年経つが、特に文句はないし、むしろC言語PythonJavaScriptなどの他の言語を触るたびに「なぜLispのような機能がないのか」「なぜLispより圧倒的に遅いのか」とイライラさえする。

もっとLispは評価されるべきだしLisp界隈が盛り上がっていくべきだと思っている。

ただ一点、指摘することがあるとすれば、ライブラリの開発が全体として勢いがないというのはある。

これはLispユーザーが少ないことによる副次的な影響なのだが、ライブラリの開発があまり活発に行われていないために死んでしまっているようなライブラリも数少なく、ソースコード自体はバリバリ現役でもドキュメントが古すぎて存在しない(もしくは埋もれてしまっている)ということがある。

Lispのこれからのために

そのようなLispであるが、個人的には最近どんどん勢いが上がっている気がする。

先述の深町さんがCommon LispでWeb系ライブラリを作りまくってLisp × Webの雪原を踏み荒らしまくった結果、Lispユーザーがグッと増えたような気がする。

それを見て、自分は自分も得意分野を盛り上げて行こうと思うようになった。

先日もIBMでAIリサーチャーをやっているMasataro AraiさんからNumclというライブラリを一緒に開発していかないかとお誘いいただいた。

これはPythonのNumpyにある機能をCommon Lispライクに実装しようというプロジェクトで、自分は機械学習系・数値計算系の人間なので、このようなプロジェクトは非常にワクワクしている。

さて、数値計算機械学習系のプロダクトを開発するにあたって、何かとデータを可視化させるツールというのは必要になる。

一応Common LispにはCL-Plotのような可視化ツールは存在するが、だいたいが2次元プロットで、3次元プロットや散布図、ヒストグラム、ヒートマップのような機能はない。

ということでMatplotlibのようなプロッターをOSSとして自分で作ることにした。

github.com

名前はKaiとし、ハワイ語で海という意味を持つ。

現在まだ開発途中であるが、すでに2次元プロット程度ならできるようになっている。

f:id:komi1230:20191207005216p:plain
Kaiでプロットしてみた図

まだ依存関係を記述するファイルなどを整えていないのでプロダクトとしてしっかりリリースはできていないが、ライブラリとしての体裁が整ったらまた追って正式にリリースの報告を出そうと思っている。

自分はLispを愛しているが、これからどんどん盛り上がっていけるように自分にできるコミットをどんどんやっていこうと思う。

これからLispの時代が来るように、一つ一つできることを積み上げていこうと思う。

終わりに

Softbank AI部のアドベントカレンダーの記事だったが、結果的にただのLispの宣伝になってしまった感がある。

ただ、本当に自分はこれからのAI系プロダクトではLispは一つのアプローチになると信じているので、これからもコミットしていこうと思う。

それではお疲れ様でした。

興味を持った人に読んでほしいもの

Lispをちょっと始めてみようかなという人向けの記事。

qiita.com

Common Lispの勉強で、入門として非常に良い本。

www.oreilly.co.jp

Y Combinatorの設立者でありLisp界のゴッドファーザーポール・グレアムのエッセイ。

Amazonのリンク

gist.github.com