CODING ECHO

インターネット広告屋でエンジニアをやっている人のブログ

機械学習システムのアーキテクチャ設計

アーキテクチャの考え方

Machine Learning Systemsを読みました。ここで紹介されているアプリケーションのアーキテクチャの設計方法を紹介します。 こちらの書籍ではScala, Akka, Sparkを使ってリアクティブなアプリケーションを作成していますが、ここではそれ以外の一般的な部分をメモします。また、機械学習に必要なフィーチャーエンジニアリングやモデルの学習方法、モデルの評価方法も紹介されていますが、ここでは扱いません。

6割程度に目を通しましたが、Machine Learning Systemsに書かれている内容はMachine Learningにかかわらず一般的な内容が多いかと思います。

コンポーネント

ここで扱う機能としてはデータ収集、特徴の生成、モデルの学習、モデルの評価、モデルのパブリッシュ、モデルを使った予測の6つに分けられます。この各機能をコンポーネントと呼ぶことにします。

ここで紹介するのは以下の図の赤枠で囲まれたデータ収集、モデルのパブリッシュ、モデルを使った予測の部分です。

image

これらのコンポーネントを組み合わせたアプリケーションのアーキテクチャを安定して動作させるために、以下の要件が必要になってきます。

  • 他のシステムに問題が起きても予想システムは動き続けて欲しい
  • 高負荷やエラーが起きても動き続けて欲しい

これらを整理すると以下の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の位置情報より情報が薄まってしまいます。なので、取得したデータは必ず生の情報として保存するようにします。

image

データは常にimmutable

データベースに書き込まれたデータは更新しない。

データのアグリゲーション

embulkなどを使う。また、非同期で並列でアップデートする。

単一障害点

分散データベースを使用する。ネットワークをパーティショニングする。

image

モデルのパブリッシュ

考慮すること

  • 学習済みモデルは保存するようにする
  • モデルの予測部分をマイクロサービス化して冗長化させる
  • マイクロサービスにはコンテナが便利。Dockerなどを使ってコンテナ化する

レスポンス

考慮すること

  • マイクロサービス化してモデルを構築する
  • スーパーバイザーを用意して各マイクロサービスを監視できるようにしておく

image

Application Serving PlatformはContainer orchestration platformと同じ意味。Kubernetesなど。 Application Serving Platformに複数のモデルサービスを持たせて分散させる。

Model Supervisorはモデルサービスの管理とモデルサービスのトラフィックの制御をする。

ProxyはNginxやHAProxyなど。

Model supervisorとProxyは基本的に同じApplication Serving Platformで動作する。

デプロイ

リリースタイミングの話ですが、一応。

f:id:ytanak:20190113193630p:plain

image

ビルドが通るとArtifact Repositoryにモデルが保存されて Serving PlatformのAPIを叩いく。Serving PlatformがArtifact Repositoryからモデルを取得してモデルをアプリケーションにデプロイする

image

Unit testとメトリクスの評価をパスしたらデプロイする。 メトリクスとはアプリケーションのパフォーマンスの指標。