ユニットテストエンジニアの佐藤です。ユニットテスト」を構想し、実装までに直面した課題と私が考えた解決方法についてお話ししたいと思います。様々なサービスをつなげて「サーバーレス・ワークフロー」を編成する仕掛けです。古来から様々なワークフロー支援サービスがありますが、その中では最も新しいものです。ことの始まり筆者はある日、とある業務システムをどうやって実装したものかと考えていました。Functionsを選択しました。重視したポイントは以下のようなものです。ワークフローの進捗が視覚的に確認できる。ワークフロー定義が読みやすい。Functionに、後者をECS(Fargate)で実行することにしました。Functionのユニットテスト・・・って?ところで昨今のシステム開発は、テストコードを記述してユニットテストを行うのが一般的です。Functionsで作成されるワークフロー設定(ステートマシン)についてのユニットテストを構想しました。ところが、考えていくうちに、これが結構深いタスクであることに、徐々に気がついてきました。一般的な話ですが、システムを人間の体に例えると、手足に相当する機能のユニットテストについては、準備作業はそれほど難しくありません。一方で中枢的な機能のテストのための準備作業は大きくなりがちです。動作が確実な仮の末端部品を接続してあげる必要があるからです。「ワークフロー管理」機能は、この観点から言うとシステムの最も中枢的な部分であり、その単体テストのためには仮の末端部品の接続が必要ということになります。FunctionとECSに仮のモジュールを入れてあげる必要がある。FunctionとECSの仮のモジュール、と構想したところで、筆者は更に寒気を覚えました。考えてみるとこの2つ、機能コードを配置するまでの作業がそれなりに手間なのです。Functionの場合、以下のようなステップがあります。Functionの設定ECSの場合はこうなります。Functionの設定」と「タスク定義の作成」には、環境変数などの設定も含まれます。テスト用の仮のモジュールなどと言いながら、一式全部必要なわけです。ステートマシンのテストをするために「システムの設計方針に従って各種の設定を発行・注入する仕掛け」の開発が必要になる・・・そう気がついた筆者は、とんでもないことを始めてしまったのではないかと、暗い気持ちになりました。中でも筆者が負担に感じたのがIAMです。FunctionもECSも機能コードの実行環境であり、実行の際に「インフラ的にできること(実行権限)」の範囲をIAMロールとして定義する必要があります。これがまた、慎重さと地道な努力を要する作業なのです。「とりあえずAdmin!」とやっつけたい気持ちはやまやまですが、これは悪魔の囁き。権限設定はミニマムからスタートしないと、権限のダイエットはとても大変なのです。Functionsについては、AWSがローカルランタイムを配布していますが、今回は利用を見送りました。ローカル版のFargateはありませんし、ローカル環境固有の設定負担や互換性問題もあるでしょう。それなら最初から本物を使ったほうがいい、ユニットテスト用のAWSアカウントを短時間使うだけならそんなに経費もかからない、と判断しました。各種設定の発行・注入する仕掛け・・・って?で、その仕掛けをどうしたのかというと、この点は大変悩んだところでした。Formationでした。調べていくと、これはこれで良くないところがあると思いました。引っかかったのが、テンプレートの入出力がいずれもリストとなっており、階層的にできない点です。Formationは見送りました。次に検討したのがCDKでした。Formationのテンプレートを効率的に作成する仕掛けです。Functionsの実装がまだプレビュー状態で、またステートマシンの定義方法が独特で良くないと思いました。ランダムな付加文字列の入ったリソース名となる点も、やり込むと散らかって良くないだろうなと思えました。筆者が最終的に選択したのは、以下のような方式でした。プロジェクト名に連なる一連の名前体系を決め、これを環境変数で設定する。SDKを用いて直接リソースの作成と削除を行う。リソース定義は、これらのソースコードに記述する。undeploy.py実行のフローで行う。幸いなことに今回のシステムの開発言語はPythonでした。AWSリソースの定義は、たいていJSONで書かれており、Python言語のdictionaryとほとんど同義(しかもコメントも挿入できる)。複数のリソース定義を体系的に作っていくにはプログラムフローが効率的で、デプロイ自体もその延長でSDKを呼び出してやってしまえば、小さくまとまらないかと目論んだわけです。FunctionとECSコンテナを実行する」実装の場合、以下のようになりました。SFN_POLICY_NAME="${PROJECT_NAME}SfnPolicy"もういきなりお腹いっぱいな感じがありますが、ここに列挙したどれ一つ不要なものはありません。機能コードをサーバーレスに埋めていくとは、こういう手間を伴うものなのです。Functionsステートマシンをデプロイするコードを書いていくわけですが、ステートマシンをデプロイする部分をご紹介すると、以下のようになりました。Functionsのステートマシン自体は、JSON文書として記述されます。FunctionやECSのタスク情報を含めていくわけですが、これをステートマシン定義取得関数get_stepsの引数で指定するようにしておきました。FunctionやECSタスク情報を設定することができるだろうとの目論見です。get_steps自体は以下のような実装になりました。get_stepsこれはステートマシンのユニットテストの方法論の開発のためのテストのために仮組みしたものですが、これが下の図のようなステートマシンになります。ステートマシンからECSを呼び出すにはタスク定義のARNを指定する必要がありますが、このタスク定義は更新の度に「project01Task:77」のように末尾の序数が加算されていき、この数字を指定する手段はありません。目的のコンテナが指定されているタスク定義を(たいていは最新のタスク定義でしょうが)掘り出すしかないようなのです。__create_ecs_parametersこのような工夫を経て、ようやく当初の目的の「ステートマシンのユニットテスト」に到達しました。テストコード全体は以下のようになりました。TestClass01このテストコードを実行することで、当初の目論見であったステートマシンのユニットテストが実行できるようになりました。Functionやコンテナと組み合わせれば、複雑な状態管理の作り込みと繰り返しの動作確認が可能になったと思います。ふり返って、どうか正直なところ、なかなか複雑な気持ちです。効率的なリソースアロケーションを目標として計画した目論見でしたが、結局CI/CDみたいなことをやることになってしまいました。Functionを本格的に業務活用しようとすると、自動デプロイの仕掛けを何かしら用意する必要があると感じました。設計目標はクリアできそうですが、けっこう大変でした。設定が煩雑になったのはECSを呼び出す部分です。Functionに用意されていると、より開発作業が効率的になるのではないかと思いました。ステートマシンとECSの入出力の高機能化。ステートマシンの入力値をJSONのまま受け渡しできるAPIの追加など。(現状では環境変数文字列にする必要がある。)個別のステートマシンからはECRのコンテナのみを指定して実行できるように簡略化。ステートマシン全体に既定のコンテナクラスタやタスク定義を設定する機能など。最後までお読みいただきありがとうございました。(12/5)CI事業部ウエダです。こんばんは本日はFLECTとして参加するのは最終日となります。各レセプション会場でもすごい人数ですが、一堂に集まるのでとにかく広いです。セキュリティのためか持ち込むものも厳格に決められています。いえ、飲食物は用意していただけるので特に必要なものはありません。様々な料理が屋台として出店されています。1つ1つの食事の量は少なめなので食べ比べる楽しみがあります。食事とは別に、飲み物を提供する場所が点在しており、好きなものを注文できます。テント大きなテントがいくつか用意されておりそれぞれ、ライブやハウスミュージックが大音量でかかっています。ライブは近くで聞くと重低音が響き、迫力があります。別のテントではいい感じのリズムで周りを盛り上げます。ゲーム大型のゲームと80〜90年代のレトロゲームが設置してあります。私は試しにボタン早押しゲームに参加しました。接戦の結果勝利することができましたが、対戦相手とは互いの検討を祝してレトロゲームをやったりと楽しめました。いった意図しない出会いの場が生まれるものre:inventのいいところだと思います。ドローン最後はドローンです。夜空に様々な形を繰り出す姿は圧巻です。エキサイティングな体験ができた1週間でした。名残惜しいですがこれから帰国です。この体験を業務で生かして行こうと思います。(12/4)みなさんこんにちは。技術開発室の岡田です。re:invent2019に参加しています。昨日のキーノートでは怒涛の新サービス発表がありましたね。私の担当している機械学習関連では、SageMakerの新サービスが多く発表され、スーパーエキサイティングな1日になりました。興奮醒めやらぬ状況ではありますが、この発表をうけて新たに追加されたセッションも含め、本日までに参加できた機械学習関連のセッションについて、ご報告したいと思います。(ちょっと専門用語が多めになります。)ちなみに、今日も朝ごはんと昼ご飯は提供されました。😊キーノート振り返り昨日のキーノートでは、レイヤごとに次の新サービス・機能が発表されました。Lens:コールセンタ向けこれらに関連して追加されたセッションのうち、本日までに次のものに参加することができました。MLまた、関連して次のものもセッションに参加しました。Autopilotを用いて自動でチューニングして、よりよいモデルを作成するワークショップです。Autopilotはガウス過程回帰とベイズ最適化を用いてパラメータを探索します。ここでチューニングできるパラメータは一般的なハイパーパラメータに加え、機械学習アルゴリズム自体も自動で選択してくれます。Engineeringも実施してくれるようです(!?)。探索の結果いくつかの候補を出してくれるので、(一般的には)もっともよいメトリックのモデルを選択する、ということになります。会場ではパラメータチューニングに伴って発生する料金についての質問が出ていました。パラメータチューニングするためには何度もトレーニングを実施する必要があり、大量の計算リソースを必要としますので、当然の懸念だと思います。回答も至極当然の回答で、探索(トレーニング)にかかった時間だけそのインスタンスの料金を払うことになるよ、とのことでした。大きなモデルに使うと結構な料金がかかってしまうのではないかという不安はありますね。グリッドサーチよりも少ないイテレーションでより良いパラメータを見つけてくれる期待はあるので、グリッドサーチをやる前提であるのであれば、代わりにこちらを使った方が安上がりになる可能性もあります。機械学習に詳しくない人にとっては、ほぼ全自動でモデルの性能を向上させることができるという点は見逃せません。このため結構使われるのではないかと思います。期待のできる機能だと思いました。このワークショップで用いたノートブックは下記のgithub上にあります。実行する際には使用したリソースの料金が発生しますのでご留意ください。このノートブックのLab2を実行すると、Autopilotで作成したパラメータの候補の一覧を中間生成物のノートブックで見ることができます。Importanceなど使ってしっかりFEしてたような気がします。Monitorのセッションです。driftは、ざっくり説明すると、モデル作成中に想定した世界が時間の流れとともに変化し、モデルが現実世界に対応できなくなることです。一般的には、上記のAutopilotのようなことを行い、モデル作成の際に与えられたデータを用いて、そこで(汎化性能も含た)最高の性能を出せるようにチューニングします。時間とともに取得できるデータのばらつきが変わるため、徐々に性能が劣化していきます。温暖化の影響を受けて天候が変わるとか。最近の日本の気候もだいぶ変わったように思いますよね。このため、モデルは作成時点が最も精度が高く、徐々に劣化していくといわれたりします。Monitorはこの劣化度合いをモニタリングして、一定の条件に至るとアラートを上げる機能とのことです。Monitorがリコメンドしてくれるようですが、最終的には)モデル開発者が決める必要があるようです。constraintsのところですね。このため、ちょっと機械学習の知識がないと敷居が高いのではないかという印象でした。Autopilotで自動でモデルチューニングした後にこの条件を作成し、その良しあしを判断ができるのかが気になるところです。driftの話はFLECTが扱っている案件でも話題になりますので期待したい機能です。Debuggerのセッションです。大規模なモデルを作成した経験をお持ちの方であればお分かりになると思いますが、モデルのトレーニングにはかなりの時間がかかります。トレーニングを開始したら数日放置しておくということもあると思います。数日後にトレーニングが完了したモデルを確認すると期待したほどの精度向上がなく落ち込むと。このような悲劇を回避するためにTensorflowであれば、TensorBoardを用いたりCallbackをうまく使って通知を上げたりするのが一般的かと思います。これを行うためにはモデル開発のコードを修正する必要があり、かなり神経を使います。Debuggerはコード変更することなくトレーニング時の異常をリアルタイムに検知、報告してくれる機能とのことです。トレーニング中に作成されるデータ(おそらくチェックポイント)をS3に保管しし、逐一それを解析する処理を起動するという感じでしょうか。確かに、デバッグコードをモデル開発のコードに直接書くと見通しが悪くなったりしがちなので、そういう意味で地味にありがたい機能だと思います。Studioのセッションです。Studioは、今回発表のあった各種機能を取り込んだ機械学習モデルの統合開発環境となります。図のような繰り返し開発を行うときに活躍します。左の箱のBuildフェーズはNoteBooksを使ってAutopilotでチューニング、Debuggerでデバッグしながら中央の箱と行ったり来たりのイテレーションを行う。このイテレーションはExperimentsで管理され、最終的にはソリューションとして最適なモデルをデプロイできる。デプロイした後はMonitorでコンセプトドリフトを監視して問題があれば再度モデルを作り直す。いう流れになるかと思います。考えると、さすが機械学習の開発プロセスを熟知しているAWSの統合環境だなと思いました。Studioの発表で開発プロセスが一段レベルアップした感じです。MSといった他社の出方が気になります。learning本セッションはキーノートの直後に実施されたものです。Library(DJL)です。Java開発者にend-endの機械学習開発APIを提供するようです。Infraチームが数週間かけてリファクタリングして使っていたのだそうです。多くのエンタプライズサービスはJavaで書かれているのだから、このコストはいろんな開発現場で発生しているはず。そこでDJLを使って初めからJavaで作成しておくことで、このコストを削減するということのようだ。TeamはDJLを使うことで開発期間を30%削減できるようになったそうです。確かにPython,特にJupyterNotebookで作成するコードはそのまま使えないことは、私もよく経験することなので、なるほどなとは思いました。Comprehendと連携して、リアルタイムで推論結果を返します。いう流れになるだろうなという範疇ではあります。個人的にはSQLがあまり得意ではないので、DBという形すら取らずに、すべて自然言語でDBからAIからすべてのデータソースをクエリできるようにしてほしい。さいごに以上が私が参加した機械学習のセッションのご報告となります。FLECTは明日が最後の参加日となります。明日はキーノートがあります。何か大きな発表があったら、さすがに体力が持たないかも。どこかの会社様は数十人体制で来てるとのこと。今回のような大幅アップデートを4人で捌くのは正直きつい。来年は偉い人にお願いして増員してもらうかな。私は来年も来たいなー。頑張って楽しんできます!では、おやすみなさい。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。