post Image
JavaScriptでDeep Learning

最近の興味


機械学習


私のレベル

  • 昨年から年末年始にかけて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コミュニティは大きいのでこれから来るかもしれない)

参考


『 機械学習 』Article List
Category List

Eye Catch Image
Read More

Androidに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

AWSに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Bitcoinに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

CentOSに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

dockerに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

GitHubに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Goに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Javaに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

JavaScriptに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Laravelに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Pythonに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Rubyに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Scalaに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Swiftに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Unityに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Vue.jsに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Wordpressに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

機械学習に関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。