クライアントサイドでの機械学習の実行について

# TL;DR
フロントエンドエンジニアである自分が、とあるきっかけで、クライアントサイドで機械学習を実行する際に留意すべきことを調べてみたものになります。

# きっかけ
以下の記事においてクライアントサイドでの機械学習に興味を持ったため
[なぜGoogle Meetの背景ぼかしが最強なのか（一般公開版）](https://zenn.dev/kounoike/articles/google-meet-bg-features)
（元記事：[Background Features in Google Meet, Powered by Web ML](https://ai.googleblog.com/2020/10/background-features-in-google-meet.html)）

## 記事の内容
- ブラウザなのにネイティブアプリと同程度の性能を実現しているのがすごい
- 体感で4倍ぐらい早い機械学習高速化について
- ライブストリーミングに特化した機械学習・画像処理のフレームワーク
  - [MediaPipe](https://mediapipe.dev/)
     - WebAssembly(wasm)でビルドできる（※WebAssemblyとはJavaScriptよりも高速で実行できる技術 参考：[WebAssemblyとは？〜実際にC言語をブラウザで動かす〜【2019年6月版】](https://qiita.com/umamichi/items/c62d18b7ed81fdba63c2)）
     - 全てをwasmで完結しているため余計なオーバーヘッドがない
- 400kBと超軽量な機械学習モデル
  - [MobileNetV3-small](https://arxiv.org/abs/1905.02244)
     - 対象検出
- その他画像処理技術
  - Refinement（輪郭の処理）
  - 背景ぼかし処理（背景と対象を分離して、背景のみぼかす）

# クライアントサイドで機械学習を高速で実行すにはどうすればいいのだろう？
- [機械学習モデル自体の軽量化](#機械学習モデル自体の軽量化)
- [実行環境の高速化（TensorFlow.jsについて）](#実行環境の高速化tensorflowjsについて)

## 機械学習モデル自体の軽量化
[ディープラーニングを軽量化する「モデル圧縮」３手法｜エンジニアコラム]
(https://laboro.ai/column/%E3%83%87%E3%82%A3%E3%83%BC%E3%83%97%E3%83%A9%E3%83%BC%E3%83%8B%E3%83%B3%E3%82%B0%E3%82%92%E8%BB%BD%E9%87%8F%E5%8C%96%E3%81%99%E3%82%8B%E3%83%A2%E3%83%87%E3%83%AB%E5%9C%A7%E7%B8%AE/)より

- 主な3手法
  - [Pruning（枝刈り）](#### Pruning（枝刈り） )
  - [Quantize（量子化）](#### Quantize（量子化）)
  - [Distillation（蒸留）](#### Distillation（蒸留）)


### それぞれの手法について
#### Pruning（枝刈り） 
計算するニューロンと重みの削減
![unnamed (7).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146971/a7115edf-cf9b-b0cd-ed23-87adecfa12d7.png)


#### Quantize（量子化）
数値の桁数の削減
![unnamed (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146971/b6684774-34e0-0540-86cc-bfe5e8158c40.png)


#### Distillation（蒸留）
大きいモデルの出力を活用して小さいモデルを学習
![unnamed (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146971/c13f2a48-098c-f3dc-f840-3c7b960d13bb.png)

### 様々な研究
- [ディープラーニングを軽量化「宝くじ仮説」｜エンジニアコラム](https://laboro.ai/column/%E5%AE%9D%E3%81%8F%E3%81%98%E4%BB%AE%E8%AA%AC/)
![unnamed (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146971/afae5707-3d97-af3b-fad9-8ef12adf21f8.png)

- [GhostNet](https://ai-scholar.tech/articles/image-recognition/ghostnet-ai-383)
![unnamed (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146971/fff09e86-608b-35f6-d586-de82eaa5a2ef.png)


## 実行環境の高速化（TensorFlow.jsについて）
- 実行するbackendの選択
  - CPU
  - WebGL
  - WebAssembly
  - WebGPU
  - React Native

（[Fast client-side ML with TensorFlow.js, by Ann Yuan (Google)](https://www.w3.org/2020/06/machine-learning-workshop/talks/fast_client_side_ml_with_tensorflow_js.html)、[Platform and environment](https://www.tensorflow.org/js/guide/platform_environment)、[TensorFlow.jsの新たな目玉機能｜Kai Sasaki｜note](https://note.com/lewuathe/n/n26d284dec180)）

## WebAssemblyを使うべきタイミング
[TensorFlow.js の WebAssemblyバックエンド の紹介｜npaka｜note](https://note.com/npaka/n/n6dd4d983b17f) **←おすすめ**
（元記事：[Introducing the WebAssembly backend for TensorFlow.js](https://blog.tensorflow.org/2020/03/introducing-webassembly-backend-for-tensorflow-js.html)）
![unnamed (5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146971/41fd92bd-dfb8-9e0a-1758-ddcfcefe35dd.png)

![unnamed (6).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146971/bc89a88c-e605-dd0b-822b-fa6a7a080098.png)

基本的にWebGLよりも遅い。なぜなら、WebGLはGPUによる計算が行われるため。一方でwasmは、CPUで計算を行う。ただし、wasmの並列計算機能である[SIMD](https://v8.dev/features/simd)を活用すると、3倍程度早くなる。また以下の場合には、wasmの方が有利になる。

**1. モデルが小さい場合**
計算処理をGPUに転送するオーバーヘッドよりも、計算量が小さい時
**2. 幅広いデバイスをサポートしたい場合**
GPUはデバイスごとに大きな性能差があるため
**3. 数値誤差が重要な場合**
GPUではデバイスによって16ビットの浮動小数点にしか対応していないため
以上の点から、WebGL一強というわけではない。

その他の参考
[SIMD およびマルチスレッド処理で TensorFlow.js WebAssembly バックエンドを高速化する](https://developers-jp.googleblog.com/2020/09/simd-tensorflowjs-webassembly.html)