アーキテクチャの考え方
Machine Learning Systemsを読みました。ここで紹介されているアプリケーションのアーキテクチャの設計方法を紹介します。 こちらの書籍ではScala, Akka, Sparkを使ってリアクティブなアプリケーションを作成していますが、ここではそれ以外の一般的な部分をメモします。また、機械学習に必要なフィーチャーエンジニアリングやモデルの学習方法、モデルの評価方法も紹介されていますが、ここでは扱いません。
6割程度に目を通しましたが、Machine Learning Systemsに書かれている内容はMachine Learningにかかわらず一般的な内容が多いかと思います。
コンポーネント
ここで扱う機能としてはデータ収集、特徴の生成、モデルの学習、モデルの評価、モデルのパブリッシュ、モデルを使った予測の6つに分けられます。この各機能をコンポーネントと呼ぶことにします。
ここで紹介するのは以下の図の赤枠で囲まれたデータ収集、モデルのパブリッシュ、モデルを使った予測の部分です。
これらのコンポーネントを組み合わせたアプリケーションのアーキテクチャを安定して動作させるために、以下の要件が必要になってきます。
- 他のシステムに問題が起きても予想システムは動き続けて欲しい
- 高負荷やエラーが起きても動き続けて欲しい
これらを整理すると以下の4つの考え方に分けられます。
Responsive
一定の時間内にレスポンスを返すことができる。
Resilient
ハードウェアやヒューマンエラー、設計上の欠陥があった時も適切な応答を返せるようにする。503 (Service unavailable)なども含めて。
Elastic
負荷にかかわらずレスポンスを返すことができる。
Message Driven
非同期で処理ができる。疎結合な状態を作ることができる。システムエラーや負荷の問題を検知するのが容易。
可用性を上げる戦略
以下のような戦略で可用性を上げていきます。
レプリケーション (Responsive, Resilient)
同じコンポーネントが複数ある状態を作ります。また、データも冗長化されて保存と処理が実行されると良いでしょう。
疎結合 (Message Driven)
コンポーネント間を疎結合にします。ポイントは連鎖的にシステムが止まってしまうのを防ぐことです。コンポーネントはDockerなどを利用してコンテナ化し、マイクロサービス化するのが1つの方法としてあると思います。
Supervision (Message Driven)
各コンポーネントの死活監視をします。
Reactiveなシステム
Scala, Akka, Sparkが紹介されていましたが、他言語でActorモデルを使用するなど他の方法を使用しても良いと思います。
考慮すること
- Scalaは不確実性に対しての考え方を提供してくれる
- Option, Future…
- Futureのタイムアウトは応答性を上げる。応答時間を決めて切ってやる
- Akkaのactor modelはfailureに対していくつかの防御策を持っている
- メッセージパッシングによってシステムの過負荷を抑制する
- スーパーバイザーによってコンポーネントの可用性を上げる
- Sparkはデータ処理の便利なパイプラインを提供してくれる
- パイプラインは純粋関数とimmutableな変換で構成されている
- 遅延評価を使用している
- MLLibはモデルの構築と評価に便利なツールを提供してくれる。ミニマムなコードで書ける
- 分散データベースにCouchbaseを使っていた
データ収集
既存のDashboardなどのデータを使うと思いますが、以下のようなことを念頭に集める必要があります。
- 未加工の生データを集める
- データは常にimmutable
- データのアグリゲーション
- 単一障害点
未加工の生データを集める
生データを保存するようにします。例を紹介すると、下の図の上の表は生データのロケーション情報を扱いやすい地名に変換しています。下の表は下のデータでGPSから取得した位置情報を表しています。上の表のデータは一見扱いやすいように見えますが、GPSの位置情報より情報が薄まってしまいます。なので、取得したデータは必ず生の情報として保存するようにします。
データは常にimmutable
データベースに書き込まれたデータは更新しない。
データのアグリゲーション
embulkなどを使う。また、非同期で並列でアップデートする。
単一障害点
分散データベースを使用する。ネットワークをパーティショニングする。
モデルのパブリッシュ
考慮すること
- 学習済みモデルは保存するようにする
- モデルの予測部分をマイクロサービス化して冗長化させる
- マイクロサービスにはコンテナが便利。Dockerなどを使ってコンテナ化する
レスポンス
考慮すること
- マイクロサービス化してモデルを構築する
- スーパーバイザーを用意して各マイクロサービスを監視できるようにしておく
Application Serving PlatformはContainer orchestration platformと同じ意味。Kubernetesなど。 Application Serving Platformに複数のモデルサービスを持たせて分散させる。
Model Supervisorはモデルサービスの管理とモデルサービスのトラフィックの制御をする。
ProxyはNginxやHAProxyなど。
Model supervisorとProxyは基本的に同じApplication Serving Platformで動作する。
デプロイ
リリースタイミングの話ですが、一応。
ビルドが通るとArtifact Repositoryにモデルが保存されて Serving PlatformのAPIを叩いく。Serving PlatformがArtifact Repositoryからモデルを取得してモデルをアプリケーションにデプロイする
Unit testとメトリクスの評価をパスしたらデプロイする。 メトリクスとはアプリケーションのパフォーマンスの指標。