ブラウザ上でデータ分析が出来る!Clojure/Gorilla入門

f:id:AntiBayesian:20140907214031j:plain
f:id:AntiBayesian:20140907201052j:plain

概要

この記事は、Gorillaという
ブラウザ上でClojureという言語を利用出来るライブラリを利用し、
ブラウザ上でデータ分析環境を構築するための入門記事です。
Clojureの事前知識は一切不要で、
ClojureやGorillaのインストールから、ブラウザ上で各種手法を
コピペだけで実践出来るになるまでを説明しています。
なお、各種分析手法の詳細には言及しておりません。

とにかくGorillaを動かす

「説明は良いから、とにかく動かしたい」
という方向けに要点だけ説明します。

leiningenをインストールし、作業フォルダにてlein new gorillaでプロジェクトを作り、
生成されたgoraillaフォルダ直下にあるproject.cljに下記をコピペし保存、
lein gorillaと打ち込み、少し待つと
Running at http://localhost:XXXXX/worksheet.html
と表示されるので、そのURLを叩くとこんな感じのページが表示されます。
以上。

(defproject gorilla-test "0.1.0-SNAPSHOT"
  :description "A test project for Gorilla REPL."
  :dependencies [[org.clojure/clojure "1.6.0"]
                 [incanter "1.5.5"]
                 [incanter-gorilla "0.1.0"]
                 [cc.artifice/clj-ml "0.6.0-SNAPSHOT"]
                 [org.atilika.kuromoji/kuromoji "0.7.7"]]
  :main ^:skip-aot gorilla-test.core
  :target-path "target/%s"
  :repositories [["Atilika Open Source repository" "http://www.atilika.org/nexus/content/repositories/atilika"]]
  :plugins [[lein-gorilla "0.3.3"]]
  :profiles {:uberjar {:aot :all}})

Clojure/Gorillaとは

Clojureとは、JVM上で動くプログラミング言語の一種です。
Clojureには統計解析ライブラリIncanter機械学習ライブラリclj-mlなど、
継続して開発されているデータ分析用のライブラリが用意されています。
また、同じくJVM上で動くHadoopやHBaseなどのシステムとも親和性が高く、
それらを利用して大規模なデータ分析を行うのに適しています。
しかし、Clojureをいつでもどこでも誰にでも利用して貰うためには、
各端末にJDKのインストールやパスを通すなどの環境構築が必要であり、
各種ライブラリの更新の度全端末にそれを適用し続けるのは
ハードルが高いと言わざるを得ません。
また、データを個々の端末に移動するのも非常にコストがかかります。
勿論これはClojureに限った話ではなく
他の処理系においても同じ問題ではありますが。
そこで、ブラウザ上で誰でもアクセス出来て、
直ちにデータ分析を行えるようなシステムを簡単に構築出来れば
上記のハードルをクリアできます。
つまり、誰でも色んな端末(スマホタブレットでも!)アクセス出来て、
最新のバージョンを利用したければサーバ側で更新を掛ければ済み、
データはサーバ上に置いたままなので一々解析するのに
全データをローカルに落とす必要も無く、
解析用の処理を送り結果を受け取るだけでよくなります。
そのような要望によって生み出されたのがGorillaです。
下記のGollira本家サイト、また、
GorillaにIncanterを組み込んだincanter-gorillaのサイトを
ご覧頂ければどのようなものかがご理解頂けると思います。
Gollira本家
incanter-gorilla
同様のプロジェクトはPythonやRにも存在しています。
特にIPython notebookはかなりの出来栄えですので、
特にJVM環境以外でも問題無く、
かつPythonに慣れ親しんでいる方は
そちらを利用するのも良いと思われます。

Clojureのインストール

主にWindows7向けのインストール方法について説明します。

まず最新のJavaSDK(Javaの開発環境)を入れる必要があります。
下記からご自分の端末に合わせたモノをインストールしてください。
http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html

次に、下記のページを参考にPath, JAVA_HOMEを設定します(windows向け)。
http://www.javadrive.jp/install/jdk/index4.html

次に、Clojureの開発ツールであるleiningenをインストールします。
公式サイトからlein.batをダウンロードして下さい。
http://leiningen.org/
(あるいはこれを利用)

最後に、パスの通っている作業フォルダ(例:c:\lein)にlein.batを移動して、
コマンドプロンプトから
lein self-install
を実行。
あとはインストール処理が自動で行われますので、終了するまで待ちます。
終了したら
lein -version
と打ち込み、2014/09/07時点では
Leiningen 2.4.3
と表示されればインストール作業終了です。

Gorillaを起動してみる

作業フォルダにて、コマンドプロンプト
lein new <プロジェクト名>
と打ち込むと新規プロジェクトを作成出来ます。
新規プロジェクトには最低限必要なファイルや設定が自動で生成されています。
ここでは
lein new gorilla
と打ち込んでみましょう。
するとgorillaというフォルダ名の直下に
project.cljというファイルが生成されています。
これはこのプロジェクトの設定ファイルです。
設定を変更する場合はこのファイルを編集します。
ここでは下記のように編集して下さい。

(defproject gorilla-test "0.1.0-SNAPSHOT"
  :description "A test project for Gorilla REPL."
  :dependencies [[org.clojure/clojure "1.6.0"]
                 [incanter "1.5.5"]
                 [incanter-gorilla "0.1.0"]
                 [cc.artifice/clj-ml "0.6.0-SNAPSHOT"]
                 [org.atilika.kuromoji/kuromoji "0.7.7"]]
  :main ^:skip-aot gorilla-test.core
  :target-path "target/%s"
  :repositories [["Atilika Open Source repository" "http://www.atilika.org/nexus/content/repositories/atilika"]]
  :plugins [[lein-gorilla "0.3.3"]]
  :profiles {:uberjar {:aot :all}})

ここで重要なのはdependenciesとpluginsです。
dependenciesに利用するライブラリを記載します。
ここに記載されたライブラリをleiningenが
依存関係などを自動解決してインストールしてくれます。
ここではincanterとincanter-gorilla、clj-ml、そしてkuromoji*1
という形態素解析器を指定しています。
形態素解析器についてはこちらをご覧ください。
pluginsにlein-gorillaを記載し、gorillaを使えるようにしています。*2

これらが全部終わったら
lein gorilla
コマンドプロンプトに打ち込むと
Running at http://localhost:xxxxx/worksheet.html
とURLが表示されるので、そのアドレスをブラウザで見ると
Clojure実行環境が表示されます。
f:id:AntiBayesian:20140907202323j:plain

なお、アドレスのxxxxxの部分はランダムで決まりますが、ipやportを指定したい場合は
lein gorilla :ip xxxxx :port yyyyy
とします。詳細なオプションは下記に記載されています。
http://gorilla-repl.org/configuration.html

動作するか確かめてみましょう。
f:id:AntiBayesian:20140907202437j:plain
表示された画面の灰色のブロックに
(+ 1 2 3)
と打ち込み、ShiftとEnterキーを同時押しすると処理が実行されます。
実行結果が6になったら成功!
これにてGorillaの設定作業は終わりです!お疲れ様でした!

Gorillaで統計量を求めてみる

(use '(incanter core stats charts datasets)) ;統計解析ライブラリIncanterを使う指定
(def iris (get-dataset :iris)) ;サンプルデータセットの中からirisを選択し、その内容をirisに束縛
iris ;irisの中身を見てみる。
; :column-names から[:Sepal.Length :Sepal.Width :Petal.Length :Petal.Width :Species]
; という列があることが分かる。
; irisとはあやめのデータで、sepalはがく、petalは花びら、speciesはあやめの種類である
(mean ($ :Petal.Length iris)) ;花びらの長さの平均値を求める
(sd ($ :Petal.Length iris)) ;花びらの長さの標準偏差を求める

f:id:AntiBayesian:20140907202646j:plain

Gorilla上で可視化してみる

(use '(incanter core stats charts datasets))
(use 'incanter-gorilla.render) ;Incanterで可視化したモノをGorilla上で表示するライブラリを指定

(def iris (get-dataset :iris))
(chart-view (histogram :Petal.Width :data iris)) ;chart-view関数でヒストグラムをGorilla上に表示
(view (histogram :Petal.Width :data iris)) ;view関数でヒストグラムをGUIで表示

f:id:AntiBayesian:20140907202748j:plain
こちらに掲載した可視化のviewの部分を
chart-viewに置き換えれば、全てブラウザ上で実行可能です

Gorilla上で機械学習してみる

(use 'clj-ml.classifiers 'clj-ml.utils 'clj-ml.io 'clj-ml.data)
; weka特有のデータ形式arffを利用します。
(def iris  (-> (load-instances :arff "http://repository.seasr.org/Datasets/UCI/arff/iris.arff") (dataset-set-class :class)))
; サーバ上にあるCSV形式を読み込む場合は次のようにします。
; (def iris  (-> (load-instances :csv "iris.csv") (dataset-set-class :class)))
; 決定木(c4.5)を作ってみる
(def decision-tree (-> (make-classifier :decision-tree :c45) (classifier-train iris)))
; 作成した決定木の中身を見てみます
decision-tree
;クロスバリデーションに掛けてみます
(def decision-tree-evaluation (classifier-evaluate decision-tree :cross-validation iris 10))
;クロスバリデーションの結果を確認します
(println (:summary decision-tree-evaluation))
(println (:confusion-matrix decision-tree-evaluation))

f:id:AntiBayesian:20140907203011j:plain
f:id:AntiBayesian:20140907203017j:plain
こちらに掲載した機械学習手法も
全てブラウザ上で実行可能です。RandomForestやK-meansなどもお試しください。
但し、ファイルを読み込む際、サーバ上でGorillaを立ち上げている場合はファイルパスにご注意ください。
ローカルファイル指定は自分の端末ではなくサーバ上で探索します。

Gorilla上で形態素解析してみる

(import [org.atilika.kuromoji Token Tokenizer])
(def tokenizer (.build (Tokenizer/builder)))
(defn ma [sentence] 
  (doseq [^Token token (.tokenize tokenizer sentence)] 
      (println (str (.getSurfaceForm token) "\t" (.getAllFeatures token))))) 
(ma "あきつ丸改二で大発動艇欲しい")
; (ma "あきつ丸改二で大発動艇欲しい")
; の形態素解析結果が望みの結果になってないので
; 形態素解析用の辞書を整備する必要がある

; 以下の内容を記載したファイルを用意し、適当なファイル名を付ける
; ここでは一旦userdict.txtと名付ける。
; -- ファイル内容ここから -- 
; 大発動艇,大発動艇,ダイハツドウテイ,固有名詞
; あきつ丸改二,あきつ丸 改二,アキツマル カイニ,カスタム名詞
; -- ファイル内容ここまで -- 
; 1列目:表層, 
; 2列目:1列目をどう区切るか。区切りたい位置に半角スペースを入れる
; 3列目:読み(カタカナ)
; 4列目:品詞情報
; ※windowsの場合はファイルのエンコードをSJISにする必要有り
; ファイルをc:\\lein\\gorilla\\userdict.txtに置いたとした場合、
; 以下のようにすると望みの結果が得られる。

(def dic "c:\\lein\\gorilla\\userdict.txt")
(def tokenizer (.build (.userDictionary (Tokenizer/builder) dic)))
(defn ma [sentence] 
  (doseq [^Token token (.tokenize tokenizer sentence)] 
      (println (str (.getSurfaceForm token) "\t" (.getAllFeatures token))))) 
(ma "あきつ丸改二で大発動艇欲しい")

f:id:AntiBayesian:20140907203143j:plain
f:id:AntiBayesian:20140907204502j:plain
形態素解析の結果を用いてワードカウントなどをする場合は
こちらをご覧ください。
ここで紹介している内容もブラウザ上で実行可能です。

終わりに

ブラウザ上で様々な分析が出来る便利な時代になってきました。
外出先の貧弱な端末や回線からでも、インタラクティブなデータ分析が可能になり、
例えばMTGの最中に「あのデータってどうなってるんだっけ?」
って話題に上がったその場ですぐ集計・可視化して確認出来るなど夢が広がりまくりです。

実務上データ分析しててかなり面倒だと思うのがデータサイズです。
数十GB単位になるとファイルの移動だけで面倒なことになりますし、
ローカルに持ってくるとそれだけでSSD空き容量死ぬケースがあります。

あと分析ツールの更新管理は多分皆さんが想像するのの27倍ダルいです。
一つのユースケースとして想像して欲しいのですが、
分析チームに30人くらい人がいて、
そのうちの半分がコンサルやマーケター的な方、
残り半分がエンジニアだったとしましょう。
大体前半の方々は「更新したのでアップデートしてくださーい」
とアナウンスしても、面倒なので無視します。
だって現状で使えてるもん。慣れてるのが一番だよね!
大体後半の方々は「更新したのでアップデートしてくださーい」
とアナウンスすると、既に自力拡張してるので、
それが動かなくなると嫌だから無視します。
こういう時システム提供側が取り得る選択肢は
更新しない同僚をハンマーで一人ずつ殴って回るか
あるいはブラウザで実行できるようにするかです。
非常に僅差ですが二個めの方がまだ若干マシかなと思わなくもないです。

ブラウザ上での分析環境構築は、
同時接続数とか認証周りとかにまだまだ機能不足や問題があります。
これはClojure/Gorillaだけではなく、
RのShinyやPythonのIPython notebookでも同じ問題は生じています。*3
とはいえ、ブラウザ上で分析可能なメリットは結構大きい上に、
Clojure/GorillaはJVM環境で簡単に構築できるツールなので
是非チャレンジしていきたい+皆さんもチャレンジして欲しいなと思います。
f:id:AntiBayesian:20140907214043p:plain
それでは皆様、よきGorillaライフを!!

素敵なLispエイリアンイラストをマルタコEX@marutakoEX様からお借りしました!
マルタコEX様、利用のご快諾、誠に有難うございます!!!

*1:ちなみにここで指定しているのは最新版ではありません。これは単に私が今まで利用してて動作が理解出来てるというので、今回も惰性で指定しているだけです。Lucene Kuromojiの最新版を使う方が良いです

*2:私は「何でこれがdependenciesで何でこれがpluginsなの?」っていうのがいまいちわかってないんですが、その切り分けをご存知の方いらっしゃったら教えてください…。まぁとりあえず公式サイトの指示に従って設定すれば動きます

*3:IPython notebookは一応パスワード設定出来ますが、ここでいう認証は「Aさんはこのデータとこのデータにアクセス出来て、Bさんはさらにあのデータにもアクセス出来て、あ、Cさんは異動したからこのデータへのアクセス禁止して」とかやりたいって意味です。まぁ他で認証機能別途付けろと言われたらそりゃそうなんですが

WindowsでSublime Text2 + leiningen + Clojure/Incanter環境をお手軽に作る

WindowsでClojureを用いて統計解析を行う環境を簡単に作成します。難しい作業はしません*1
ClojureJVM上で動くLispのようなプログラミング言語です。
これは簡単に説明すると
JVM上で動く=WindowsでもMacでもLinuxでも動く!その上使えるライブラリも多い!」
Lisp=簡単に読み書き出来て幸せ」
という意味です。
IncanterはClojureで書かれた統計解析ライブラリです。
Clojureから簡単に使えます。
もしあなたがプログラミングのこと一切知らなくて統計解析を始めようというならこの組み合わせが最t…ごふっ。
まぁ騙されたと思ってとりあえずやりましょうとかいってる相手にほいほい乗ってると騙されるので人生が辛い。
これらの組み合わせはsublime text2を除いて無料です。
Sublime Text2は便利なテキストエディタです。
コーディングしたりコードを実行したりするのにとても役立ちます。
無期限の試用期間があるので手軽に始められます。気に入ったらぜひ購入して下さい。
vimemacsという熟練のプログラマに愛されている素晴らしいツールもあるのですが、
設定や操作が素人には難しくハードル高かったので、いつか頭が良くなったら使いたいなと思います。
Sublime Text2の良い所は、デフォルト設定でもかなり使えることです。
さらにPythonやJSONを利用して自由にカスタマイズできるので、
使いこなせるようになればどんどんカスタマイズしましょう。
leiningenはClojureのビルドツールと言うかプロジェクト管理ツールです。
Clojure単体だと色々設定を書かなくてはいけなくて面倒臭い所を
このleiningenがよしなにやってくれます。


まずleiningenをインストールします。
Windowsにleiningenインストールする手順はこちらをご参照ください。
http://d.hatena.ne.jp/AntiBayesian/20120122/1327236946
次にsublime text2をインストールします。そしてsublime replというものもインストールする必要があります。
それにはこちらを参照してください。
http://yagays.github.io/blog/2012/11/16/sublimerepl-clojure/
ここらへんで気づいたと思われますが、リンク張るだけで済むしわざわざ記事書く必要ありませんでしたね。


さて、leiningenをc:\leinにインストールしたとします。
c:\leinにproject.cljって名前のファイルを作って次のように記述して下さい。

(defproject test "1.0.0-SNAPSHOT"
  :description "FIXME: write description"
  :dependencies [[org.clojure/clojure "1.4.0"][incanter "1.4.1"]])

記述し終わったらコマンドプロンプトを用いてc:\leinでlein replと打ちこんでください。
するとIncanterがインストールされて、(use '(incanter))とかやると使えるようになります。
ちなみにreplってのは何かと言うとこちらをご参照ください。
http://d.hatena.ne.jp/keyword/REPL
要するにあなたのコマンドプロンプトが突然Clojureプログラミング環境になってハッピーと言う話です。

最後にsublime text2のreplから直接Clojure呼べるようにします。
{あなたがsublime text2をインストールしたフォルダ。「Preference→Browse Packeges参照」}\Sublime Text 2\Packages\SublimeREPL\config\Clojure\Main.sublime-menu
を開いて

"cwd": {"windows":"c:/Clojure", // where the lein.bat lives!

ってなってる行を

"cwd": {"windows":"c:\lein", // where the lein.bat lives!

に変えればOKです。
これでSublime Text2からさっきのIncanter設定したreplを呼べます。


えーと、簡単でしたね。もうちょっと色々書くつもりだったけど特に書くことないくらい設定楽だしかなり飽きてきたのでここら辺でさようなら。


■2013/5/24追記
sublime text2からleiningenを呼ぶ件ですが、どうもleiningen2からは動かなくなってるそうです。いや、これは困ったことですね。
https://github.com/wuub/SublimeREPL/issues/48
仕方ないのでclojure.jarを直接呼ぶbatファイルを作って、sublime textはそいつを呼ぶことにしてとりあえずrepl動くようにしましょう。
多分leiningenでclojureをデフォルト設定でインストールした場合は
C:\Users\{あなたの名前}\.m2\repository\org\clojure\clojure\{インストールしたClojureのver}\clojure-{ver}.jar
となってると思います。違ったら適宜調整して下さい。
clojure.batって名前でファイルを新規作成して、その中に

java -jar C:\Users\{あなたの名前}\.m2\repository\org\clojure\clojure\{インストールしたClojureのver}\clojure-{ver}.jar

と書きます。
これをさっきのc:\leinフォルダに置きます。
次にMain.sublime-menuを開いて
"cmd": {"windows": ["lein", "repl"],
となってるところを
"cmd": {"windows": ["clojure.bat"],
とします。
これで動くと思います。
batファイル置くフォルダはどこでもいいのですがパスを通しておいてください。でないと動きません。
これでとりあえず私の環境だと動いてるんですが、もしこれ試しても無理だよ〜という方いらっしゃったらご連絡ください。
なんか考えます。

*1:出来ません

Windowsでleiningenを使おう!

2014/06/07 追記
現在windowsでliningenインストールするならこちらを使えば一発です。
http://leiningen-win-installer.djpowell.net/





 以前「Clojureのビルドツール"Leiningen"を使ってみた」という記事を書きました。Leiningenを使えば簡単にClojureのビルドが出来て大変便利です。これをUbuntuだけではなくWindowsで利用する手順をメモしておきます。え?なぜWindowsClojure書くのかって?ハハッ察してくださいXD
 手順はめちゃくちゃ簡単です。

  1. https://github.com/technomancy/leiningen/downloadsからWindows distributionの最新版を取得(2012/1/19現在Leiningen 1.5.2が最新)
  2. 解凍したフォルダを適当な場所に置き、そこにパスを通す。私は解凍したフォルダをC:\leinに置き、"SET PATH=%PATH%;C:\lein"としてパスを通しました。以下C:\leinにフォルダを設置したという前提で話を進めます。
  3. コマンドプロンプトを立ち上げ、先ほどパスを通したフォルダまで移動("cd c:\lein")し、"lein self-install"と打ち込むと、あとは勝手にインストールしてくれます

これだけでインストール終了。非常に簡単ですね!

 ではいろいろ遊んでみましょう。"lein version"と入力するとインストールしたleiningenのバージョンを確認できます。

>lein version
>Leiningen 1.5.2 on Java 1.7.0_02 Java HotSpot(TM) 64-Bit Server VM

もしここで

'"java"' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。

となったら、JDKというJavaのプログラムを実行するためのものをインストールする必要があります。
現時点では以下で最新版が取得できます。
http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html


REPL(対話的なClojure実行環境)を立ち上げるには"lein repl"と入力します。実にわかりやすいですね。すると

>c:\lein
>lein repl
>REPL started; server listening on localhost:21896.
user=>

なんとも簡単にClojure実行環境が整っちゃいました!簡単!
 お約束としてHello Worldプロジェクトを作ってみましょう。まずはコマンドプロンプトに"lein new HelloWorld"と入力します。するとHelloWorldプロジェクトフォルダが生成されます。そこにproject.cljというファイルが生成されているので、中に

(defproject HelloWorld "makeTest"
:dependencies org.clojure/clojure "1.2.1"
:main HelloWorld.core)

とプロジェクトの内容を記述します。次に、実際の処理を書くため、C:\lein\HelloWorld\src\HelloWorldまで移動します。そこにcore.cljというファイルがあるので、

(ns HelloWorld.core)
(defn -main [& args]
(println "Hello World!"))

と記述します。あとはプロジェクトのトップフォルダ"C:\lein\HelloWorld"まで戻って、コマンドプロンプトに"lein run"と入力すると"Hello World!"と表示されます。とっても簡単ですね。
 WindowsでもClojure環境を簡単に構築することが出来ました。これでバリバリClojure書けますね!皆さんのClojureライフが快適になることを願っています!

統計解析アプリ「Incanter」入門

 Clojure製統計解析アプリ「Incanter」は無料かつjarファイル一つでお手軽に実行できる、その上Javaの豊富なライブラリを利用したり、描画に特化したProcessingという処理系でリッチなアニメーションやインターフェイスを実装できるという面白いアプリケーションです。また、JVM上で動くため、HadoopLuceneなどにシームレスで適用できますし、GoSenなど形態素解析アプリも簡単に呼び出せるため、自然言語処理テキストマイニングにも活用できます。一番重要なことは、Clojureであるということ、つまり皆さんの愛するLispでコーディング出来るということです。もう一度言いますが、Lispで統計解析が出来るという喜b(略)。


 無料の統計解析アプリというとR(あとアプリではありませんが、Python-Scipy/Numpyなど)が挙げられると思います。正直な話、IncanterはRに比べて(いや、まず比べ物にならないのでは…)、ユーザー数や利用実績では完全に劣ります。Rでは最新の解析手法が実装されていたりしますが、Incanterは割と基本的な手法しかありませんし、パッケージの数も全く見劣りします。研究や実務で使う場合はRを用いるほうが良いでしょう。ではIncanterを使う利点はどこにあるのでしょうか?IncanterはコンパイルしてJarファイルにまとめて配布することができるので、「解析結果を渡すだけではなく、エンドユーザーが使いやすい簡単な統計アプリを作りたい。しかも色々インストールして頂くこと無く手軽に!」という用途に向いています。エンドユーザーとしても、単なる報告書渡されるだけよりも、パラメタを色々変更できたほうが楽しいですよね。また、Javaと連携できるという強みがあるので、Rでは出来ない大規模解析が可能(かもしれません、やったことないので…でも夢が広がりますよね!ですよね!)。また、JavaのSwingなどを使えるため、RよりGUIアプリをとても作り易くなります。あと一番重要なことはLispってことですね。RやScipyはLispではないので駄目ですね。もはやIncanter使うしか有りませんしIncanter知らずに今まで生きてきたことを深く恥じてください。


 さて、前置きはこれくらいにして、実際Incanterを使ってみましょう。Incanter本家からIncanter.jarを落としてきて*1、Incanterを設置したディレクトリで次のコマンドを実行します。

java -jar incanter.jar incanter.main;←Windows環境の場合
java -cp incanter.jar incanter.main;←Linux環境の場合

これでClojureのREPLという処理系が起動します。では皆さん大好きHello World!から始めましょう。

(str "Hello" " World!")

で"Hello World!"と表示されます。もうこの時点でIncanterというかLispの素晴らしさの片鱗が見えてきます。"str"は引数を標準出力する関数です。まぁそこは問題ないでしょう。しかし、上のコードを見てみると、引数が複数指定されています。試しに引数をもっと増やしてみましょう。

(str "hello" " world, " "あんちべ!")
>"hello world, あんちべ!"

引数を増やしても全く問題なく動作する…素晴らしい!このまま電卓のように利用してみましょう。足し算をします。

(+ 1 2 3 4 5)
>15

1〜5までの整数を足しあわせた結果15になりました。先程のstrと同じように、複数に引数を指定しても想定通り動きますね。


 Lisp系の基礎は、まず関数名(strや+など。+もLispでは関数です)が一番左にあり、その関数に放り込む要素を関数名の右に指定し、そしてその関数が働く範囲(スコープ)を括弧で表現するというものです。関数と要素はいいとして、スコープとは何か。足し算と掛け算を組み合わせたもので説明しましょう。

(+ 1 (* 2 3))
>7

…う、分かりづらい!!と思われるかもしれませんが、落ち着いて考えてみましょう。まず、一番左の関数は+です。引数は1と(* 2 3)です。なので、1と(* 2 3)と足しあわせたモノが一番外の括弧の処理結果になりますね。そして内側の括弧は(* 2 3) = 2 * 3 = 6なので、最終的に1 + 6になり、答えは7となります。美しい…曖昧性が一欠片もない…。しかも1~5まで加算するとき、いちいち他の言語のように1 + 2 + 3 + 4 + 5みたいな無駄に+を書く必要はありません。なんてシンプル。しかもLispと言えば目も眩む括弧の数が揶揄されますが、演算もstrの例も、別段他の言語と比べて括弧が多いわけではありません。C系の言語と比較してみるとprint ("hello world!");と(str "hello world!")で、処理に対して全く余計な;などもありません。というか;とは一体何なのか!なぜそんなモノが必要なのか!





やぁ、ここまで読んでくれたあなた!その精神的耐久力に僕は感動するし、おめでとう、これからはこんな狂気な話は出てこないから安心して欲しい:D。ギャグのようだけど、上の話は、今後どうしても必要になる前置記法に慣れてもらうためには仕方なかったんだ。実はもっともっと説明しないといけないことがあるんだけど、Lispの説明をしだしたら長くなる、ここでは単にLispへの病的な恐怖心を取り除いてもらい、「わかんないところはわかんない、とりあえずサンプルコードの値を変えるところから初めて遊ぼう」と思っていただければ幸いだ。そろそろIncanterを利用していくことにしよう。おっと、一つだけ事前にdocという関数について覚えてもらいたいな。何かわからない関数があれば(doc 関数名)とやると、その関数の説明を見ることが出来る。docは君の強力な味方、わからないことがあればとにかくdocを試してみよう!


まず、Incanterの様々な統計ライブラリを利用するために、「このライブラリを使用するよ」というのを処理系に指定して教えてあげないといけません。次のコマンドをREPLに打ち込んで下さい。

(use '(incanter core stats charts io datasets))

useで処理系に引数として指定したライブラリを利用することを教えてあげる。coreはIncanterのまさにコア部分、何をするにもこれがないと始まらない。statsは統計処理、chartsはグラフ描画、ioはファイル入出力のライブラリ、datasetsはサンプルデータセットです。とりあえずこれくらい用意しておけば十分でしょう。次のようにデータセットを用意します。

(dataset ["x1" "x2" "x3"] [ [1 2 3][4 5 6] ])

これで2行3列のデータが出来ます。Excelで表示すると

x1 x2 x3
1 2 3
4 5 6

という感じになります。
これをdataという変数に束縛します。

(def data (dataset ["x1" "x2" "x3"] [ [1 2 3][4 5 6] ]))

このデータをExcelのようなインターフェイスで表示させましょう。

(view data)

簡単ですね。このように、view関数を使うとデータをGUIで表示できます。変数dataに先程の表データを束縛したので、それをファイル入出力してみましょう。

(save data "test.csv")
(read-dataset "test.csv" :header true)

なんとこれだけでCSV形式でのファイルの入出力が可能です。非常に簡単ですね。


 次に、平均と標準偏差を求めてみましょう。Incanterにはdatasetsというライブラリにサンプルデータを用意しています。datasetsは既にuseしておきましたね。サンプルデータはget-dataset関数で取得します。今回はcarsという車の速度と走行距離のデータを利用します。サンプルデータの中からcarsのデータを取得するには

(get-dataset :cars)

とします。するとspeed, distの2列50行のデータが取得出来ます。このデータのうちspeed列のデータだけ取得したい場合は$を利用します。

($ :speed (get-dataset :cars))

これをまたもやdataに束縛し、平均と標準偏差を得るには、各々mean, sd関数を用います、

(def data($ :speed (get-dataset :cars)))
(str "mean = "(mean data) " :: SD = " (sd data))
>"mean = 15.4 :: SD = 5.2876444352347844"

簡単ですね。他細々としたデータ操作について書いておきます。

($where {:speed {> 10}} data);carsデータからspeed列が10より上のデータだけ取得

(def data (get-dataset :iris));irisデータをdataに束縛
($where {:Species "setosa"} data);irisデータからSpecies列がsetosaの行だけ取得

(def data (get-dataset :hair-eye-color));髪と目の色のデータをdataに束縛
($order :count :desc data);count列を降順でソート


データの描画も簡単です。散布図を書いてみましょう。scatter-plotという関数で散布図が描けます。

(view (scatter-plot :Sepal.Length :Sepal.Width :data (get-dataset :iris)))

簡単ですが、もっとかっこいい図を書きたいですね。doc関数を利用して、オプションを調べて追加してみましょう。

(view (scatter-plot :Sepal.Length :Sepal.Width :data (get-dataset :iris)
:group-by
:Species
:title "Fisher Iris Data"
:x-label "Sepal Length (cm)"
:y-label "Sepal Width (cm)"))


棒グラフも描きましょう。

(view (bar-chart :Species :Sepal.Length :data (get-dataset :iris)))

(view (bar-chart :hair :count :group-by :eye :legend true :data (get-dataset :hair-eye-color)))


関数のグラフも簡単に描けます。

(view (function-plot sin -10 10))


綺麗なグラフが簡単にかけましたね。これを画像として保存する場合もsave関数を用います。save関数を用いるときは、次のように保存時の名前を指定します(ちなみにsave関数で画像を保存する場合はpngしか出来ないようです、多分)。

(save (function-plot sin -10 10) "func.png")


ちょっと発展的な話題として、IncanterからMongoDBを利用するのにチャレンジしてみましょう。

(use 'incanter.mongodb)
(use 'somnium.congomongo)
(mongo! :db "mydb")
(view (fetch-dataset :cars))


 お疲れ様でした!Lisp系初体験の方、如何でした?巷で言われる程難しくはなかったなー簡単に出来そうだなーという感じを持っていただければ幸いです。Lispハッカーの皆さん、如何でした?Incanterで統計解析をやる気が漲ってきませんか?簡単な計算からファイル入出力、描画、DB操作と一通りよくある操作をやってきました。皆さんがIncanterを利用し、素敵な統計解析アプリを作って下さり、社会(と重点的に僕)をもっとハッピーにしてくれることを願ってます。不明点があればご質問下さい。では、楽しいLispによる統計解析ライフを!

*1:exe版、私が試したところかなりバギーな感じなので、jar利用をお薦めします

Clojureのビルドツール"Leiningen"を使ってみた

 LeiningenはClojureの標準的な総合ビルドツールで、単体で動作するjarファイルを簡単に吐けたり、依存関係を適切に自動設定してくれたりと何かと便利です。Leiningenは簡単にインストールできますし、ついでにClojureも一緒に入れてくれるので、色々設定してClojure単体でインストールするより作業は楽です。
 この記事ではLeiningenをインストールし、ダブルクリックでGUIが立ち上がるjarファイル作成するところまでをご紹介したいと思います。
なお、実行環境はUbuntu10.10です。
(※Ubuntu10.10以前だと、標準ではopenjdk-6がインストールされているかもしれません。事前にsun-java6-jdkをインストールする必要があります)


1.Leiningenのインストール
 https://github.com/technomancy/leiningen/blob/master/README.md
Download the script.をダウンロードする。ダウンロードしたleinファイルをPATHの通ったディレクトリに置き、実行権限を付与します。
・PATHの設定
 PATHが通っているディレクトリは、ターミナルで"echo $PATH"とコマンドを打てば表示されます。今回は/userName/LeiningenというディレクトリにPATHを通したかったので、PATH=$PATH:/userName/Leiningen"とコマンドを打ってPATHを通しました。
・プログラムの実行権限付与
 実行権限を付与するコマンドを打つか、Ubuntuであれば、leinを右クリック→プロパティ→アクセス権→「実行:□プログラムとして実行できる」にチェックを入れると、プログラムとして動作させることができます。ここまでの設定が終われば、"lein self-install"とコマンドを打つことによって、Leiningenが/userName/.leinディレクトリにインストールされます。
※ディレクトリ名の先頭に.がついているディレクトリは隠しディレクトリです。Ctrl + Hか、メニューバーから表示→□隠しファイルを表示する、にチェックすることによって表示されます。
ここで"lein version"とコマンドを打って、Leiningenのバージョンが確認出来たら成功です。(2011/7/30現在、Leiningen 1.6.1がインストールされます)


2.プロジェクトの作成
 jarファイルをダブルクリックすると、GUIJavaのSwingを利用)で"hello Clojure!"とダイアログを出すアプリケーションを作成してみましょう。
lein new [プロジェクト名]で新規プロジェクトを作成することが出来ます。このプロジェクト単位でビルドします。ここではMyTestプロジェクトを作成するために"lein new MyTest"とコマンドを打ちました。すると/userName/LeiningenディレクトリにMyTestディレクトリが作成されます。/userName/Leiningen/MyTest/src/Mytestにcore.cljが作成されているはずです(出来ていなければ、何か設定がおかしい)。このcore.cljをエディタで開き、次のコードを書いて保存してください。

(ns MyTest.core
  (:gen-class))

(defn -main [& args]
  (. javax.swing.JOptionPane (showMessageDialog nil "hello Clojure!")))

コードをざっくり読んでみると、main関数でjavax.swingのメセージダイアログを呼ぶ処理をしていますね。
 次に、/userName/Leiningen/MyTest/project.cljを開き、次のコードを書いて保存してください。

(defproject MyTest "userName"
  :description "FIXME: write description"
  :dependencies [[org.clojure/clojure "1.2.1"]
               [org.clojure/clojure-contrib "1.2.0"]]   
  :main MyTest.core)

このコードは、MyTest.coreファイルのmain関数をエントリポイントとしてMyTest.jarを作成するものです。
これで設定は完了です。コンパイルしましょう。
今/userName/Leiningen/がカレントディレクトリだと思いますが、/userName/Leiningen/MyTest/に降りて、"lein uberjar"とコマンドを打ちます。するとMyTest-userName-standalone.jarが生成されます。
" java -jar MyTest-userName-standalone.jar"とコマンドを打ち、無事"hello Clojure!"というダイアログが表示出来たのを確認出来たら終了です。お疲れ様でした!


 如何でしたか?結構簡単にClojureから単体実行可能ファイルが生成できますね。Windowsなどでは、生成されたjarファイルをダブルクリックするだけで実行できるため、配布も実行も簡単です。もちろんJavaですから、例えばUbuntuで生成したアプリケーションがWindowsでもMacでも動きます(と信じましょう:D)!


 たまたまこれを書いている最中、『「日本語形態素解析MeCabClojure から呼ぶ方法」書きました --- Using MeCab the Japanese Morphological Analyzer from Clojurehttp://lilyx.net/2011/07/30/using-mecab-the-japanese-morphological-analyzer-from-clojure/)』という素晴らしい記事が公開されました。MeCabJavaから叩けることにより、Clojureを用いて自然言語処理アプリケーションを作成する敷居が随分下がったと思います。また、次の様なClojureNLPで用いる、簡潔かつ明確な利点についてのコメントもあります。

@mhagiwara Masato Hagiwara
NLP に向いているかどうかは分かりませんが、個人的に言語仕様(というか Lisp)が好きなのと、並列計算がし易いのと、Java の膨大な資産を活用できる点に惚れ込んでいます。 RT @nokuno ClosureでNLPって向いてるの?
http://twitter.com/#!/mhagiwara/status/97152499454185472

Clojureでどんどん実用的なアプリケーションを作成、公開して行きましょう!