推論のための機械学習基盤を本番稼働させる際に気をつけるn個のこと

[ABEJA Platform Advent Calendar 2018](https://qiita.com/advent-calendar/2018/abejaplatform) の10日目の記事です。

推論のための機械学習基盤を作るのは、通常のWebシステムを作る時に気をつけることと大体は一緒ですが、機械学習基盤ならではの気をつけるポイントがあります。

PoCだけで終わるなら誰でも適当に作れるのでEC2を立てておしまいですが、本番環境で稼働させるには注意点が多数あります。機械学習ならではのポイントを書いていきます。

## 1. パフォーマンス、スペックを検討する上での注意事項
![image.png](https://qiita-image-store.s3.amazonaws.com/0/75573/65c1760c-e310-c76f-c8bb-03bb4ec89f5d.png)

### CPU / メモリ / 処理時間
機械学習は推論と言えども、要件次第でモデルが大きくなりCPUやメモリを大量に食うモデルもあります。
処理時間は、推論の内容やCPU/GPUの選択次第ですが、1つの推論で数秒から数十秒かかるものもあります。

一つの処理の特性を把握することが必要です。
リクエスト量が多い場合は、再処理や負荷を安定させるために、コストが高くても処理時間を短くする選択肢（後述のCPU最適化やGPU利用など）がオススメです。

### ネットワーク帯域
CPUやメモリ以外にもネットワーク帯域も気をつけるポイントです。
推論するデータには、画像はもちろんのこと4K画像や動画データなどデータサイズの大きいファイルが含まれる場合があり、それらがリクエストとして投げられてきます。

リクエスト量とデータサイズに応じてネットワーク帯域も気をつけるポイントです。
AWSの場合はインスタンスタイプ毎にネットワーク帯域が違うので注意が必要です。

[Amazon EC2 インスタンスの構成](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ebs-ec2-config.html)

### rps(Requests per second)
上記の要因で通常のWebアプリケーションだと頑張れば数万、数十万rpsとかを出せたりしますが、機械学習の推論は数百rps出たら良い方です。

要件を変える、モデルの実装を変える、後述のスケーラビリティ、CPU最適化、GPUの利用で解決する、ネットワーク帯域の確保など、ボトルネック解消ポイントは多数ありますが、要件、コストパフォーマンス、運用を考えて、バランスを取る必要があります。

### リアルタイム性
レスポンスにリアルタイム性が求められる要件の場合はEdge側で処理することもあります。
Edge側で処理を高速化させるために、NVIDIAが開発しているGPUの[Jetson](https://www.nvidia.com/ja-jp/autonomous-machines/embedded-systems/)やGoogleが開発している[Edge TPU](https://cloud.google.com/edge-tpu/)（まだアーリーアクセス）を利用します。
JetsonはARMベースのため、別途コンパイルが必要になったりするため、Github上のコードを簡単にそのまま載せるといったことはできません。
（この辺りのツラミは 13日目 に書かれると思います。）


## 2. スケーラビリティを上げるための実装
### ステートフルをステートレスに
コストを最適化したり、パフォーマンスを向上させるために、スケーラブルな実装にします。いわゆるオートスケールを実装します。

しかし、中にはメモリを数十GB消費するものもあったり、メモリのロードにすごく時間がかかるものもあります。
また、Githubなどに公開されている機械学習のコードは、実装優先のためか、Web界隈では当たり前になってきているステートレスな実装も行われていないものもあります。
そのため、コスト効率やパフォーマンスを向上させるためにスケーラブルにするには、自らステートレスな実装に変える必要がある場合もあります。

### オートスケールのチューニング
スケーラビリティを高めるにはオートスケールを実装が有効であり、それにはオートスケールの設定とチューニングが必要です。

オートスケールは簡単に設定できますが、CPUのメトリクスをベースにするのか、GPUのメトリクスをベースにするのか、メモリやIOなのか、何の負荷をベースにするのかは処理内容の特性を理解する必要があります。
また、どの程度のスパイクに耐えられるようにするためにホストをあらかじめ何台確保するのか、スケールアウトとスケールインの間隔や台数などの調整も必要になります。

[Amazon EC2 Auto Scaling とは](https://docs.aws.amazon.com/ja_jp/autoscaling/ec2/userguide/what-is-amazon-ec2-auto-scaling.html)

## 3. コスト効率を上げるための実装
### Docker / コンテナ
[![image.png](https://qiita-image-store.s3.amazonaws.com/0/75573/e99a1877-84cc-a149-8b67-1876820f6810.png)](https://www.docker.com/)

1つのサーバで1のアプリケーションを動かすと無駄が多いため、Dockerなどのコンテナを利用し集約効率を上げる流れはWeb界隈では当たり前になっています。機械学習でもDockerなどのコンテナを利用することでコスト効率を上げることができます。しかし、Dockerのためステートレスな実装を意識する必要があります。

なお、Dockerイメージは小さくすることがベストプラクティスとされていますが、ディープラーニングのフレームワークを含むDockerイメージは数GBから10GB程度あるものもあるため、現状ではDockerのベストプラクティスは踏襲できません。
ビルドに数時間かかるのもザラにあります。。

しかし、最近はクラウド側でもGPU対応をしてくれたり、NVIDIAからnvidia-docker2などが提供され、Dockerから比較的GPUを扱いやすくなってきています。

ディープラーニングフレームワークは過渡期のためバージョンアップが頻繁に行われています。通常のサーバで複数のアプリケーションを稼働させると複数のバージョンやライブラリの依存関係問題が発生し、困難を極めます。
ライブラリや依存関係を閉じ込めるため、ポータビリティ性を上げる、コスト効率を上げるためにもコンテナで利用することをオススメします。

[Docker入門（第一回）～Dockerとは何か、何が良いのか～](https://knowledge.sakura.ad.jp/13265/)

### CPU最適化
[![image.png](https://qiita-image-store.s3.amazonaws.com/0/75573/0b157b1b-7006-76f4-272e-e0cd97ac436e.png)](https://software.intel.com/en-us/mkl)

先ほどポータビリティ性を上げるためにも、と言いました。ポータビリティ性を上げてどこでも動かせる状態にすることで、安いサーバやスポットインスタンス、他のクラウドへ移行するなどしてコストを最適化することが可能です。

しかし、推論の速度を向上させるためにCPUに合わせて最適化する[Intel® Math Kernel Library(mkl)](https://software.intel.com/en-us/mkl) なども出てきています。
CPUに依存するためポータビリティ性が若干下がりますが、それ以上に処理速度を向上させることができるので、コスト効率を上げることができます。
ポータビリティ性をどこまで上げて、どこまで依存させるのかは悩ましいポイントです。



### 推論用GPU
[![image.png](https://qiita-image-store.s3.amazonaws.com/0/75573/d8ef8ef9-c303-90ab-6f7b-80e5486623b6.png)](https://aws.amazon.com/jp/machine-learning/elastic-inference/)

AWSでは re:Invent 2018 で [Elastic Inference](https://aws.amazon.com/jp/machine-learning/elastic-inference/) というサービスがリリースされました。
これは、任意のEC2インスタンスタイプに対して推論用GPUをアタッチすることで、p2.xlarge等を利用するよりインスタンスタイプが最適化されるため安くなるよというサービスになります。

p2.xlargeは主に学習用途では良いですが、推論用途でGPUを利用するのは高いため、コストパフォーマンスを考えて、推論ではCPUを利用することが多いです。
しかし、CPUでは処理時間が長くGPU使いたいけど、、、というところから出たサービスかと思います。

CPUでは時間がかかる処理をGPUに変え、処理時間が短くなることでパフォーマンスを上げることができます。
コストがかかりますが、大量の処理を行う場合は、ボトルネックを無くす方が運用を安定させることができるため、時間をお金で買う形が望ましいです。

### スポットインスタンス
[![image.png](https://qiita-image-store.s3.amazonaws.com/0/75573/0db60b1f-4b26-d493-8bbb-ff8f7ccacf4c.png)](https://aws.amazon.com/ec2/spot/?nc1=h_ls)
[![image.png](https://qiita-image-store.s3.amazonaws.com/0/75573/cb8bbcbb-1e47-e6b7-4980-2d8cf721b83e.png)](https://cloud.google.com/preemptible-vms/)

機械学習ならではなのか微妙ですが、GPUインスタンスや推論用に高いCPUインスタンスを利用する場合があります。
そのため、AWSの[スポットインスタンス](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/using-spot-instances.html)やGCPの[プリエンプティブVM](https://cloud.google.com/compute/docs/instances/preemptible?hl=ja)を利用し、最大90%程度のコストダウンを図ることも重要です。

スポットインスタンスは急にインスタンスを停止されるため、それに耐えうるステートレスな実装が求められますが、最大90%程度のコストダウンの威力は大きいので、オススメになります。

## 4. 耐障害性
出来る限り人手の運用は無くしたいところです。そのため自動的に復旧する仕組みをためにオートスケールやフルマネージドサービスをフル活用することが推奨されます。

### AWS Well-Architected
[![image.png](https://qiita-image-store.s3.amazonaws.com/0/75573/65023596-ea53-66f5-8123-f39e85957966.png)](https://aws.amazon.com/architecture/well-architected/?nc1=h_ls)

何かを指標にしたい場合は、[AWS Well-Architected](https://aws.amazon.com/jp/architecture/well-architected/) に準拠することがオススメです。
クラウドのベストプラクティスに準拠することができます。
全て満たす必要はありませんが、参考になるポイントは多いです。

> AWS Well-Architected フレームワーク(以下W-A)は、AWSのソリューションアーキテクト(SA)が、AWSのサービス開始から10年以上に渡り、様々な業種業界、数多くのお客様のアーキテクチャ設計および検証をお手伝いしてきた経験から作成したクラウド活用のベストプラクティス集です。具体的には「運用の優秀性」「セキュリティ」「可用性」「パフォーマンス効率」「コスト最適化」の5つの観点について、クラウドをより活用するための設計原則と、お客様システムがベストプラクティスに沿っているかを確認するための質問と回答で構成されています。

### Kubernetes
[![image.png](https://qiita-image-store.s3.amazonaws.com/0/75573/c60ca17c-45b6-b635-c282-e4a65781aab9.png)](https://kubernetes.io/)

この文脈に[Kubernetes](https://kubernetes.io/)を登場させることに違和感はありますが、耐障害性文脈だけ登場させます。

Dockerを運用する際は、Dockerの管理を楽にするためにオーケストレーションツールを利用します。
KubernetesはDocker(それ以外のコンテナも)のオーケストレーションツールのデファクトスタンダードで、Googleが開発したOSSで、コンテナを運用する上でのベストプラクティスがたくさん詰まっています。
Kubernetesを利用することで、ベストプラクティスに乗りやすくなります。

しかし学習コストは高く運用負荷も高くなります。使いこなせばそれに見合うだけの価値はあります。
最近は Kubeflow というKubernetes上で機械学習を動かすOSSも登場したり、GPUを公式に扱えるようになったりと、Kubernetes上での機械学習を利用しやすくなり始めています。

## 5. デリバリ
### 安全にデプロイする
推論コードの修正はもちろんのこと、再度学習したモデルを入れ替えることもあります。
Web界隈で言われている[ブルーグリーンデプロイメント](https://aws.amazon.com/jp/blogs/news/bluegreen-deployments-with-amazon-ecs/)などの実装をしていると、安全にデプロイし、切り戻しも簡単に行えるためオススメです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/75573/63545308-4b77-ab52-0621-9af22a2a12b5.png)
_[*EC2 Container ServiceのBlue/Greenデプロイメント](https://aws.amazon.com/jp/blogs/news/bluegreen-deployments-with-amazon-ecs/)_

### 推論結果とデータの保存
本番に稼働させたらそれでおしまいではありません。その推論モデルが意図した精度が出ているのか、結果を保存し可視化することも重要です。また、他のモデルを作成した際の精度確認のため推論したデータは重要になります。

そのため、推論結果とデータの保存は非常に重要なポイントになります。

### 可視化するのかしないのか
推論した結果が `正しい` のか、どうやれば精度が上がるのか、仮説を立てて検証した結果はどうだったのか、どうやればビジネス上の価値に紐ずくのか、は推論モデルをAPI化しただけではわかりません。

推論結果とビジネス上重要なフィードバックを元に可視化を行う必要があり、それらが見えないシステムは費用対効果が見えないため、そのうち費用対効果が薄いということで、使われないシステムになってしまいます。

費用対効果を可視化することは重要な要素です。

<img src="https://qiita-image-store.s3.amazonaws.com/0/75573/f0537c50-fe69-88f9-c4c4-8bba7572affd.png" width=50%>

### 入れ替える前の精度確認
再度学習したモデルは果たして精度が高くなったのでしょうか？切り替えて影響は出ないでしょうか？

それを確かめるためにも、今まで貯めたデータを用いて推論し検証するのか、新しく入ってきたデータを新旧のモデルで推論してみて比較するのか、というアプローチも必要になってきます。

<img src="https://qiita-image-store.s3.amazonaws.com/0/75573/60309bab-1dd8-c5d4-2891-ef0a98f0b9b7.png" width=50%>

## 6. セキュリティの注意事項
![hacker-1944688_640.jpg](https://qiita-image-store.s3.amazonaws.com/0/75573/c180c6f8-345b-a382-d8e8-477702e98924.jpeg)


ディープラーニングでは主に画像を扱うことがよくあります。画像は個人情報が含まれるものもありますし、OCRなどで個人情報を扱うものもあります。
最近は医療関係でもディープラーニングが使われることもあり、よりセンシティブなデータを扱うこともあるでしょう。
それらのセンシティブなデータを適切に管理し、利用、破棄することが求められます。

AWSの場合はAWSのセキュリティの特性を理解した上で、NW/OS/MW/アプリケーションレイヤーで様々な対策を施す必要があります。
例えば、IAMの管理を適切に行い、SecurityGroupを絞り、CloudTrailでLoggingし、S3はKMSで暗号化し、バケットポリシーを設定、などなどです。
暗号化に関しても、サーバサイド暗号化でいいのか、クライアントサイド暗号化にするのか、鍵はどこに保管するのか、誰が扱えるのか、ロギングはどうするのか、といった問題が発生します。

セキュリティは各レイヤーの知識を持った人が対応する必要があります。

## 7. モニタリング、トラブルシュート
![image.png](https://qiita-image-store.s3.amazonaws.com/0/75573/65c1760c-e310-c76f-c8bb-03bb4ec89f5d.png)

監視・モニタリングに関しては通常のシステムと同じでいいですが、トラブルシュートに関してはこれまで出てきた技術要素と特性を理解・把握している人でないと対応は難しいです。


## 8. 人とスキルセット
![image.png](https://qiita-image-store.s3.amazonaws.com/0/75573/6dd946bd-3a94-e7c8-e319-876201335453.png)

さて、ここに来て一番重要なポイントが `人とスキルセット` です。

### どの程度のスキルセットで、どのくらいの人数で、どれくらいの規模が必要か
通常のWebシステムの知識に加えて、これまでのポイントを理解、把握して設計・構築できる人が必要です。
さらに、これらのシステムを運用・トラブルシュートできるスキルセットを持っている人達（一人では運用できない）が必要です。

どの程度のスキルセットが必要で、どのくらいの人数とどれくらいの規模が必要かはシステムの規模に寄ります。システムの拡大を見据える場合は人員計画も必要です。

### 追従しアップデート
機械学習基盤はまだまだベストプラクティスが定まっていないですし、ディープラーニングフレームワークもアップデート頻度が高いため、すぐにシステムが陳腐化する可能性もあり、最新動向に追従しアップデートする工数も必要です。

### 経験値と作り直しの頻度
経験者でない限り1回で優れたものを作ることはできません。感覚的には3回くらいは根本的に作り直すフェーズはあるのではないでしょうか。
ABEJA Platformでも各機能は何回か時間をかけて作り直しています。

### 属人化防止
数人で行なった場合、特定の業務が特定の人に寄ることもあります。異動や退職時に大きな混乱が生じます。
現状、機械学習基盤を作れる人は多くいませんが、業務を個人依存しないような体制が必要です。

## 9. 作らない選択肢
<img src="https://qiita-image-store.s3.amazonaws.com/0/75573/fce32165-9bdc-d242-6482-2274e84c7ca7.png" width=20%>

上記のスキルセットの人を採用し、体制を組み、雇用するコストは安くありません。
作るのではなく、サービスを利用しすぐに事業を開始し、事業の価値を最大化させるところに人をアサインしたいところです。

スキルのある人はもっとコアコンピタンスに集中し、事業的な価値のある業務を行なってもらいましょう。

## 10. ABEJA Platform
[![image.png](https://qiita-image-store.s3.amazonaws.com/0/75573/64dbfe9f-d448-5b97-efb5-9472354d9df1.png)](https://abejainc.com/platform/ja/)

はい。[ABEJA Platform Advent Calendar 2018](https://qiita.com/advent-calendar/2018/abejaplatform) なので、もちろんここで ABEJA Platform 紹介のターンです。

上記の通り、機械学習基盤を作るのは人と時間がかかります。
たくさんの企業で同じ作業を繰り返さなくて良いように、ABEJAでは貯めたノウハウを元に [ABEJA Platform](https://abejainc.com/platform/ja/) という機械学習プラットフォームを開発し、提供しています。

AWS コンピテンシープログラムの一つである [AWS Machine Learning コンピテンシー](https://aws.amazon.com/jp/machine-learning/partner-solutions/) にも認定されており、ここに書かれていることは大半満たした状態で、作らなくてもすぐに使える状態で提供しています。

ABEJA Platformは何ができるのか、どう使うのかはこの [ABEJA Platform Advent Calendar 2018](https://qiita.com/advent-calendar/2018/abejaplatform) で公開されていくので、もし興味持たれた方はこちらで [デモ](https://abejainc.com/platform/ja/contact/) を申し込んでください。