🤖

deno で機械学習

2021/09/15に公開

はじめに

最近、deno が面白くなり始めています。deno はコマンドラインバイナリを1つインストールすれば、import によりパッケージの読み込みはインターネットからダウンロードしてキャッシュされ、開発者が package.json を書く事もなく、とてもお手軽に TypeScript を書くことができます。

もし、機械学習をやりたいとして、事前準備(npm でインストールしたり、conda/pip 等で依存物をインストールしたり)が大幅に削減できるなら、とても便利だと思いませんか?

deno で機械学習

deno で機械学習と聞くと tensorflow.js を使いたくなりますが、残念ながら現在はまだ deno で tensorflow.js を扱える様にはなっていません。しかし deno 1.8 では GPU を扱う為の機能が追加されており、ジワジワではありますが目標に向かって進んでいる状況です

https://www.infoworld.com/article/3610391/deno-18-preps-for-gpu-accelerated-machine-learning.html

また tensorflow.jsWebAssembly に対応中らしいので、いずれ deno 単体で GPU をサポートした tensorflow.js が動く様になるかも知れませんね。

じゃあまだ機械学習は早い?

と思われるかもしれませんが、tensorflow ほど大規模な物は無理ではあれど、dklearn の様な線形回帰だけサポートしている様な小さな物は幾らかある様です。

https://deno.land/x/dklearn@0.0.3

試してみる

試しに以下のコードを書きました。

import { LinearRegression } from 'https://deno.land/x/dklearn@0.0.3/linear-regression.ts';
import { Matrix } from 'https://deno.land/x/math@v1.1.0/matrix/matrix.ts';
import { readCSVObjects } from 'https://deno.land/x/csv@v0.6.0/mod.ts';

export const runIrisExample = async () => {
    const f = await Deno.open('./data/iris.csv');
    const Xtmp: Array<number> = [];
    const ytmp: Array<number> = [];
    const options = {
        columnSeparator: ",",
        lineSeparator: "\n",
    }
    const nameMap = new Map([
      ['Iris-setosa', 1],
      ['Iris-versicolor', 2],
      ['Iris-virginica', 3],
    ]);
    for await (const obj of readCSVObjects(f, options)) {
        Xtmp.push(+obj.SepalLength);
        ytmp.push((nameMap.get(obj?.Name) as number) / 3);
    }
    f.close();
    const Xtrain = new Matrix([Xtmp]);
    const ytrain = new Matrix([ytmp]);
    const linReg = new LinearRegression()
    const [W, B] = linReg.train(Xtrain, ytrain, 15000, 0, 0, 0.001, true)
    const value = 6.7 // がくの長さが 6.7 は(おそらく) virginica
    const result = linReg.predict(value, W, B);
    const name = [...nameMap.entries()]?.find(([_, v]) => v.toFixed() == ((result * 3 + 0.5)).toFixed())![0];
    console.log(`Result: ${name}`)
}

runIrisExample()

このコードは data/iris.csv を読み込んで、「あやめ」という花の「がく」の長さから、setosa (セトサ)種、versicolor (バージカラー)種、virginica (バージニカ)種の何れかを推測するコードです。

CSV は以下のフォーマットになっている物をご用意下さい。

SepalLength,SepalWidth,PetalLength,PetalWidth,Name
5.1,3.5,1.4,0.2,Iris-setosa
4.9,3.0,1.4,0.2,Iris-setosa
4.7,3.2,1.3,0.2,Iris-setosa
...

実行すると以下の様に表示されます。

deno run --allow-read main.ts

※本来は学習に使うデータと推論に使うデータは分け、さらにテストデータから正解率を出すのが正しいのですが、本記事ではそこは省略させて頂きます。

事前準備は要りません。ただ上記の TypeScript のファイルを main.ts として保存し、どこからか CSV ファイルを持ってくれば、コマンド1つで試すことができます。とても便利ですね。

さいごに

deno で機械学習ができる dklearn というライブラリを紹介しました。deno はまだまだ発展途上ではありますが、これからどんどん面白くなっていく領域なので要注目だと思います。

Discussion