JavaScript
機械学習
MachineLearning
DeepLearning
TensorFlow
More than 1 year has passed since last update.


最近の興味



機械学習



私のレベル


  • 昨年から年末年始にかけてCourseraの機械学習コースを修了

  • 超基礎的なアルゴリズムがわかる

  • 数式をみても説明ができる(厳密ではない…)

  • 詳細はこちら



JavaScriptで機械学習?



JavaScriptで機械学習?


  • Python/Rじゃないの?

  • また「JSできもできちゃいました」系のやつ?



JavaScriptで機械学習をするメリット



JavaScriptで機械学習をするメリット

大きく2つ


  1. JavaScriptが使える

  2. 環境構築不要でGPUが使える



1. JavaScriptが使える



1. JavaScriptが使える


  • JavaScriptは敷居がとっても低い言語

  • 誰でも一度は書いたことがある

  • ブラウザ開発者がなれた言語

  • これはまあわからなくはない



1. JavaScriptが使える

ライブラリも結構ある。

デモ等



1. JavaScriptが使える


が、決定的ではない。


また、機械学習コミュニティもPython/Rと比べ物にならない。

=>やっぱりPythonでいいのでは?



2. 環境構築不要でGPUが使える



2. 環境構築不要でGPUが使える


  • 今日のメインはこっち

  • GPUを手軽に使うことでプロトタイピングの高速化

  • いろんな敷居が下がる



GPUとは?


  • 元々画像処理のためのハード

  • 高画質の動画を適切に処理するために、並列計算に特化したアーキテクチャ



なぜGPUの話がでてくる?


  • Deep Learningをやりたいのであれば、コンピュータの性能を無視することはできない

  • むしろ、計算性能の向上がDeep Learningを支えている

  • =>「GPUの並列処理できるアーキテクチャを計算処理に利用してしまおう」

  • =>GPGPU (General-purpose computing on graphics processing units)

  • =>これがDeep Learningで使われている (大量のデータを扱う場合/ニューラルネットの層が何層にもなる場合)



GPGPUするには?



GPUを用意する

GPUメーカー2強


  • NVIDIA社: (GeForce/Quadro/Tesla)

  • AMD社: (Radeon/FirePro/FireStream)



開発環境を用意する

GPUにアクセスするための開発環境/標準規格/フレームワーク/言語/APIがある


  • CUDA

  • OpenCL

  • OpenGL

  • DirectX

  • etc



例.CUDA


  • GPU購入(高いもので10万など)

  • CUDAインストール

  • cuDNNインストール(Deep Learning用のCUDAライブラリ)

  • NVIDIAドライバーのセットアップ

  • TensorFlow等フレームワークの環境構築

  • ↑Dockerコンテナ等でつくる(好み)

  • しかも、(CUDAに関しては)NVIDIA製のGPUを搭載しているハードウェアでしか使えない

  • もしくはクラウドを使うという手もある(AWS/Azure/GCP。お金はかかるが時間は節約できる)

  • =>インフラ含めた環境構築が必要



大変



大変 is


  • それなりに準備が必要

  • 開発環境への理解が必要

  • 初学者には敷居が高い



それ、JavaScriptとブラウザでできますよ



WebGL



WebGL


  • OpenGLをJavaScriptに移植したもの


    • HTML上の画像や動画を簡単にテクスチャにできるように拡張してある

    • 関数名がJSっぽくなっている



  • ブラウザからローカルマシンのGPUにアクセスできるAPI

  • 閲覧者のOS/ハードウェアに関係なくクロスプラットフォーム

  • =>このGPU資産を演算に使う

  • =>GPGPU



ブラウザからGPUを使って機械学習できるライブラリ

少ないが、いくつかある(&過去にもあった)



deeplearn.js



deeplearn.js


  • Google製である

  • WebGLを使ってGPUを使用した機械学習ができる

  • 他のライブラリとは異なり、推論だけでなく学習も行うことができる

  • TensorFlowといい感じに組み合わせて使うことができる



ベンチマーク1

スクリーンショット 2018-01-16 13.01.36.png



ベンチマーク2

スクリーンショット 2018-01-16 12.44.44.png



使ってみた



KaggleのTitanicチュートリアル



TypeScript環境の構築



  • GitHubにスターターがあるのでそれを真似ればOK

  • TypeScriptなので、フロントエンドの人はいつものようにカスタマイズしてもOK


package.json

{

"name": "kaggle-titanic-deeplearn-js",
"version": "1.0.0",
"main": "main.js",
"scripts": {
"prep": "yarn && mkdirp dist",
"watch": "watchify main.ts -p [tsify] -v --debug -o dist/bundle.js",
"build": "browserify main.ts -p [tsify] -o dist/bundle.js",
"lint": "tslint -p . -t verbose",
"deploy": "yarn build && uglifyjs dist/bundle.js -c -m -o dist/bundle.min.js"
},
"dependencies": {
"deeplearn": "^0.4.1"
},
"devDependencies": {
"csv": "^2.0.0",
"mkdirp": "~0.5.1",
"tsify": "~3.0.3",
"tslint": "~5.8.0",
"typescript": "~2.6.1",
"uglifyjs": "~2.4.11",
"watchify": "~3.9.0"
}
}


tsconfig.json

{

"compilerOptions": {
"module": "commonjs",
"sourceMap": true,
"preserveConstEnums": true,
"declaration": true,
"target": "es5",
"lib": ["es2015", "dom"],
"outDir": "./dist"
}
}



データのクレンジング


  • 不要なデータの削除

  • 欠損値補完

  • スケーリング

  • 文字列の変数化



実装詳細


  • 多層パーセプトロン

  • 今回は入力、出力を合わせて3層だけ

  • Optimizerは最急降下法(SGD)のみ

  • 学習率、イテレーション数などはSGDが収束するように微調整した


main.ts

import {

Array1D,
Array2D,
NDArrayMathGPU,
NDArrayMath,
ENV,
Scalar,
Session,
SGDOptimizer,
InCPUMemoryShuffledInputProviderBuilder,
CostReduction,
Graph,
Tensor,
NDArray
} from 'deeplearn';

import {trainX} from './trainX';
import {trainY} from './trainY';
import {testX} from './testX';

const graph: Graph = new Graph();
const x: Tensor = graph.placeholder("x", [7]);
const t: Tensor = graph.placeholder('t', []);

// input layer - hidden layer
const w0: Tensor = graph.variable("w0", Array2D.randNormal([7, 7]));
const b0: Tensor = graph.variable("b0", Scalar.randNormal([]));
const h0: Tensor = graph.relu(graph.add(graph.matmul(x, w0), b0));

// hidden layer - output layer
const w1: Tensor = graph.variable("w1", Array2D.randNormal([7, 1]));
const b1: Tensor = graph.variable("b1", Scalar.randNormal([]));
const y: Tensor = graph.sigmoid(graph.reshape(graph.add(graph.matmul(h0, w1), b1), []));

const cost: Tensor = graph.meanSquaredCost(y, t);

const math: NDArrayMath = ENV.math;
const session: Session = new Session(graph, math);

math.scope((keep, track) => {
const xs: Array1D[] = trainX.map(x => track(Array1D.new(x)));
const ys: Scalar[] = trainY.map(x => track(Scalar.new(x)));

const shuffledInputProviderBuilder = new InCPUMemoryShuffledInputProviderBuilder([xs, ys]);
const provider = shuffledInputProviderBuilder.getInputProviders();
const [xProvider, yProvider] = shuffledInputProviderBuilder.getInputProviders();

const BATCHE_NUM = 500;
const BATCH_SIZE = xs.length;
const LEARNING_RATE = 1.13;

const optimizer = new SGDOptimizer(LEARNING_RATE);
console.log('BATCHE_NUM', BATCHE_NUM);
console.log('LEARNING_RATE', LEARNING_RATE);

for (let i = 0; i < BATCHE_NUM; i++) {
const costValue = session.train(
cost,
[{tensor: x, data: xProvider}, {tensor: t, data: yProvider}],
BATCH_SIZE, optimizer, CostReduction.MEAN
);
console.log('-----------------------------');
console.log('index', i);
console.log('cost', costValue.get());
}
});




デモ

こんな感じで、ブラウザ上で学習が進んでいく

スクリーンショット 2018-01-17 18.12.56.png

スクリーンショット 2018-01-17 18.13.15.png



最終的な成果物をKaggleにsubmit

スクリーンショット 2018-01-17 18.06.17.png


  • Score 0.76076

  • そんなによくはないですが、さくっとやった割にはいいのではないでしょうか…。

  • もっと特徴量を細かく調整すればスコアは上がりそう。

  • 機械学習力は今回のテーマとは別ということで…。



いい感じに、学習から推論までJavaScript+ブラウザだけで完結できた



ただし :warning:

注意点として、以下の様なものがある。


  1. 学習したモデルを使いまわせない

  2. TensorFlowのモデルを(そのままでは)使えない



学習したモデルを使いまわせない :warning:

スクリーンショット 2018-01-16 12.44.44.png



  • MNISTの例



    • Download modelをおしても、モデルの基本情報がダウンロードされるだけで、学習済みモデルのチェックポイントなどが手に入るわけではない。

    • これができないと、学習をJavaScript側で行うのは非現実的かもしれない

    • 現状TensorFlowのモデルをポーティングした方がいいかもしれない

    • これがないと始まらない感はあるので、すぐに対応されるとは考えられる





TensorFlowのモデルを(そのままでは)使えない :warning:


  • Pythonで書いたモデルをそのまま使うことができない。

  • 学習済み変数テンソルやバイアステンソルのチェックポイント時点の値は使用することができるのみ。

  • Pythonのモデル実装をJSに書き直しているのに近い。

  • 自動モデル生成を実装するのロードマップが公式にある

import {CheckpointLoader, Graph} from 'deeplearnjs';

const reader = new CheckpointLoader('.');
reader.getAllVariables().then(vars => {
  // Write your model here.
  const g = new Graph();
  const input = g.placeholder('input', [784]);
  const hidden1W = g.constant(vars['hidden1/weights']);
  const hidden1B = g.constant(vars['hidden1/biases']);
  const hidden1 = g.relu(g.add(g.matmul(input, hidden1W), hidden1B));
  ...
  ...
  const math = new NDArrayMathGPU();
  const sess = new Session(g, math);
  math.scope(() => {
    const result = sess.eval(...);
    console.log(result.getValues());
  });
});



JavaScriptで機械学習をするその他のメリット


  • オンライン学習に使いやすい

  • ネットワークが細くても、オフラインで動く

  • APIを呼び出す必要がない



まとめ

:thumbsup:


  • JavaScriptでDeep Learningをするメリットは少なくない

  • JavaScriptという馴染みのある言語

  • 環境構築不要、ブラウザだけでGPUを使用できる

  • 高速な機械学習プロトタイプ開発

  • オンライン学習に使いやすい

  • ネットワークが細くても、オフラインで動く

  • APIを呼び出す必要がない

:thumbsdown:


  • 機械学習初心者が初めに触るには結局ハードルが高い

  • 機械学習の開発環境について理解するために、結局TensorFlow等を一から学ぶ羽目になる(その結果、TensorFlowの環境構築ができるようになってしまうので、TensorFlow使ったほうがいいのでは、という結論も…)

  • ライブラリの機能やコミュニティなど、まだ発展途上

  • ローカルマシンのGPUでは足りないということもある(がっつりやるならやはりいいGPU環境が必要)

  • 情報が少ない(Pythonが使われるようになったのも、エコシステムという側面がある。しかし、JavaScriptコミュニティは大きいのでこれから来るかもしれない)



参考