Maker上に構築した機械学習モデルを本番導入までをやりました。そこからいろいろ実運用でのつらさが見えてきたので問題点の共有とその一部を解決するためにMLデータマートを考えてみたという記事です。今までも機械学習を使った機能開発はありましたが、会社としてやっていき💪な機運だったのでチームとしてが立ち上がる運びとなりました。チームについての詳細は以下の記事に書いたので、読んでもらえると嬉しいです!AIチームの立ち上げとこれから既存の機械学習機能は僕がちょこちょこ作ったものや、数年前に作られていたものだったので過去機械学習周りをやっていた人はすでにいなくなっており、実際に手を動かすのは僕一人という状況でした。最初のうちは手探り状態で、何が失敗かわからず、見えている領域も狭いので、とりあえず小さく運用してみて感覚と知見を得ることを目的にしました。めでたく施策も決定し(ここの詰めが中途半端で痛い目見るのはまた別の話...)、どうやって導入するかを考え始めました。サービス導入ににあたってのアーキテクチャ要件は以下を設定しました。Gatewayの構成でした。MakerはAWSが提供するマネージドのML開発サービスです。Notebookを使ったデータ分析や、学習用コンテナの提供、作成したモデルのデプロイまでを一貫して行うことができるイカしたサービスです。システムこのサービスは今回の要件にベストマッチしてました。ありがとうAmazonさん🎉。Makerを使うことでデータ分析や推論用エンドポイントの提供までを簡単に行うことができます。Makerのエンドポイントを呼び出してやれば、推論を実行できます。それだけではうまく動作せず、入力データをデータセット形式に加工する必要があります。サービスと推論用エンドポイント間での依存関係を少なくしたかったので、Lambdaを使ってこれを実装しました。Gatewayを配置しました。これによってエンドポイントのIP制限やデータ形式の制御などを行うことができます。Makerのエンドポイントを変更したい場合は、自由に置き換えることができます。やってわかったツラみポイント一ヶ月半ほどでサービスへの導入が完了したのですが、当初の目的どおりやってみないとわからないツラさがいろいろ出てきました。データを手動で持ってこないといけない弊社ではありがたいことにいい感じのDHWが以下のような構成で構築されていました。MakerはS3に配置されたデータセットをデータソースとして参照することが出来ます。Queryに構築されているDWHからS3に持ってくる必要がありました。Queryのデータをいい感じに持ってこれるような機能を作ることは出来ます。そもそも作るのが面倒なのとスピードを早くする目的から一旦手動でのデータ転送を選択しました。目的のデータセットを抽出するクエリをRedashで書いて、CSVでダウンロードしてS3に配置するみたいなことをやってました。データ分析や特徴量解析やっているときに、別のデータ要素が欲しくなったら、Redashのクエリを書き直して、手動でS3に配置する必要がありました。これが結構めんどくさかったです。ここからちゃんと自動でデータセットが更新される仕組みと直接データにアクセスできる環境が必要だと思いました。Makerはデータの前処理から学習、デプロイまでを行うことができて非常に便利です。Notebookですべての処理を行っていました。記述されているコードにテストがないのはすごく不安です。Notebookでテストを行うこともできましたが、一時しのぎにしかならず、本質的じゃないと思ったのでやめました。ここから前処理部分などのテストをちゃんと行うようにしたいと思いました。Notebookに前処理からデプロイまでを書いていたので、かなりレビューがしにくかったと思います。(レビューして頂いた各位ありがとうございました)import部分でさえこんな感じです。]},一応Python形式でもExportしていましたが、大きい単一ファイルだったので可読性は低かったです。Makerは以下のような複数のコンテナ環境でモデルのデプロイまでを行います。このような一連の流れから、学習用コンテナの設定部分やデプロイ周りの設定もNotebookで行いました。Imageの指定やインスタンスタイプの設定、インスタンスに渡すハイパーパラメータの設定などが含まれます。Maker特有の知識が含まれ、レビューするのにも勉強する必要がありました。ここから小さいスクリプトの集合で処理や設定を定義したいと思いました。Notebookではデータの知見がその中に閉じてしまい、なぜその特徴量を使ったのかを体系的に共有できないと感じました。なんでそのデータを使ったのか、なぜそのような特徴量変換を行ったのか、その分析で使わなかったデータはどういう傾向があるのかなどが失われてしまっていました。コメントを残すようにしましたが、それでもどうしてもわからなくなってしまいます。ドキュメントを書けばいいのではと思いましたが、そういうドキュメントは往々にして手が行き届かなくなっていくと思っています。ここからなるべくコードに近いところでドキュメントを管理し、レビューを通すようにすればいいのではと思いました。MLデータパイプラインを作ろう上記の問題を解決するためにアーキテクチャの改善を行うことにしました。ツラさが存在するデータ取得部分と前処理部分の改善を行うことにします。いう風に直していくかを考えてみます。データ取得部分の問題は、モデリングまでの環境(学習済みモデルを作成する部分まで)をGCPに変更することにします。Queryから直接データをとってこれるようにします。PlatformというML開発サービスが存在するので、これを使うことにしました。前処理部分の問題は前処理ををスクリプトとして切り出し、それを使ってデータを特徴量に加工するデータパイプラインを構築することにしました。スクリプトとして切り出すことで、それぞれに対してちゃんとテストを書くことができるようになります。Stringにデータの知見をきちんと書き、それをShpinxを使って静的ページとして公開することで知見が共有できるようになると思いました。Query上に戻し、MLデータマートとして扱うことで次回モデリング時にそこからデータ使うことができるので、無駄な計算を行う必要もなくなります。データパイプラインを使って定期的に処理を実行させるようにすることで、特徴量の更新を行うことができます。Query上にMLデータマートを作ってやればデータ取得から前処理までの問題は解決することができ、さらに大きなメリットが発生することがわかりました。データマートなどの説明はゆずたそさんの記事が詳しいので以下に貼っておきます。20190213MLデータマートの構築にあたって、アーキテクチャの構成には以下の要件を設定しました。CIで監視し、更新内容によって実行するワークフローの分岐を行います。その命令はFargate内で常時起動しているDigdagに渡されます。このインスタンスはワークフローの実行だけを担うので、比較的サイズの小さいインスタンスで実行させることができます。実行させる処理の制御やDAG構築、インスタンスの起動&終了、GUIからの再実行、エラー時のリトライ処理などをこのDigdagが担保します。処理部分についてCircleCIからの命令を常時起動のDigdagが受けて、API経由でFargateインスタンスを立ち上げます。これらはモデルごとにDockerイメージをECRに登録しておき、それをベースに構築されます。データ加工を行うインスタンスは処理だけに役割を絞ることで、粗結合な仕組みにすることができます。行う処理内容から比較的大きなサイズのインスタンスを指定してやります。S3間のデータ転送部分をEmbulkコンテナに切り出しています。データこうすることで各モデルのワーカーインスタンスは処理だけに特化させることができるようになり、コンテナ内部での依存関係とイメージサイズをなるべく小さくすることができます。各モデルのワーカーコンテナについてはS3のデータを用いて処理を行い、加工が終わったものをS3に戻すようなフローを組んでいます。Queryに格納することでデータマートにデータが溜まっていきます。監視部分について監視はDatadogを使って行います。Datadogにデータの加工処理で発生する負荷のモニタリングや、エラー検知、ログの可視化などを任せます。Fargateから直接参照させることできないので、Digdagの実行ログをS3に吐き出し、それをS3に参照させます。各モデルのワーカーインスタンスはCPUやメモリの負荷についてもDatadogを使って監視することにします。コスト部分についてこの構成だと、比較的重い処理も必要最低限のコストで実行することができます。常時起動なのは比較的サイズの小さいDigdagだけで、必要に応じて各モデルのワーカーインスタンスを適切なサイズで起動させます。処理が終わればdigdagインスタンスが終了命令を出してくれるので大きなサイズのインスタンスを使用しても、コストがかからないような設計になっています。imageを定義してやればいくらでも拡張することができます。見えてない部分は多いですが、上記の問題は解消されるようなアーキテクチャになっています。上記を使用したモデリングのワークフローを示します。Composer+Dataflowを使って構築しようとしていました。Fusionを使った構成、GCP上にDigdag+embulkでパイプラインを作るなどいろいろな構成を考えました。どの構成も運用経験がなく、問題の発生予想が不透明だったのとそれなりに複雑なので覚えないといけないこと一杯で会社的にちょっときつかったです。どれも採用には一歩足りず、既存でDHWへのデータ転送をdigdag+embulkでやっていたり、チームにAWS運用の知見が溜まっていたのでAWS上での構築を選択しました。機械学習モデルをなるべくシンプルにしたかったから。このイメージは学習環境やデプロイ環境にも使うので、余計な部分が増えてボリュームが大きくなるのが嫌でした。digdagのアップデートやプラグインを追加したいときに、個別に分散していると移行作業が面倒になると予想しました。まとめて置くことでバージョンアップ等が楽になり、プラグインも一括管理できます。前処理部もデータパイプラインで定義したスクリプト使いたい。この記事を読んでいるみなさんへの質問です。Maker時代の運用例だとLambda)って今回作ったMLデータマートと全く同じ処理をするんですよ。同じこと二度かくのは面倒だし、ダサいのでこれも同じスクリプトを使っていい感じに処理できるようにしたいと思っています。バッチ処理は上記の構成で満たしているので、ストリーム処理をいい感じにできるようにしたいです。僕が考えているのは、Lambdaを使って実現する方法です。Layerに定義してやります。このパッケージをLambdaで呼び出して、前処理を定義してやればよいのではと思っています。ベストではないので、もしよければ、アドバイスもらえると嬉しいです。まとめ以上、見えている範囲で僕が考えた最強のMLデータマートの話でした。前処理部分だけなので、次はモデルのデプロイ周りやA/Bテスト環境を整えようと思います。Makerは個人的にとても良いツールだと思っているので、そこからエッセンスを学びつつ、開発できたらと思います。※ヴァイオレット・エヴァーガーデン見ながらこの記事を書いたのですが、良すぎて全く手が進みませんでした😢。今年見た中で一番良かった作品でした。みなさんも見てみてください。requestStockLike11@odrum428Followランサーズ株式会社テクノロジーで誰もが自分らしく働ける社会をつくる。upLoginユーザーは見つかりませんでした。