🦊

Pyodideでブラウザサイドで機械学習を実行する

2021/10/03に公開

概要

Pyodideに実装されたScikit-learnでデータセットをロードし、機械学習をブラウザサイドで実行してみます。

Pythonでの学習コード

今回はbreast_cancerデータセットを使い、OneClassSVMを学習させてみます。

import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.svm import OneClassSVM

dataset = load_breast_cancer()

x_train, x_test, y_train, y_test = train_test_split(
    dataset.data,
    dataset.target,
    test_size=0.3,
    random_state=36
)

scaler = StandardScaler().fit(x_train)
x_train_std = scaler.transform(x_train)
x_test_std = scaler.transform(x_test)

detector = OneClassSVM().fit(x_train_std)
print(detector.predict(x_test_std))

今回はPyodideのAPIを叩いたりしていないので、普通にローカルでPythonで実行することもできます。実際に使う場合、JavaScriptと値をやり取りしたりDOMを操作するとどうしてもJSと密結合になってしまうので、おそらくローカルではテストできません(未検証)。学習用コードは関数として読み込み部分と別に切り出しておくとよいでしょう。

JavaScriptコード

Promise.thenを使うサンプルが多いですが、下記のようにawaitベースで書くこともできます。

また今回はPythonコードは別ファイル(train.py)としてホストしておき、JavaScriptで取得して中の文字列を取り出してrunPythonに渡しています。

window.onload = async () => {
    const res = await window.fetch("public/pyscripts/train.py");
    const pycode = await res.text();

    const pyodide = await loadPyodide({
        indexURL: "https://cdn.jsdelivr.net/pyodide/v0.18.1/full/",
    });

    await pyodide.loadPackage("numpy");
    await pyodide.loadPackage("scikit-learn");

    console.log("Pyodide is ready.");

    await pyodide.runPython(pycode);
}

実行結果

適当なサーバにホストしてブラウザで開きF12でコンソールを見ると、実行結果が出力されます。Pythonコードのprintはconsole.logに出力されるので、コンソールを見るとPythonをローカルで実行したときと同じ結果が出力されます。

PyodideにはDOMを操作する機能もあるので、出力結果に応じてテキストボックスの値を書き換えるとかもできます。

まとめ

PyodideでScikit-learnのOneClassSVMを学習させることができました。学習もクライアントサイドでできるのはよいですね。

今回はありもののデータセットをダウンロードして学習させましたが、サーバサイドをちゃんと実装してやればブラウザサイドで学習や推論を行うこともできます。OneClassSVMやEmpiricalCovarianceのような軽いモデルをPlotlyと組み合わせて、グラフの選択領域でラベルをつけてブラウザサイドでインタラクティブに学習をさせたりすると便利かなと思います。

Discussion