Edited at

F#でとにかくJupyterが使いたい人に捧ぐIFSharp


イントロ

最近の機械学習などのデータ分析に関する情報のやり取りは、

コードに限らずグラフや表、数式も出力可能なJupyter Notebookが主流ですよね。

Jupyter使いたい、Pythonが憎い?とお嘆きのF#erにも朗報が。

MicrosoftがJupyter Notebookのweb版のAzure Notebookというサービスがあるんです。

ただ、まだpreview版のせいかレスポンスがもっさり。

なのでAzure上で動いているIFSharpというF#が実行可能なJupyterをDockerコンテナ上に配置して

ローカルでも利用出来るようにします。


(もちろんローカルにPython一式がインストールしてある方はifsharp.exeをそのまま実行するやり方もあります)

=> 今回はこれで行きます


使用環境


  • Ubuntu 16.04 LTS

  • Docker CE

  • Windows 10

  • Anaconda


環境構築

IFSharp.exeをここからダウンロードして起動してください。

そのあとJupyter Notebookを起動すればOK。

Dockerをインストール。以下はUbuntuで実行していますが、他のOSはそれぞれのDockerのインストール手順に従ってください。

適当な作業フォルダにIFSharpをクローンしてコンテナを起動。

FOLDERNAMEはDockerと共有したいフォルダ名に置き換えてください。

実行後URLが表示されるのでクリックしてブラウザが起動しJupyterの画面が開きます。

これで完了。くれぐれもPythonを選ばないように。

image.png


使ってみる

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

image.png


表はIFSharp.Utilを使う DeedleのData Frameを表示する

PythonでいうところのPandasのようなイメージで、Deedleで作成したFrameを表としてJupyter上に表示させたいのですが、今のところ公式ではサポートしてません。そこでIFSharp.Utilを用いることでレコード型を表示出来るようです。

(2019/8/11 追記)

Formatterはこちらのものを使用。

機械学習でよく使うTitanicはこちらからダウンロードできます。


初期設定

GithubのIssueにかいてありますが、

このファイルをIFSharpフォルダにおいてあげてよみこめば出力可能。


DeedleFormat.fsx

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

実行結果はこちら

image.png


まとめ

Alt-PythonとしてF#使ってみるといいのではないでしょうか!