イントロ
最近の機械学習などのデータ分析に関する情報のやり取りは、
コードに限らずグラフや表、数式も出力可能なJupyter Notebookが主流ですよね。
Jupyter使いたい、Pythonが憎い?とお嘆きのF#erにも朗報が。
MicrosoftがJupyter Notebookのweb版のAzure Notebookというサービスがあるんです。
ただ、まだpreview版のせいかレスポンスがもっさり。
なのでAzure上で動いているIFSharpというF#が実行可能なJupyterをDockerコンテナ上に配置して
ローカルでも利用出来るようにします。
(もちろんローカルにPython一式がインストールしてある方はifsharp.exeをそのまま実行するやり方もあります)
=> 今回はこれで行きます
使用環境
Ubuntu 16.04 LTSDocker CE- Windows 10
- Anaconda
環境構築
IFSharp.exeをここからダウンロードして起動してください。
そのあとJupyter Notebookを起動すればOK。
Dockerをインストール。以下はUbuntuで実行していますが、他のOSはそれぞれのDockerのインストール手順に従ってください。
適当な作業フォルダにIFSharpをクローンしてコンテナを起動。
FOLDERNAMEはDockerと共有したいフォルダ名に置き換えてください。
実行後URLが表示されるのでクリックしてブラウザが起動しJupyterの画面が開きます。
これで完了。くれぐれもPythonを選ばないように。
使ってみる
Github上のサンプルもありますが、
今までFSIで実行したのと違いや気になったことをまとめておきます。
パッケージのインポート方法
Paketを用いて以下のようにかけます。paket.dependenciesみたいな感じですね。
公式ドキュメントは#Nでnuget出来るよって書いてあるんですけど現在は非推奨のようです。
#load "Paket.fsx"
Paket.Package ["Newtonsoft.Json";"Deedle"; "MathNet.Numerics"; "MathNet.Numerics.FSharp"; ]
#load "Paket.Generated.Refs.fsx"
open Deedle
open MathNet.Numerics
open Newtonsoft.Json
open MathNet.Numerics.LinearAlgebra
グラフの出力
F#でグラフの出力というと、Windows.Formsを用いたFSharp.Chartingが真っ先に思い浮かぶんですが、
AzureやDockerコンテナ上で動いているIFSharp上ではPaketで持ってきてもFSharp.Chartingは使えません。
(Gtk周りのエラーが出ます)
サンプルにもあるようにXPlotを使うのがよいみたいです。
#load "XPlot.Plotly.Paket.fsx"
#load "XPlot.Plotly.fsx"
open FSharp.Core
open XPlot.Plotly
let x = [for i in -10.0 .. 10.0 -> (i, 1.0 / (1.0 + exp -i))]
Chart.Line x
表はIFSharp.Utilを使う DeedleのData Frameを表示する
PythonでいうところのPandasのようなイメージで、Deedleで作成したFrameを表としてJupyter上に表示させたいのですが、今のところ公式ではサポートしてません。そこでIFSharp.Utilを用いることでレコード型を表示出来るようです。
(2019/8/11 追記)
Formatterはこちらのものを使用。
機械学習でよく使うTitanicはこちらからダウンロードできます。
初期設定
GithubのIssueにかいてありますが、
このファイルをIFSharpフォルダにおいてあげてよみこめば出力可能。
module DeedleFormat
+ #I @"packages\Deedle\lib\net45"
+ #r "Deedle.dll"
+ #r "IfSharp.Kernel.dll"
open System
表の出力
Deedleのこちらの例を試しに実行してみます。
#load "DeedleFormat.fsx"
open Deedle
open FSharp.Core
// Read Titanic data & group rows by 'Pclass'
let titanic = Frame.ReadCsv(@"..\..\data\train.csv").GroupRowsBy<int>("Pclass")
// Get 'Survived' column and count survival count per clsas
let byClass =
titanic.GetColumn<bool>("Survived")
|> Series.applyLevel fst (fun s ->
// Get counts for 'True' and 'False' values of 'Survived'
series (Seq.countBy id s.Values))
// Create frame with 'Pclass' as row and 'Died' & 'Survived' columns
|> Frame.ofRows
|> Frame.sortRowsByKey
|> Frame.indexColsWith ["Died"; "Survived"]
// Add column with Total number of males/females on Titanic
byClass?Total <- byClass?Died + byClass?Survived
// Build a data frame with nice summary of rates in percents
frame [ "Died (%)" => round (byClass?Died / byClass?Total * 100.0)
"Survived (%)" => round (byClass?Survived / byClass?Total * 100.0) ]
byClass
実行結果はこちら
まとめ
Alt-PythonとしてF#使ってみるといいのではないでしょうか!