🔍

Kotlinでデータサイエンストライアル

2022/12/22に公開約10,100字

本記事はオプティマインド Location Tech Advent Calendar 2022の22日目の記事となります。

0. 初めに

興味から敢えてKotlinを使ってデータ分析系のタスクがどの程度できるのかを知るために調査、実験したという趣旨です。環境構築や使えるライブラリ、Kaggleのチュートリアルを試すといった内容を記載します。データ分析において一般的に使用される言語ではないので、データ分析の一般的なことが知りたい方に参考になる情報はあまり含まれないと思います。一方、Java資産の可搬性の高さを理由に使用を検討されている方や、Kotlin愛で使いたい方にとって、何かしらの参考になればと思います。なお、Kotlinのデータ分析系ライブラリは発展途中のものが多く、お読みいただいている時点で古い情報が含まれる可能性があることをご了承ください。

1. 環境構築

データ分析においては、データを探索的に操作可能であることが嬉しい場合が多いかと思うため、本稿ではインタラクティブに作業可能なKotlinカーネルを使用したJupyter(Lab)環境で進めることとします。

JupyterのKotlinカーネル環境構築

  • macOS Monterey 12.6 / Intel Core i7
  • Python 3.10.6

Jupyter Lab[1] 及び kotlin-jupyter を使用することにします。
pipenvコマンド仮想環境を作成後、以下を入力してインストールします。

pip install jupyterlab kotlin-jupyter-kernel

インストールに成功したら、次のコマンドでJupyterLabを起動します。停止は Ctrl+C です。

jupyter lab

localhost:8888 にJupyterLabサーバが起動し、ブラウザで以下のようなページが開けると思います。そこから、KotlinカーネルのNotebookを開けます。

Hello Worldしてみます。コード補完はデフォルトでTABキーのようです。

Good.

なお、:help でKotlinカーネルに関するヘルプを表示し、ライブラリ等の情報を見ることができます。

ちなみに(Colabについて)

2022/12/18現在、Google ColaboratoryでKotlinカーネルはサポートされていない様子です(参考)。ちなみにRはサポートされている様子で、例えば以下のURLを開く等で、Rカーネルのnotebookが作成できるようです https://colab.research.google.com/notebook#create=true&language=r)。

2. 依存アーティファクトのinstall

データ分析における現状のまとも(?)なKotlinのユースケースはJVM資産の再利用にあると思います。本節でやり方を書きます。

@file:Repository(<absolute-path>)でアーティファクトレポジトリを指定できます(参考)[2]。MavenCentralの場合は以下。

@file:Repository("https://repo.maven.org/maven2")

また、@file:DependsOn(<coordinates>)でアーティファクトをinstallできます。PythonでいうNumPy相当のND4jを入れる場合は以下。

@file:DependsOn("org.nd4j:nd4j-api:0.9.1")
@file:DependsOn("org.nd4j:nd4j-native:0.9.1")
@file:DependsOn("org.nd4j:nd4j-native-platform:0.9.1")

3. Kaggleのタイタニックを試す

Kaggleでは超お馴染みのチュートリアルTitanicをKotlinでやってみて、ライブラリの基本的な使い方を試します。なお、Kaggleで提供されるNotebookも使用可能言語はPython,Rのみのようなので、上記で作成したローカル環境で実行します。なお、本節はこちらのPythonの書籍を参考にさせていただいています。

データ読み込みと概観

まずはデータ読み込みと概観です。kotlin-jupyter にバンドルされている dataframe というものを使用し、CSVファイル等の読み込みを行うことができます。これを使用するための Magic は以下。

%use dataframe

この dataframe は pandas にインスパイアされているようで、例えば以下のようにファイルを読み込んでデータを表示することができます。

val df = DataFrame.read("./data/train.csv")
df.head()

読み込んだデータの concatdescribe などもできます。

特徴量エンジニアリング

次に特徴量エンジニアリングをします。

Kotlinのdataframeでは、プロパティでカラムを取得することができます。↓こんな感じ。

(ちなみに dataDf["Age"] のようにも書けます。)

これが平均値 mean、標準偏差 std など統計値を取得するメソッドを持っていたりします。

欠損値補完fillNAもできます。ただこの時、静的型付け言語らしく、各カラムの型で補完する必要があります(例えばDouble型のカラムにInt型の値で補完しようとするとエラー)。

また、カラムの各値を変更replaceすることができますが、型を変えて符号化(例えば"男性"を0に、"女性"を1に変換)する場合には、convertを使う必要がありそうです。

不要なカラムはremoveで落とせます。selectもあります。

ちなみにDataFrameオブジェクトはImmutableで、上記の各メソッドの戻り値は新しいインスタンスです。

グラフ描画

探索的にデータを分析するにあたりデータ可視化は重要な要素です。グラフの描画には lets-plot という、kotlin-jupyter にバンドルされているライブラリが使えます。これを使うmagicは以下です。

%use lets-plot

試しに、Ageに関してヒストグラムと性別ごとのボックスプロットを眺めてみようと思いますが、以下のように簡単に描画できます。

次のようにちょっと凝った見た目にもできます。ドキュメントを参考に色々試してみると面白そうです。

データ書き出し

整形した訓練、テストデータをそれぞれCSVファイルとして書き出しておきます。

機械学習

最後に、学習モデルを作成してみたいと思います。ライブラリの選択肢は様々ですが、KotlinDLというKotlin純正でKerasインスパイアのライブラリを触ってみたいと思います。

例えば次のようにしてDataFrameをDatasetインターフェースに変換することで、本ライブラリで使用するデータとして使うことができます。

import org.jetbrains.kotlinx.dataframe.DataFrame
import org.jetbrains.kotlinx.dataframe.api.remove
import org.jetbrains.kotlinx.dataframe.api.rows
import org.jetbrains.kotlinx.dl.api.core.Sequential
import org.jetbrains.kotlinx.dl.api.core.WritingMode
import org.jetbrains.kotlinx.dl.api.core.layer.core.Input
import org.jetbrains.kotlinx.dl.api.core.layer.core.Dense
import org.jetbrains.kotlinx.dl.api.core.loss.Losses
import org.jetbrains.kotlinx.dl.api.core.metric.Metrics
import org.jetbrains.kotlinx.dl.api.core.optimizer.Adam
import org.jetbrains.kotlinx.dl.api.core.summary.printSummary
import org.jetbrains.kotlinx.dl.dataset.OnHeapDataset
import org.jetbrains.kotlinx.dl.dataset.fashionMnist
import java.io.File

fun <T> DataFrame<T>.toOnHeapDataset(labelColumnName: String): OnHeapDataset {
    return OnHeapDataset.create(
        dataframe = this,
        yColumn = labelColumnName
    )
}

fun OnHeapDataset.Companion.create(
    dataframe: DataFrame<Any?>,
    yColumn: String
): OnHeapDataset {
    fun extractX(): Array<FloatArray> =
        dataframe.remove(yColumn).rows()
            .map { (it.values() as List<Float>).toFloatArray() }.toTypedArray()

    fun extractY(): FloatArray =
        dataframe.get { yColumn<Float>() }.toList().toFloatArray()

    return create(
        ::extractX,
        ::extractY
    )
}

モデルも次のように(Kerasっぽく?)構築できます。

ちなみに上記はこのページを参考にしています。

ソース

以上のノートブックはこちらに置いておきます。
https://github.com/shunsuke-tsumori/kotlin_analytics_helloworld

ライブラリのドキュメント

4. 他ツールやライブラリ

  • kotlin-notebook(IntelliJプラグイン)
    IntelliJのプラグインです。今回はブラウザを使用したため使用していませんでした。コードインサイト等の機能があり、ブラウザよりこちらを使った方が作業効率は上がるかも知れません。

  • krangl
    これもkotlin-jupyter にバンドルされているようです。magicは以下。

%use krangl

5. 終わりに

本稿では、Kotlinでデータ分析する場合の環境構築の例や使い方の初歩的な例について書きました。

調査及び触ってみた感想ですが、データ分析にKotlinを使用するにあたっては、ライブラリの豊富さにおいてPythonに見劣りする点と、GoogleColaboratoryでKotlinカーネルがサポートされていない点は痛いかなと思います。また、公式ドキュメント以外の情報が乏しい点は辛いです。一方で、使えるものの使いやすさに関して、dataframe等のライブラリは予想より出来がよく使いやすいなと思いました。期待してJetBrains社のデータ分析分野ライブラリの開発動向をウォッチしつつ、遊びで使っていきたいと思いました。

最後に、お読みいただきありがとうございました。誤記や誤情報などありましたらお知らせください。

6. 宣伝

弊社採用を強化中です。詳しくは下記の採用資料をご覧ください。また、カジュアル面談も大歓迎ですので、気軽にお声がけください。

https://recruit.optimind.tech/

7. その他参考・関連情報

脚注
  1. Jupyter NotebookでもKotlinカーネル動作しました。 ↩︎

  2. mavenローカルレポジトリは@file:Repository("*mavenLocal")で指定できるようです。また、試せていないのですが、NuxusRepositoryManager等で立てた社内リポジトリ等も指定可能かと思います。 ↩︎

Discussion

ログインするとコメントできます