Taste of Tech Topics

Taste of Tech Topics

Acroquest Technology株式会社のエンジニアが書く技術ブログ

Amazon CloudWatch RUM で Angular アプリのパフォーマンスモニタリングをやってみた

はじめに

こんにちは。フロントエンドエンジニアのmiuraです。

本記事では、2021年12月のAWS re:Inventで発表されたAmazon CloudWatch RUMを、
AngularのWEBアプリケーションで実際に利用してみて、使い勝手を確認してみたいと思います。

Amazon CloudWatch RUMの特徴、実際の使い方をお伝えできればと思います。

Amazon CloudWatch RUMとは

概要

Amazon CloudWatch RUMは、WEBアプリケーションのパフォーマンスやエラーなどをモニタリングすることができるサービスです。
例えば、ECサイトに組み込むことで、ユーザーがどの端末やブラウザからアクセスしており、コンテンツの表示速度がどのくらいかなどを簡単にモニタリングすることができ、WEBアプリケーションの改善に役立たせることができます。

f:id:acro-miura:20220228001413p:plain

特徴

Amazon CloudWatch RUMでは、以下の4つをモニタリングすることができます。

  • パフォーマンス
    • WEBアプリケーションのパフォーマンス指標である4つの値が収集され、確認することができます。
      • 時刻別の平均ロード時間
      • 最大コンテンツの描画(LCP)
      • 最初の入力遅延(FID)
      • 累積レイアウトシフト(CLS)
  • エラーとセッション
    • HTTPエラーやJavaScript内の想定外のエラーを一覧で確認することができます。
  • ブラウザとデバイス
    • ブラウザやデバイス、国ごとに平均ロード時間やエラー数などを確認することができます。
  • ユーザージャーニー
    • ユーザーが、WEBアプリケーション内のどのページからアクセスして、どのページに遷移したかを確認することができます。

そして、これらのモニタリングをお手軽に設定できることが、Amazon CloudWatch RUMの最大の特徴になります。

料金

Amazon CloudWatch RUMの料金は「イベント」を単位として、100,000 イベントあたり $1の課金が発生します。
ページの遷移やエラーをそれぞれ1イベントとして計算されるため、JavaScriptや画像などのコンテンツサイズは料金には影響しません。

Amazon CloudWatch RUMを使ったモニタリング

それでは実際に、Amazon CloudWatch RUMを設定し、いかに手軽にWEBアプリケーションのモニタリングをできるかを見ていきたいと思います。

前提

今回は、以下の前提をもとに手順を示します。
1. AWSアカウントを持っている。
2. Node.js v14.15.5以上がインストールされている。

Amazon CloudWatch RUMの新規追加

AWSコンソールで、Amazon CloudWatchを開きます。左のサイドメニューより「アプリケーションのモニタリング > RUM」を選択します。
「アプリケーションモニターを追加」を押下し、アプリケーションモニターの追加画面を開きます。
f:id:acro-miura:20220227213834p:plain

アプリケーションモニターの追加画面では、
 ①アプリケーションモニター名
 ②アプリケーションドメイン
を設定します。
②のアプリケーションドメインには、WEBアプリケーションにアクセスできるドメインを設定します。今回はローカルで動作確認できるように「localhost」を指定します。
上記の①②以外のオプションは、今回、デフォルト設定のままにします。
画面下部の「アプリケーションモニターを追加」を押下し、追加を完了します。

f:id:acro-miura:20220227213940p:plain
f:id:acro-miura:20220227214011p:plain

アプリケーションモニターが追加されると、WEBアプリケーションに組み込むコードスニペットが表示されます。
クリップボードにコピー」を押下して、メモに残しておきます。
※一度閉じた後でもアプリケーションモニターの設定画面から確認できます。

f:id:acro-miura:20220227214313p:plain

WEBアプリケーションへの組み込み

今回、JavaScriptフレームワークであるAngularを用いたWEBアプリケーションに組み込んでみます。

まずは、Angular CLIをインストールします。

npm install -g @angular/cli

Angular CLIを使って、初期プロジェクトを作成します。

ng new my-angular-web-app

初期プロジェクトの作成が完了すると、指定したプロジェクト名(例:my-angular-web-app)のフォルダが作成されるので、そのフォルダを開きます。
そのフォルダ内にある「src/index.html」を編集するため開きます。
「head」タグ内の最後に、Amazon CloudWatch RUMを追加したときに取得したコードスニペットを貼り付けて保存します。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>MyAngularWebApp</title>
    <base href="/" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link rel="icon" type="image/x-icon" href="favicon.ico" />

    <!-- こちらにコードスニペットを貼り付ける -->
  </head>
  <body>
    <app-root></app-root>
  </body>
</html>

ここまでで、すでにモニタリングできる準備は整いました。
しかし、Angularの場合、想定外のエラーをキャッチしてAmazon CloudWatch RUMに送信するために、追加で実装が必要でした。
「src/app」フォルダ配下に「utils」フォルダを作成し、その中で以下のコードで「cwr-error-handler.ts」を作成します。

import { ErrorHandler } from '@angular/core';

declare function cwr(operation: string, payload: any): void;

export class CwrErrorHandler implements ErrorHandler {
  handleError(error: any) {
    console.error(error);
    cwr('recordError', error);
  }
}

「app.module.ts」を開き、「providers」に「ErrorHandler」を追加します。

import { ErrorHandler, NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { CwrErrorHandler } from './utils/cwr-error-handler';

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, AppRoutingModule],
  providers: [
    {
      provide: ErrorHandler,
      useClass: CwrErrorHandler,
    },
  ],
  bootstrap: [AppComponent],
})
export class AppModule {}

以上で、WEBアプリケーションへの組み込みが完了しました。
以下のコマンドでWEBアプリケーションを起動し、http://localhost:4200を開きます。

npm start

WEBアプリケーションを開いた時点でAmazon CloudWatch RUM(https://dataplane.rum.<リージョン>.amazonaws.com)への送信が開始されます。
そして、画面遷移やエラーが発生する度にその情報が送信され、Amazon CloudWatch RUM上に表示されます。

f:id:acro-miura:20220227224600p:plain

パフォーマンスの確認

数回WEBアプリケーションの表示を行うと、Amazon CloudWatch RUM上にログが蓄積し、ウェブバイタルやユーザージャーニーなどにグラフが表示されます。
ウェブバイタルの場合、グラフには「Positive」「Tolerable」「Frustrating」という3つのしきい値があらかじめ設けられています。
それぞれ「Positive」ならパフォーマンスが良く、「Tolerable」なら許容できる程度のパフォーマンスがあり、「Frustrating」ならユーザーがイライラするほどパフォーマンスが悪いことを示しています。

例えば、下図の場合、「最大コンテンツの描画」では、計6回のアクセスのうち5回は「Positive」で、1回は「Frustrating」であったことが、時系列で確認できます。
もし今後「Frustrating」が多くなった場合は、パフォーマンス改善が必要ということになります。

f:id:acro-miura:20220307225723p:plain

また、Amazon CloudWatch RUMでは、WEBアプリケーションが複数ページある場合、それぞれのページを指定して表示することができるため、どのページで改善が必要なのかを確認することもできます。

f:id:acro-miura:20220307231825p:plain

使用感

使いやすい点

  • お手軽にWEBアプリケーションのモニタリングを始められる
    • Amazon CloudWatch RUMの最大の特徴として記載したが、基本的にindex.htmlにコーススニペットを追加するだけで、モニタリングを始めることができるのは良いと思いました。

注意が必要な点

  • JavaScriptフレームワークによっては追加の実装が必要になる
    • AngularなどJavaScriptフレームワークによっては、想定外のエラーを内部でキャッチしてしまうため、今回のような追加の実装が必要になります。
  • 問題を検知して自動で通知してくれる機能がない
    • Amazon CloudWatch RUMは、AWSコンソール上で状況を確認することを前提のサービスのため、メール通知といった機能は自身にはありません。
    • Amazon CloudWatchのアラーム機能を駆使することで閾値による通知を設定することは可能のようです。
  • ユーザージャーニーにて、動的に変わるURLを同じページとみなすためには、追加の実装が必要になる
    • 表示するページは同じだが、中身の値を変化させる場合、「/users/<ユーザーID>」のようにURLを動的に変えることがあります。
    • この動的に変わるURLを同じページとみなしたい場合は、aws-rum-web/cdn_angular.md at main · aws-observability/aws-rum-web · GitHubのように、追加で実装をする必要があります。

さいごに

以上で、Amazon CloudWatch RUMを使ったモニタリングは完了です。

とにかくお手軽にWEBアプリケーションのモニタリングを始めたい、という人におすすめできるサービスだと思いました。
また、X-Rayと一緒に活用することで、よりWEBアプリケーションの運用に役立ちそうです。

それでは。

Acroquest Technologyでは、キャリア採用を行っています。

  • ディープラーニング等を使った自然言語/画像/音声/動画解析の研究開発
  • Elasticsearch等を使ったデータ収集/分析/可視化
  • マイクロサービス、DevOps、最新のOSSを利用する開発プロジェクト
  • 書籍・雑誌等の執筆や、社内外での技術の発信・共有によるエンジニアとしての成長

 
少しでも上記に興味を持たれた方は、是非以下のページをご覧ください。
サーバーレスでサービス開発を行いたいクラウドエンジニア募集! - Acroquest Technology株式会社のシステムエンジニアの採用 - Wantedlywww.wantedly.com

Amazon QuickSightで異常検出してみた

こんにちは、エンジニアの駿です。

最近AcroではWordleが流行っており、親の仕事の都合で中学3年間をアメリカで過ごし英語が得意を売りにしている身としては2回くらいで当てたいと思っているところ。
ですが、なかなかうまくいきません。。。

普段、サーバーレスでの開発をしており、私自身は、QuickSightの利用はまだ経験が浅いのですが、BIで異常検知もできる、ということで、どのようなことができるのか、試してみました。

f:id:acrosyoshioka:20220308111445p:plain:w25:h25 Amazon QuickSightとは

Amazon QuickSightAWSが提供する可視化用のツールで、 各種AWSサービス、サードパーティクラウド、オンプレのデータに接続し可視化できるだけでなく、 機械学習の統合、Qを用いた自然言語の質問を使ったクエリなど、必要な情報を簡単に手に入れることができます。

QuickSightの機械学習機能、ML Insightsには3つの主要機能があります。

  1. 異常検出

    機械学習を用いて、時系列データを分析し、異常を検出します。
    また、異常につながった主な要因の特定、Eメールでのアラートなどを行うことができます。

  2. 予測

    機械学習を用いて、時系列データの予測を行います。
    追加の設定不要で、季節性や欠損値など複雑なシナリオにも自動で対応します。

  3. 自動説明文生成

    最大/最小をはじめとするデータの内容を、自動でわかりやすい説明文として表示することができます。
    必要な情報を得るためにチャートや表を調べる必要がなくなり、また、組織内でデータの理解を共有することができます。

下の画像は公式のQuickSight紹介ページに載っているIoTデバイスの情報を可視化したデモダッシュボードです。
可視化するだけでも必要な情報を一目で見られるようにできて、さらにML Insightsを使うことで異常検出と予測の情報を付け加えることができる、と考えると、非常に強力なツールになりそうです。

f:id:acrosyoshioka:20220223182521p:plain
公式のIoTデモ(https://d2lzvqq4w5ulk4.cloudfront.net/?dashboardName=iot

異常検出してみる

今回は、周期性のある時系列データと複数の要素を含む時系列データを使って、QuickSightの異常検出を実際に試してみます。

f:id:acrosyoshioka:20220306031949p:plain
周期性のある時系列データ

f:id:acrosyoshioka:20220306032015p:plain
複数の要素を含む時系列データ

周期性のある時系列データ

QuickSightのML Insightsを使って異常検出をするためには大きく3つのステップが必要です。 (1) QuickSightにサインアップする、 (2) データをアップロードする、そして最後に (3) ビジュアル/インサイトを追加します。

まずは周期性のある時系列データで各ステップを説明します。

(1) QuickSightにサインアップする

AWS ConsoleからQuickSightを初めて開くとき、サインアップを求められます。 ダイアログに従ってサインアップを行ってください。

なお、Editionを選択するダイアログでは、「Enterprise」を選択してください。 「Standard」を選択してしまうと、ML Insightsの機能が利用できません。

(2) データをアップロードする

QuickSightコンソール右上の「新しい分析」>「新しいデータセット」の順にクリックして、データをアップロードします。

今回は single-anomalydata.csv という名前のファイルを用意しました。 中身は下記の様にセンサーID、日時、値が約10分起きに記録されたシンプルな物になっています。

id timestamp value
sensor01 2018-11-28 00:00:00 151.87
sensor01 2018-11-28 00:09:56 157.66

「ファイルのアップロード」をクリックし、ファイル選択ダイアログで single-anomalydata.csv を選択すると、プレビューが表示されるので、「次へ」をクリックしデータセット作成を完了します。

「設定の編集とデータの準備」を使うと、別のCSVとの結合やフィルタ、列の削除などが行えます。 今回は編集せずにそのまま扱います。

f:id:acrosyoshioka:20220223180617p:plain
ファイルプレビュー

(3) ビジュアル/インサイトを追加

ファイルをアップロードし、データセットを作成した後は、ビジュアルを追加して可視化を行います。

左上の「+追加」>「ビジュアルを追加」を選択し、可視化する要素として「timestamp」と「value」を選択します。
この時、それぞれの要素をクリックするだけで、QuickSightが自動でtimestampをx軸、valueをy軸に設定してくれます。
デフォルトだとtimestampの集計間隔は「日」になっていますが、今回は10分間隔のデータを扱うため、集計間隔を「分」に変更します。
また、y軸の値の集計方法は「合計」「平均」「最大/最小」などから選択することができます。 データに応じて適した集計方法を選択してください。
可視化した結果を図に示します。 今回用意したデータには2018/12/19 7:30前後に異常なデータがあることが分かりました。

次にインサイトの異常検出を使って、この異常を検出できるか試してみます。

f:id:acrosyoshioka:20220223180742p:plain
ビジュアル/インサイトの追加
f:id:acrosyoshioka:20220223180747p:plain
周期性のあるデータ可視化

今度は「インサイトを追加」を選択し、表示されるプルダウンから「異常値検出(ML駆動型インサイト)」を選択します。
続いてビジュアルと同様に「timestamp」と「value」を選択します。 集計間隔と集計方法もビジュアルと同じ設定を行います。
「今すぐ始める」ボタンが現れるため、それをクリックし、異常検出の設定を行います。
「異常検出をセットアップ」画面で異常検出の設定を行うことができます。 今回はすべてデフォルトのままでよいので、右上の「保存」を選択します。
次に「今すぐ実行」ボタンが表示されるので、クリックします。 「異常値の分析中…」と表示されたら、解析が終わるのを待ちます。

5分ほど待つと異常検出の結果が表示されます。
2018/12/19 05:03に異常が見つかったようです。
「異常の探索」を選択し、詳細を見てみます。

f:id:acrosyoshioka:20220223180721p:plain
異常発見

ビジュアルを作成して、目視で確認できた7:30前後の異常が確かに検出できていました。
普段であれば、正常データを機械学習モデルに学習させて、そのモデルを使って異常検出をしていたところ、QuickSightのML Insightsを使えば画面をポチポチするだけでカンタンにできてしまいました。

f:id:acrosyoshioka:20220223180744p:plain
以上詳細

複数の要素がある時系列データ

次に要素の多いデータでもML Insightsを試してみました。

先ほどのデータセットでは値を1つしか使いませんでしたが、今度は、気温、湿度など5つの要素を持つデータを準備しました。 こちらのKaggleのデータセットを元にしています。
表の様に5つの要素を縦持ちにしたセンサーデータです。 また、値は各要素毎に値が0-1の範囲に収まるように正規化してあります。

Time SensorType Value
2021-06-15 18:21:46 Temperature 0.314
2021-06-15 18:21:46 Humidity 0.386
2021-06-15 18:21:46 Air Quality 0.0
2021-06-15 18:21:46 Light 0.380
2021-06-15 18:21:46 Loudness 0.161

Time列がUnix時間となっており、このままだとQuickSightが日時と認識してくれないため、「設定の編集とデータの準備」で計算フィールドを追加し、Unix時間から日時文字列への変換を行いました(epochDate({Time}))。

可視化した結果がこちらです。

f:id:acrosyoshioka:20220223180733p:plain
複数要素可視化

また、時間にTime、値にValue、カテゴリにSensorTypeを設定して異常検出を実施したところ、下記のように各要素で異常が発生した箇所を見つけることができました。 線が紺色になっている部分が、異常が検出された部分です。また、異常の開始時刻は紺色の点で示されています。

f:id:acrosyoshioka:20220306033118p:plain
Temperature
f:id:acrosyoshioka:20220306033120p:plain
Humidity
f:id:acrosyoshioka:20220306033122p:plain
Light

下の様に、各要素で異常が発生した日時をまとめて確認することもできるため、同時期に他にどのような異常が発生しているのかを一度に確認することができます。

f:id:acrosyoshioka:20220223180730p:plain
Multiple

ただし、上記の様に各要素毎に異常がある部分を検出することはできましたが、要素間の異常検出は現状できないようです。

例えば可視化した図を見ると、TemperatureとLightに相関があり、TemperatureとHumidityに負の相関があることが分かりますが、 この相関が崩れた時に異常と判定する、といったことはできません。
あくまで一度に異常を検出できる時系列データはひとつだけの様です。

f:id:acrosyoshioka:20220223180735p:plain
2つ設定できない

同様に、Temperatureに異常があったときに、どの要素がその異常に最も寄与しているかを産出させることもできません。
QuickSightの異常検出には「上位の寄与要因」といって、異常の背後にある主要な要因を見つける機能があるのですが(「異常検出をセットアップ」で設定可能)、 この機能はカテゴリデータのみに対応しており、時系列データは扱えません。
この寄与要因はチュートリアルやサンプルを見る限り、「会社の売り上げが大きく下がったときに、どの地域の売り上げがよくなかったのか、どの分野の売り上げがよくなかったのか」といった要因を調べるための物の様でした。

このような相関分析ができるようになると、活用の幅がさらに広がりそうです。

料金

ML Insightsを用いるには、評価されたメトリクス数に応じて料金がかかります。

評価されたメトリクス 料金/1,000 評価されたメトリクス
1~1,000,000 $0.5
1,000,001~10,000,000 $0.25
10,000,001~100,000,000 $0.1
>100,000,000 $0.05

評価されたメトリクス数は、メトリック数x評価回数を元に計算されます。 評価方法などはQuickSight料金計算ツールの例を参考にしてください。

If you set up one alert to run hourly, that would bill as 24 metrics per day (or 720 metrics per month).
If you set up an Anomaly Detection job to watch “sales”, and then added break-downs by region (four regions) and product category (let’s assume 10 categories),
that could be up to 55 metrics (1 sales + 4 regions + 10 categories + 4*10 region-categories, depending on if you choose to run it for all combinations of the data).
If you ran that anomaly job daily, you’d expect to run 1.65 per thousand metrics (55 * 30 = 1,650) per month.

それ以外に、ユーザーごとの料金として、Enterprise Edition だと、Authorユーザー(ダッシュボードの作成者)で$24/月、Readerユーザー(ダッシュボードの閲覧者)で最大$5/月の料金がかかります。

今回は評価されたメトリクスが1,000に満たないため、Authorユーザの料金と合わせて、$24.5ほどでQuickSightとML Insightsを利用することができました。
上の例のように55のメトリクスを一日一回異常検出に使用したとすると、ひと月に異常検出にかかる料金は$1弱になる計算なので、非常に安く利用できると思います。

注意点

形式

いくつか、ML Insightsの異常検出を利用するにあたって注意が必要な箇所がありました。

  1. 解析されるデータは時系列データである必要がある。

    時折、時系列データでも日時ではなく、インデックスが振ってある物がありますが、 インデックスが日時カラムと認識されないため、QuickSightが時系列データとして扱ってくれません。
    また、日時カラムが文字列ではなくUnix時間になっている場合は、上で紹介したように、データ読み込み時に変換する必要があります。

  2. 横持ちより縦持ちの方が扱いやすい。

    カラムに各要素の値を持つ横持ちのデータも、要素毎に行が分かれている縦持ちに変換することで、カラム名をカテゴリとして活用できるようになります。

    横持ちのデータも分析はできますが、複数の要素がある時系列データで示したようにまとめて異常検出をすることや、 ML Insightsの機能の一つである、「上位の寄与要因」の分析ができない、といったデメリットがあります。

    縦持ちデータの例

    日時 センサ種類
    2021-06-15 18:21:46 温度 20.5
    2021-06-15 18:21:46 湿度 30.5
    2021-06-16 18:21:46 温度 21.5
    2021-06-16 18:21:46 湿度 28.5

    横持データの例

    日時 温度 湿度
    2021-06-15 18:21:46 20.5 30.5
    2021-06-16 18:21:46 21.5 28.5

データ量

異常検出を実行する前に要件を確認してください。

  • 少なくとも1つの日付ディメンションが必要
  • 異常検出のトレーニングに最低15のデータポイントが必要

などの要件があります。

まとめ

今回はAmazon QuickSightのML Insightsを使って異常検出をしてみました。

低コストで簡単に異常検出を行うことができ、びっくりしました。
1つ目に紹介した、周期性のある時系列データを用いた内容を実施するのに30分ほどしかかかりませんでした。

これだけ簡単にできるのは、学習データの準備など煩わしいことをしなくても、 ML Insightsが教師なし学習をしてくれるからで、専門知識がない人でも適用できると思われました。

また、現状、相関分析まではできないようですが、複数の系列データを一度に分析できるのも、実用的だと感じました。

是非皆さんも一度試してみてください。

Acroquest Technologyでは、キャリア採用を行っています。
  • ディープラーニング等を使った自然言語/画像/音声/動画解析の研究開発
  • Elasticsearch等を使ったデータ収集/分析/可視化
  • マイクロサービス、DevOps、最新のOSSを利用する開発プロジェクト
  • 書籍・雑誌等の執筆や、社内外での技術の発信・共有によるエンジニアとしての成長
  少しでも上記に興味を持たれた方は、是非以下のページをご覧ください。 www.wantedly.com

AWS CodeBuildでKarateを動かし、E2E/UIテストを自動化しよう

こんにちは、DevOpsエンジニアとして活動している横山です。

以前、本ブログ内で「KarateのDockerイメージを使用して、UIテストを自動化してみた - Taste of Tech Topics」を紹介しました。
今回は、E2Eテストを行う「Karate」をAWS上で実行し、テストを自動化する方法を紹介します。

クラウド上でKarateを実行することで、次のメリットが生まれます。

  • チーム全体でテスト結果を共有でき、修正が行いやすくなる
  • Gitへのプッシュをトリガーにテストを実行でき、問題に早く気づけるようになる

また、今回CodeBuildの実行環境として、AWSにより管理されているマネージド型Dockerイメージではなく、
カスタムDockerイメージを使用しましたが、その際の注意点も合わせて紹介します。

概要

本記事では、以下の内容について説明を行います。

  • AWS CodeBuildを用いたKarateの実行
  • Kareteのレポートを確認できるようにS3にアップロード
  • CodeBuildの実行環境としてカスタムDockerイメージを使用する際の注意点

Karate実行結果として以下のような結果がチーム全体で見られるようになります。
f:id:acro-yokoyama:20220225214142p:plain:w800
f:id:acro-yokoyama:20220225214152p:plain:w800

前提

Karateの詳細については、以下を参照ください。
qiita.com

全体構成

f:id:acro-yokoyama:20220213232615p:plain:w500

パイプラインの構築・実行

設定内容の流れとしては以下のようになります。

  1. buildspec.yml、Karateソースコードの準備
  2. CodeBuildの設定
  3. サービスロールの設定
  4. CodeBuild実行
  5. 結果確認

それでは、詳細です。

1. buildspec.yml、Karateソースコードの準備
以下のようなディレクトリ構成でKarate実行に必要なファイルをAWS CodeCommitにプッシュします。

karate-sample
├─ buildspec.yml  ・・・CodeBuildの定義ファイル
└─ src
    └─ test
        └─ ui
            └─ karate-git.feature  ・・・UIテストのシナリオファイル

buildspec.ymlの内容は以下になります。

version: 0.2
env:
  variables:
    # レポート配置用に作成したバケット名を指定
    REPORT_S3_BUCKET: karate-sample-bucket
phases:
  pre_build:
    commands:
      # 元のDockerイメージのENTRYPOINTで実行される想定だった処理を実行
      - echo Start Chrome
      - nohup /entrypoint.sh & # ★1
      # Karate実行ファイルをダウンロード
      - echo Download karate.jar
      - mkdir -p lib
      - curl -L -o ./lib/karate.jar https://github.com/karatelabs/karate/releases/download/v${KARATE_VERSION}/karate-${KARATE_VERSION}.jar
      # S3へのアップロードのために、AWS CLIをインストール
      - echo Install AWS CLI ...
      - curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
      - unzip awscliv2.zip
      - ./aws/install --bin-dir /usr/local/bin --install-dir /usr/local/aws-cli --update
  build:
    commands:
      # MavenによるKarateテスト実行
      - echo Karate Test...
      - java -jar lib/karate.jar -f cucumber:json src/test
  post_build:
    commands:
      # S3にレポートをアップロード
      - echo Uploading Karate results...
      - aws s3 sync ./target/karate-reports s3://${REPORT_S3_BUCKET}/karate/karate-reports --no-progress --delete

<注意点>
CodeBuildの環境イメージとして、AWSのマネージド型イメージではなく、カスタムイメージを使用する際、ENTRYPOINTはオーバーライドされるようです。
CodeBuild のDocker サンプル - AWS CodeBuild
今回利用する「ptrthomas/karate-chrome」イメージでは、ENTRYPOINTの処理にてKarate UI実行のために必要なプロセスを実行するため、そのままではKarate UIが実行できません。
そのため、本来ENTRYPOINTで実行したかった処理を、buildspec.ymlのpre_buildで実行するように記述しています。
(buildspec.ymlの★1の部分)

Karateのコードの詳細は割愛しますが、以下のコメントに書いたテストケースを実行します。

  • karate-sample/src/test/ui/karate-git.feature
Feature: GitHubのファイル確認

Background:
  # driver設定
  * configure driver = { type: 'chrome', start:false, headless: true, addOptions: ['--window-size=1920,1080']}

  # UI操作開始
  Given driver 'https://github.com/karatelabs/karate'
  * screenshot()

Scenario: land on the karate github page, and search for a file

  # 「Go to file」をクリックしてファイル一覧に遷移する
  When click('{a}Go to file')
  Then waitForUrl('karate/find/master')

  # 検索エリアに「karate-logo.png」を入力する
  And waitForEnabled("input[name=query]").input('karate-logo.png')
  * delay(500)
  * screenshot()
  
  # 1件以上ヒットすることを検証する
  Then assert locateAll("ul#tree-browser li[role=presentation]") > '#[1]'

2. CodeBuildの設定

AWSコンソールのCodeBuild画面から、「ビルドプロジェクトを作成する」をクリックし、以下のように設定して作成します。
(デフォルトから変更する箇所のみ記載しています。)

<注意点>
実行環境として指定するDockerイメージが、DockerHubなどの公開されているイメージの場合、CodeBuildでのダウンロード制限に引っかかる場合があります。
その場合は、以下を参考にするか、ECRにイメージをプッシュし、ECRから取得(プル)する設定にすることで対処可能です。
CodeBuild の「イメージ設定のプルエラー: toomanyrequests」エラーを解決する

①CodeBuildのビルドプロジェクト名を入力(任意)
f:id:acro-yokoyama:20220212165226p:plain:w650

②テストコードをプッシュしたリポジトリを指定
f:id:acro-yokoyama:20220212165239p:plain:w650

③CodeBuild上でのKarate実行環境のDockerイメージ、実行時に利用する環境変数、CodeBuildに適用するロールを設定
f:id:acro-yokoyama:20220212165246p:plain:w650
f:id:acro-yokoyama:20220213230959p:plain:w650
f:id:acro-yokoyama:20220212165302p:plain:w650

④CodeBuildで使用するbuildspecファイルを指定
f:id:acro-yokoyama:20220212165312p:plain:w650

⑤CloudWatch Logsへのログ出力設定を指定
f:id:acro-yokoyama:20220212174946p:plain:w650

3. サービスロールの設定

作成されたサービスロールに対し、以下のポリシーを追加します。

  • s3:ListBucket
  • s3:PutObject
  • s3:DeleteObject

※リソースは、レポート配置用のバケットを指定

4. CodeBuild実行
作成したCodeBuildのプロジェクトを開き、「ビルドを開始」から実行できます。

5. 結果確認

CodeBuildでビルドを実行すると、Karateテスト実行後に、レポートファイルがS3の指定のバケットにアップロードされます。
Karateレポート出力用のバケットの中の、以下のファイルをブラウザで開くことで、キャプチャも含めたレポートを確認することができます。

  • karate/karate-reports/karate-summary.html

f:id:acro-yokoyama:20220225214142p:plain:w800
f:id:acro-yokoyama:20220225214152p:plain:w800

まとめ

今回は、AWS CodeBuildを用いたUIテストを含んだKarate実行と、S3へのレポートファイルのアップロードについて説明しました。
これにより以下のようなメリットが得られます。

  • Karateを利用することで、ユースケースを意識したシナリオテストを実施しやすい
  • E2Eテストを自動化することで、リグレッションテストの手間を大幅に削減でき、変更の影響の検知を素早く行える
  • 画面キャプチャもレポートに組み込むことができ、テストの結果やエラーの内容をすぐに確認可能

チームの中で、テスト実行を継続して実行することで、
リリースサイクルが高速化する中でも、品質向上につながると思いますので、参考にしていただけたらと思います。

それでは。

Acroquest Technologyでは、キャリア採用を行っています。

  • ディープラーニング等を使った自然言語/画像/音声/動画解析の研究開発
  • Elasticsearch等を使ったデータ収集/分析/可視化
  • マイクロサービス、DevOps、最新のOSSを利用する開発プロジェクト
  • 書籍・雑誌等の執筆や、社内外での技術の発信・共有によるエンジニアとしての成長

 
少しでも上記に興味を持たれた方は、是非以下のページをご覧ください。
www.wantedly.com
www.wantedly.com

AWS MLOps Workload Orchestrator で機械学習モデルのデプロイ/検証の自動化を体感してみた


こんにちは、DevOpsチームの@buzz_tkcです。
最近枕を「ヒツジのいらない枕」に買い換えました。2020年にクラウドファンディングで話題になっていた時から、キャッチーなネーミングと興味がそそられるフォルムが気になっていたはいたのですが、やっと重い腰を上げて買い換えました。弾力があり高さのある枕が好みの自分にとてもフィットしており、おかげさまで睡眠が捗っております。

さて、今回は AWSが公開している「MLOps Workload Orchestrator」を、試してみたいと思います。

機械学習プロジェクトにおいて、以下のような課題に直面したことがある人は多いのではないでしょうか?

  • 学習リソース不足
    • GPUマシンが足りず、並列実験ができない、、、
  • ローカルで検証したモデルを本番環境へ適用するのに時間がかかる
    • デプロイの自動化が大変、、、
  • 実験が再現できず、品質保証ができない
    • 何個か前の精度が良かった学習の再現が難しい、、、

そのような際に、MLOpsのプラクティスが有効とされていますが、自分も機械学習エンジニアではないため、何をどのようにすれば良いのか、イメージを持てていなかった部分があるので、「MLOps Workload Orchestrator」を試してみて、理解を深めていきたいと思います。

MLOps とは?

MLOpsとは、「機械学習チーム(Machine Learning)/開発チーム(Developers)」と「運用チーム(Operations)」がお互いに協調し合うことで、機械学習モデルの実装から運用までのライフサイクルを円滑に進めるための管理体制(機械学習基盤)を築くこと、またはその概念全体を指します。まさにDevOpsの機械学習版ですね。(MLOps = ML + Dev + Ops

Wikipediaにも、DevOpsの概念がベースとなって、MLOpsが生まれたと書かれていますね。

ソフトウェア開発ライフサイクル全体におけるワークロードの管理は、従来からDevOpsの概念があった。機械学習プロジェクトにDevOpsを適用した場合、モデルトレーニング等を含むのCI/CDのプロセス管理やデータサイエンティストとデータエンジニアの職種の役割分担など多数の機械学習特有の課題を考慮する必要が生まれた。その結果DevOpsをベースに機械学習プロジェクトに合理化された手法がMLOpsとして概念化された。

MLOPs Wikipedia


機械学習で精度の高いモデルを作るためには、多くの時間を試行錯誤に費やしモデルを育てていく必要があります。しかし実際には、動作環境の構築、システム全体の開発など、モデル作成以外でもやるべきことが多く、モデル作成に時間を多く割けないことが多いです。MLOpsを実践し、機械学習ワークフローの自動化・効率化を進めていくことで、良いモデルを育てるというコアな部分に、多くの時間を費やすことができるようになります。


AWS MLOps Workload Orchestrator とは?

MLOps Workload Orchestrator」は、AWS機械学習サービスとサードパーティーサービスの機械学習パイプラインを管理するためのフレームワークで、機械学習モデルの運用向けにアーキテクチャのベストプラクティスを合理化および強制するのに役立ちます。

具体的には、このサンプルテンプレートを使用し、トレーニング済みのモデル(自分で用意する)をデプロイすることで 、モデルのデプロイや運用/監視を簡単に実現することができます。モデルのデプロイや運用/監視を自動化することで、モデルの検証や更新のサイクルを高速に回すことができ、プロジェクト全体の俊敏性と効率を上げることができます。
aws.amazon.com

AWS MLOps Workload Orchestrator を使ってみる

このサンプルテンプレートでは、同アカウントへのデプロイと、マルチアカウントへのデプロイと大きく二種類対応しています。今回は同アカウントへのデプロイを扱います。アーキテクチャは以下になります。

やることとしては、以下の3つです。

  1. CloudFormationテンプレートを実行してスタックを作成
    • 通知用のメールアドレスを入力するだけでスタックを作成できます。
  2. パイプラインをプロビジョニングして機械学習モデルをデプロイ
    • パラメータを指定して、APIを実行する or Code Commitのルート直下にmlops-config.jsonをコミットすることで、パラメータによって指定されたCloudFormationが実行されます。その後、ワークフローに応じたCode Pipelineが作成・実行され、必要なリソースの作成と、モデルのデプロイが行われます。
  3. モニタリング用パイプラインのプロビジョニング
    • 2.の実行が完了し、機械学習モデルがエンドポイントにデプロイされている状態で、実行する必要があります。


学習(モデルの作成)自体はスコープ外なので、事前準備として、学習済みモデルが必要です。今回は、AWSが公開している公式サンプルを実行して用意しました。

1. CloudFormationテンプレートを実行してスタックを作成

CloudFormationのManagement Consoleに移動し、CloudFormationテンプレートから、「mlops-workloadorchestrator-single-account-framework.template」を選択します。
以下のパラメータの中から、必須項目の通知用メールアドレスを入力して、スタックを作成します。

この段階で、赤枠の部分が作成されます。

2. パイプラインをプロビジョニングして機械学習モデルをデプロイ

続いて、機械学習モデルデプロイのワークフローを実行します。Code Commitのレポジトリルート直下にmlops-config.jsonをコミットするか、APIにリクエストを送ることで、ワークフローを実行できます。今回はAPIへのリクエストを試してみます。

先程実行したCloudFormationで「/provisionpipeline」と「/pipelinestatus」二つのエンドポイントが作成されているので、「/provisionpipeline」に対して、学習済みモデルをエンドポイントにデプロイするためのリクエストを投げます。「/pipelinestatus」は「/provisionpipeline」実行後、パイプラインのステータス確認用として使用できます。

EndPoint:/provisionpipeline
Method:POST
Body:

{
"pipeline_type" : "byom_realtime_builtin", # Sage Makerが用意しているビルトインアルゴリズムを使用してのリアルタイム推論を行うパイプラインをプロビジョニング
 "model_framework": "xgboost", # モデル作成時に使用したフレームワーク
 "model_framework_version": "1", # フレームワークのバージョン 
 "model_name": "my-model-name", # Amazon SageMaker modelや、エンドポイント作成時に使用されるモデル名
 "model_artifact_location": "path/to/model.tar.gz", # 事前に学習し、S3に格納しておいたモデルパス
 "data_capture_location": "<bucket-name>/<prefix>", # エンドポイントへの推論結果のデータキャプチャを保管S3へのパス
 "inference_instance": "ml.m5.large", # エンドポイントで使用するインスタンスタイプを指定
 "endpoint_name": "custom-endpoint-name" # エンドポイント名を指定
}

「byom_realtime_builtin」用のパイプラインがプロビジョニングされ、エンドポイントが立ち上がり、推論を行うことができるようになりました。簡単に推論を行える環境が用意できるので、非常に便利ですね!

3. モニタリング用パイプラインのプロビジョニング

さきほど作成したエンドポイントのモニタリングを行うワークフローを実行し、モニタリング用のパイプラインをプロビジョニングします。エンドポイントにデプロイされたモデルに対し、ベースとなるデータセットを実行し、実際に飛んできている推論データとの統計情報を可視化することで、モデルがビジネスゴールを満たしているかどうかの指標を得ることができます。

EndPoint:/provisionpipeline
Method:POST
Body:

{
 "pipeline_type" : "byom_data_quality_monitor", # 推論やテストデータの評価を行うパイプラインをプロビジョニング
 "model_name": ""my-model-name"", # モデル名(リソース作成時に命名として使用されます)
 "endpoint_name": "xgb-churn-prediction-endpoint", # 評価対象のエンドポイント名
 "baseline_data": "path/to/data_with_header.csv", # S3に格納してある評価用データ(ヘッダー付きcsvファイル)へのパス
 "baseline_job_output_location": "<bucket-name>/<prefix>", # モデルデータ評価を行うジョブ結果を格納するS3へのパス
 "data_capture_location": "<bucket-name>/<prefix>", # エンドポイントへの推論結果のデータキャプチャを保管S3へのパス
 "monitoring_output_location": "<bucket-name>/<prefix>", # モニタリング結果のアウトプットを格納するS3へのパス
 "schedule_expression": "cron(0 * ? * * *)", # 評価ジョブ実行タイミングのスケジューリング
 "instance_type": "ml.m5.large", # 評価ジョブ実行で起動するインスタンスタイプ
 "instance_volume_size": "20", # 評価ジョブ実行で使用するボリュームサイズ
 "baseline_max_runtime_seconds": "3300", # 評価ジョブの起動時間上限
 "monitor_max_runtime_seconds": "3300" # モニタリングジョブの起動時間上限
} 

モニタリングの結果を確認します。 Sagemaker Studio左メニューから SageMaker resourcesを選択 >プルダウンからエンドポイントを選択 >エンドポイント名をダブルクリック >Monitoring job historyタブを選択 >「issue found」をダブルクリックして下さい。


続いて、「View Amazon SageMaker notebook」リンクをクリック > 「Import notebook」ボタンをクリックすることで、モニタリング結果を可視化してくれるnotebookが実行できるようになりました。

notebookを実行することで、モニタリング結果の可視化を行うことができました。グラフのところで、collectedが推論で飛んできているデータで、baselineが事前にベースとして用意していたデータです。データの差分や、偏り、傾向等が、感覚ではなく視覚的に確認できるのは嬉しいですね!

利用してみての所感

AWS MLOps Workload Orchestrator」を利用してきましたが、学習したモデルを簡単にデプロイできたり、状態を可視化できたりと非常に便利でした。特に、モニタリングのワークフローでは、データセットやモデルの統計情報を可視化することで、モデルがビジネスゴールを満たしているかを確認することが容易にできるので、効果的にモデルを育てていくというライフサイクルを回すことができそうだと感じました。

後は、一般的なMLOPsだと、

  • モデルの精度を評価(テスト)して、承認者が精度で問題ないことを確認した後、当該モデルをデプロイする
  • 継続的にモデルの精度劣化等をモニタリングして、必要であれば再学習を行う

ということもよくやるみたいですね。

どこまで自動化・効率化していくのかは、プロジェクトの目的や規模などによって変わるとは思いますが、今回学んだことを活かして、自分達の組織やプロジェクトに合ったMLOPsというものを考えていきたいと思います。

それでは。

Acroquest Technologyでは、キャリア採用を行っています。

  • ディープラーニング等を使った自然言語/画像/音声/動画解析の研究開発
  • Elasticsearch等を使ったデータ収集/分析/可視化
  • マイクロサービス、DevOps、最新のOSSを利用する開発プロジェクト
  • 書籍・雑誌等の執筆や、社内外での技術の発信・共有によるエンジニアとしての成長

 
少しでも上記に興味を持たれた方は、是非以下のページをご覧ください。
Kaggle Grandmasterと話したいエンジニアWanted! - Acroquest Technology株式会社のデータサイエンティストの採用 - Wantedlywww.wantedly.com

Kaggleで開催された「Sartorius - Cell Instance Segmentation」でゴールドメダルを獲得しました

皆さんこんにちは。
@tereka114です。

昨年の年末までKaggleで開催された「Sartorius - Cell Instance Segmentation」に取り組み、4位を獲得しました。
本記事では、簡単にそのサマリを掲載します。

コンペティション概要

画像の中から、脳の試験細胞を見分けるコンペティションです。
具体的には細胞を個別にSegmentationする所謂、Instance Segmentationを行うコンペティションです。
Detectionは物体の領域に矩形を付けるものになりますが、Instance SegmentationはDetectionした上で、矩形の中の前景を抽出します。

投薬の反応によって、神経病(アルツハイマーなど)の病気に対する創薬に役立てるようですが、この確認に非常に手間がかかっているそうです。
そのため、セルのInstance Segmentationを試み、反応を自動的に判断するのに役立つコンペが開催されました。

www.kaggle.com

細胞のサンプルは次の通りです。

f:id:tereka:20220129215210j:plain:w720
コンペティションで扱う細胞画像のサンプル

※本可視化には次のNotebookの画像を利用させていただいています。
Sartorius Cell Instance Segmentation - EDA | Kaggle

このコンペティションに参加した理由は次の通りです。

  • 最近、Instance Segmentationのコンペティションは開催されておらず、興味があったこと。
  • 外部データや正確なラベルがないSemi-Supervised Learning用のデータセットが配布されており、データに工夫の余地が多くあり、面白そうだと思ったこと

今回のコンペティションで難しいポイントは次の通りです。

1. 細胞の数
Detection/Instance Segmentationの論文の多くで利用されているCOCOのデータセットの1画像中最も多いオブジェクト数は92です。
しかし、今回の細胞データでは細胞の種類(astro, shsy5h, cort)によって異なりますが、最大700をも超えるオブジェクト数が存在します。
そのため、COCOのデータで最適化されたモデルでは不十分で、多くの物体を検出するには、パラメータの一部を修正する必要がありました。

2. データセット
このコンペでは、Kaggleで外部データであるLive CellとSemi-supervised learningで利用するデータセットが用意されていることが特徴的です。
LiveCellはコンペティションで提供されているものがshsy5hと呼ばれる細胞の種類以外は別のものではありますが、Segmentationのアノテーションがされています。
また、Semi-Supervised learningの画像には、細胞の種類は提供されていますが、マスク情報は存在しないため、そのまま利用できません。

ソリューション

全体の流れ

チーム全体の詳細はこちらに記載しています。
www.kaggle.com

f:id:tereka:20220129201318p:plain:w720
ソリューションの全体図

全体の流れは次の通りです。

  • Instance Segmentitonで得られた結果に基づいて、細胞全体の画像を分類する。(単純に分類されたセルの多いものを採用)
  • 分類した細胞ごとに別々のInstance Segmentationのモデルを用いる。
  • 細胞ごとにアンサンブルやSegmentation Modelを用いたPost Process、Fix Overlap処理を行う。

※図中のshsy5y, astro, cortは細胞名由来の名称

Fix Overlapは、本コンペティションでは、提出形式としてセルのマスクの重複を許容していないため、その対応の処理です。
(細胞Aと細胞Bで同じPixelを指定できないので、片方にする必要がある。)
また、細胞に関して後処理に違いがあるのは、各処理を適用した際にCV/LBを見て精度が上がったものと下がったものがあり、その違いが後処理の内容に反映されています。

モデル作成

Classification/セルのマスク取得にはInstance Segmentationのモデルを作成しました。
具体的には次の手順を踏んでいます。

  • モデルはCBNetV2 + CascadeRCNNやResNeXt101+Hybrid Task Cascadeを利用
  • それぞれの細胞ごとにモデルとハイパーパラメータ群をチューニング
  • Semi-Supervised Learningのデータに学習済のモデルでラベルを付与(後述)
  • 事前学習として、Live Cellを学習した後、Semi Supervised Learningのデータで再学習(後述)

CBNetV2 + CascadeMaskRCNN(CRNN)とResNeXt101 + Hybrid Task Cascade(HTC)を用いたのは、最終的に精度が良かったためです。
他にもDetectors + HTC、ResNet50 + HTC、さらにはSwin Transformer + CRNNなど様々なモデルを試していましたが、アンサンブルなどに利用しても精度向上に貢献しませんでした。

チーム全体の実装はDetection/Instance Segmentationのフレームワークmmdetectionを利用しました。
設定のみで様々なアルゴリズムの利用ができる&学習済モデルが多いので、個人的にもYoloX/YoloV5を利用しないときにはmmdetectionをよく利用します。

今回は、COCOでSoTAを達成した物体検出の方式であるCBNetV2を利用したかったため、まだ実装されていない既存のmmdetectionに対してCBNetV2が追加されたリポジトリを用いました。

github.com

ハイパーパラメータ群のチューニング

mmdetectionは様々なモデルのconfigと学習済モデルが配布されています。
SoTAの計測がCOCOである論文がほとんどであるため、mmdetectionの物体検出パラメータはCOCOに最適化されています。
しかし、COCOとはデータセットの傾向が大きく異なるため、ハイパーパラメータを今回のデータセットに向けて大きく変更すると精度が向上しました。
具体的には、次のパラメータを変更して実行していました。
COCOと比較して、オブジェクト数が多いので、NMSでフィルタリングする数をCOCOよりも緩めると、精度向上します。

rpn_proposal.nms_pre=4000,
rpn_proposal.nms_post=4000,
rpn_proposal.max_per_img=4000

anchor_generator.ratios=[0.25, 0.5, 1.0, 2.0, 4.0]

外部&追加データの検討

先にも簡単に書きましたが、外部データであるLiveCellと追加データとしてSemi-Supervised Learningを行うためのデータが配布されていました。
これらのデータを有効に利用すると精度向上する可能性がありました。

Semi-Supervised Learningのデータは細胞の種類が記載されたCSVがありますが、マスクのアノテーションは存在していません。
学習にこのデータを利用する方法としていくつかありますが、チームでは学習モデルから予測した結果であるPseudo Labelingをすることで、学習に使えるようにしました。

1. LiveCell + Trainingデータを用いて学習したモデルを利用して、Semi-Supervised Learningを推論し、アノテーションする。
2. LiveCellで事前学習したモデルに対して、Semi-Supervised Learningのアノテーションした画像を学習する。
3. 最後にTrainingのデータでFinetuneする。

2で作成されたラベルはノイズが含まれているので、その影響を修正する役割として3を実行しました。
Semi-Supervised LearningとTrainingのデータを同時に学習させた場合と比較して、2,3のステップを踏むほうが精度が向上します。

最後に

Instance Segmentationは検討する内容も多く、コンペ終了後に他チームの共有されたソリューションを振り返ると様々な問題の解き方がありました。
これをうまく業務にも応用していきたいと考えています。

Acroquest Technologyでは、キャリア採用を行っています。


  • ディープラーニング等を使った自然言語/画像/音声/動画解析の研究開発
  • Elasticsearch等を使ったデータ収集/分析/可視化
  • マイクロサービス、DevOps、最新のOSSを利用する開発プロジェクト
  • 書籍・雑誌等の執筆や、社内外での技術の発信・共有によるエンジニアとしての成長

 
少しでも上記に興味を持たれた方は、是非以下のページをご覧ください。

Kaggle Grandmasterと話したいエンジニアWanted! - Acroquest Technology株式会社のデータサイエンティストの求人 - Wantedlywww.wantedly.com

AWSでお手軽時系列データの異常検知 ~Lookout for Metricsを試してみた~

はじめに

機械学習アプリケーションエンジニアの@yktmです。
本記事では、2020年12月のAWS re:Inventでアナウンスされ、2021年3月にGAとなった、
Amazon Lookout for Metricsを、実際に利用してみて、使い勝手を確認してみたいと思います。

Amazon Lookout for Metricsの特徴、実際の使い方をお伝えできればと思います。

Amazon Lookout for Metricsとは

概要

Amazon Lookout for Metricsは、機械学習を使った時系列データ分析を、機械学習の知識なしに簡単に始められるサービスです。

例えば、ECサイトトラフィックに発生した異常な外れ値を検知し、アラートを出す、という仕組みを簡単に構築することができます。

特徴

Lookout for Metricsの大きな特徴は、3つあります。

  • 機械学習による分析
  • Lookout for Metricsは機械学習に基づく分析を、機械学習の知識なしに使える点が最大の特徴です。
  • 柔軟なデータ連携
  • 分析対象とするデータは、S3、RDSなどのAWS関連サービスのほかに、
    SalesforceGoogle Analytics、Zendeskなどからシームレスに接続できます。
  • アラートのカスタマイズ性
  • Amazon SNSAWS Lambdaはもちろん、Slack、Datadog、WebHookなどに対しても、
    カスタマイズしたアラートを送信することができます。

    分析としては、複数のパラメーターの関連を見た異常検知や、複数項目を同時に異常検知することも可能な点が嬉しい点です。
    例えば、地域と時間帯から店舗収益の異常を検知したり、アクセス数と収益を同時に異常検知する、といったことができます。

    Amazon Lookout for Metricsを使った分析

    次に、Lookout for Metricsを使い、いかに手軽に分析できるかを見ていきたいと思います。

    検証データセット

    利用するデータセットは、AWS公式Githubで提供されているE-Commerceのサンプルデータを利用していきます。 zipファイルダウンロード・解凍し、backtest/input.csvが利用するファイルです。

    CSVの中身は、プラットフォームと利用国ごとの、閲覧数・収益を1時間おきに記録した履歴データになります。 期間は、2021/01/01から2021/09/30までです。

    カラムは以下の5つとなっています。

    カラム名 説明
    platform 利用デバイスと利用媒体 (pc_web, mobile_web, mobile_appの3パターン)
    marketplace 利用国 (us, uk, de, fr, es, it, jpの7パターン)
    timestamp タイムスタンプ
    views 閲覧数
    revenue 収益

    このデータから、閲覧数と収益の異常を見つけ、どのプラットフォーム・利用国で、何時に異常が発生したかを分析していきたいと思います。

    設定手順

    以下の順に設定していきます。
    1. Detector(分析器)の作成
    2. データセットを作成 / Detectorの有効化
    3. 分析結果の確認
    4. アラート設定

    1. Detector(分析器)を作成

    AWS コンソールで、Amazon Lookout for Metricsを開きます。 Create Detectorを押下し、分析器の作成画面を開きます。

    f:id:yktm31:20210930064417p:plain:w700

    分析器の作成画面では、
    ①分析器の名前
    ②分析のインターバル
    を設定します。

    分析のインターバルとは、分析の細かさを示します。 ここでは、1 hourを指定しています。
    1 dayにすれば1日単位で粗く分析でき、10 minuteにすれば10分単位の細かい分析が可能になります。
    後述しますが、与えられたデータを学習用とテスト用に分けて検証するBacktestモードでは、interval x 285(1dayなら285日分)のデータが必要になる点は注意が必要です。 分析のインターバルによって、利用料金が変動することはありません。(コストについては記事後半で解説しています。)

    f:id:yktm31:20210923172703p:plain:w700

    設定が完了したら、「Create」を押します。

    2. データセットを作成 / Detectorの有効化

    続いて、データセットを作成します。ここで設定するのは、2つの項目です。
    ① 分析対象のデータソース
    ② 分析対象のフィールド

    まず始めに、「Add a dataset」からデータセット作成画面を開きます。

    f:id:yktm31:20210923173346p:plain:w700

    データセット作成画面は、以下のようになっています。

    f:id:yktm31:20211115000438p:plain:w700 f:id:yktm31:20211128111651p:plain:w700 f:id:yktm31:20211115000528p:plain:w700

    設定が必要な項目は、
    ①データセットの名前
    ②分析対象データソースの指定
    ③分析対象データソースのフォーマット設定
    ④認証情報
    です。

    ここでは、Amazon S3上のCSVファイルを分析対象データソースとしています。

    また、分析のモードが2つ選択できます。 モードの違いによる、コストのかかり方に違いはありません。

    モード 説明 用途
    Backtest 指定したデータを学習用と検証用に分割して検証を行う。
    古い70%が学習に利用され、最新の残り30%をバックテストで利用(※interval x 285 のデータが必要になる。)
    検証
    Continuous 新しく取り込まれるデータを利用し、推論精度を向上させていく。 運用

    続いて、分析対象のフィールドを設定します。

    f:id:yktm31:20211114235934p:plain:w700

    「Measure」で指定するのは、異常を検知する対象のフィールドです。 「Demensions」で指定するのは、Measureをどのフィールドでカテゴライズするか、というものです。 例えば、プラットフォーム毎の閲覧数を見たい場合、「Measure」に「views(閲覧数)」を、「Demensions」に「platform(利用デバイス/利用媒体 )」を指定します。

    最後にTimestamp情報がどういった形式で表されているかを指定します。

    「Next」を押すと、設定情報確認画面が出てきます。

    「Save and active」を押すと、データセットが作成され、分析が始まります。

    f:id:yktm31:20210923175757p:plain:w700

    3. 分析結果の確認

    「View annomalies」から異常を確認してみましょう。

    f:id:yktm31:20210923180648p:plain:w700

    発生した異常は、以下のようにリストで表示されます。

    このリストは、どのメトリクスに、何時に異常が発生したかのリストです。 「Severity score」でソートすれば、異常度の大きさで並び替えできます す。「Time detected」でソートすれば、異常が発生した時間でソートできます。

    f:id:yktm31:20211128021445p:plain:w700

    そのうちの一つを開くと、以下のような画面になります。

    f:id:yktm31:20211128015108p:plain:w700

    Anomaly overviewを見ると、2021/09/04 00:00(GMT時間)に発生した異常の詳細であることがわかります。

    続いて、Dimension valuesを確認します。 Dimension valuesは、検知した異常に対し、どのDimensionの影響が大きかを表しています。

    ここでは、以下のような影響度になっています。

    Dimension Dimensionの値 影響度
    Marketplace De(ドイツ) 71%
    Marketplace Uk(イギリス) 28%
    Platform Mobile_web 100%

    ここから、Marketplaceが「De(ドイツ)」Platformが「Mobile_web」のrevenue(収益)に、より大きな異常が出ていることが読み取れます。

    Metric graphsには、それぞれの異常箇所がグラフとして表示されます。
    まず、9/3の21:00 ~ 9/4の1:00の間(赤枠部分)で異常が検知されていることが確認できます。 「De(ドイツ)のMobile_web」と、「Uk(イギリス)のMobile_web」を比較すると、確かに、「De(ドイツ)のMobile_web」の収益が0になっており、異常度が大きいと言えそうです。

    もし、異常と検知された部分が、予想の範囲内である場合、「Is this relevant?」(緑枠部分)でラベル付けしてアルゴリズムにフィードバックすることで、異常検知の精度を向上させることが可能です。

    4. アラート設定

    最後に、アラートを設定しましょう。 設定項目は、
    ①アラート名
    閾値(threshold)
    ③アラートチャンネル
    です。

    f:id:yktm31:20210923181010p:plain:w700

    アラートチャンネルは、Amazon SNSの他に、AWS Lambda、Skack、Webhooksなどが選択できます。

    使用感

    以上で、Lookout for Metricsを使った分析は完了です。使用感として、使いやすい点と注意点をまとめてみます。

    使いやすい点

  • Lookout for Metrics が、複数のアルゴリズムから適切なものを自動で選択してくれる
  • アルゴリズムを意識することなく使えるので、機械学習の知識・経験がない人にとっても使いやすいと思いました。
  • 異常のデータがなくても異常を検出できる
  • 教師なし学習という方法で異常データなしで分析を開始でき、データの準備が楽なところは嬉しいですね。
  • 誤判定を、アルゴリズムに簡単にフィードバックできる
  • 検知した異常を簡単に再ラベリングでき、アルゴリズムを再学習できるところは、運用しながら精度を向上できる、嬉しい部分だと感じました。

    注意が必要な点

  • 全体の傾向が見れない
  • 例えば、過去1ヶ月に起きた異常を、まとめて一つのグラフに表示する、という使い方はできないようです。今回のデータでは、異常発生から遡って約72時間分のデータのみ見ることができました。
  • 複数のMesureの異常を同時に見ることができない
  • 複数の分析軸(=Dimension)から異常を分析できることに対し、複数の分析対象(=Mesure)を同時に比較することはできないようです。
  • 設定の変更が柔軟にできない
  • 分析の時間単位(Interval)や、Measure/Dimensionを後から変更できない点は、注意が必要だと思いました。設定を変更するためには、新たに分析器を1から作成する必要があるため、とにかくランダムにパラメータを変えるという使い方は避けた方がよいと思いました。

    コスト

    ここまで、分析が簡単にできることは分かりましたが、実際使うとなると、利用コストが気になるところかと思います。

    Lookout for Metricsは従量課金制で、メトリクスと呼ばれる単位で課金が発生します。

    メトリクスは、Measureの数 × Demensionsがもつユニークな値の数から算出されます。 例えば、1時間あたりのオンライン注文数、1日あたりのウェブサイト訪問数などが例として挙げられています。

    したがって、ユニークな値を大量に持つ可能性があるフィールドを「Demensions」に設定すると、メトリクスが大きくなり料金が肥大化することに繋がります。 この点は注意が必要です。



    ここで、今回実施した分析を例にコスト試算してみたいと思います。

    まず、「Measure」には、views(閲覧数)とrevenues(収益)を指定したので、Measureの数は2です。

    続いて、「Demensions」には、platform(利用デバイス)とmarketplace(利用国)を指定しました。 それぞれのユニーク値は以下のようになっています。

    カラム名 ユニーク値 カウント
    platform pc_web, mobile_web, mobile_app 3
    marketplace us, uk, de, fr, es, it, jp 7

    上記より、Demensionsには3 x 7 = 21個のユニーク値が存在します。

    つまり、Measureの数 × Demensionsがもつユニークな値の数という式に当てはめると、 2 Measure × 21 Demensions = 42メトリクス となります。

    以下の料金表に基づき、最初の1000メトリクスでは 42 * 0.75USD = 31.5USD(約3500円) が1ヶ月ごとに課金される計算になります。

    f:id:yktm31:20211001072831p:plain:w700
    (出典: 料金 - Amazon Lookout for Metrics | AWS)

    請求ダッシュボードを見ても、計算通りの課金が発生していました。

    メトリクスごとの課金となるため、BacktestモードとContinuousモードでの課金体系に差分はありません。 1ヶ月動かし続けても、1時間だけ動かしても、料金は変わらない点は注意が必要です。
    また、検出された異常の保持、閲覧による課金は発生しません。 他方、Amazon SNS によるカスタムアラートや AWS Lambda を利用したカスタムアクションには別途課金が発生します。

    コスト試算には、AWS公式Githubで提供されているJupyter Notebookを利用できます。

    さいごに

    以上で、Lookout for Metricsを使った分析は完了です。

    時系列データの異常を検知したいけど、難しいことはしたくない、というニーズに応えるサービスだと思いました。 機械学習を利用した時系列分析が、ここまで簡単に利用できるのは、Lookout for Metricsの魅力ですね。

    今回は深く触れませんでしたが、データ連携の容易さやアラートのカスタマイズ性も、実運用するにあたり重要になってくるポイントかと思います。

    Acroquest Technologyでは、キャリア採用を行っています。
    • ディープラーニング等を使った自然言語/画像/音声/動画解析の研究開発
    • Elasticsearch等を使ったデータ収集/分析/可視化
    • マイクロサービス、DevOps、最新のOSSを利用する開発プロジェクト
    • 書籍・雑誌等の執筆や、社内外での技術の発信・共有によるエンジニアとしての成長
      少しでも上記に興味を持たれた方は、是非以下のページをご覧ください。 www.wantedly.com

    KarateのDockerイメージを使用して、UIテストを自動化してみた


    こんにちは、DevOpsチームの@buzz_tkcです。
    最近、数分のあいだに複数の筋トレとインターバルを繰り返し、高い脂肪燃焼効果が得られると注目を集めている、「HIIT(High-intensity interval training)」トレーニングにハマっています。

    数分のトレーニングですが、かなり効果があるので、運動不足でお困りの方に、おススメです。


    さて、今回もKarateに関する記事です。Karateに関する記事も、増えてきました。


    テスト自動化も、準備ができた後は良いのですが、テスト自動化の環境を作ること自体、なんだかんだいって手間がかかりますよね。
    Karateでは、Dockerコンテナの形式でUIテストを実行できる環境が提供されているようなので、今回はそれを利用して、Webアプリのテストの自動化を行ってみたいと思います!


    f:id:buzz_tkc:20211002192627p:plain

    Karateとは?

    Karateは、REST-API/GraphQL/WebSocket/負荷テスト/E2Eテストなどに対する統合テスト自動化フレームワークです。
    Gherkin形式の自然言語に近い内容でテストをわかりやすく作成することができます。


    こちらの@takanorigさんのQiita記事に詳しく書いてあります。
    qiita.com


    個人的に感じているメリットとしては、

    • シナリオベースのテストが簡単にかける
    • 学習コストが低い
    • REST-API、GraphQL、WebSocketや、負荷テスト、UIテストと幅広く対応できる

    といったところです。

    Karate+Dockerを利用したUIテスト

    テストシナリオの準備

    今回は、KarateのGitHubで公開されているUIテストのサンプルをコンテナ上から実行します。

    構成は以下になります。google.featureが、実行するシナリオです。

    .
    ├── pom.xml
    ├── src
    │   └── test
    │       └── java
    │           ├── logback-test.xml
    │           └── web
    │               ├── GoogleRunner.java
    │               └── ★google.feature

    karate-chrome コンテナの起動

    まず初めにカレントディレクトリを、コンテナ上の/src配下にマウントする形で、Karateコンテナを起動します。

    docker run -itd --name karate-chrome -p 9222:9222 --rm -p 5900:5900 -e KARATE_SOCAT_START=true --cap-add=SYS_ADMIN -v "$PWD":/src ptrthomas/karate-chrome


    起動したコンテナの特徴は、以下になります。

    • VNC(Virtual Network Computing)サーバーを起動し、 5900ポートを公開し、Chromeにアクセスできる。
    • Chrome DevToolsには、9222ポートでアクセスできる。
    • テストの録画記録は、 /tmp/karate.mp4に保存される。
    • テスト終了後、テストの録画記録が埋め込まれたHTMLレポートが確認できる。


    それでは、VNCにて起動したChromeにアクセスしてみます。

    open vnc://localhost:5900


    Windowが立ち上がり、パスワードを求められるので、「karate」と入力し、サインインします。
    f:id:buzz_tkc:20210924005824p:plain


    すると、コンテナ起動したChromeブラウザが、確認できます。
    f:id:buzz_tkc:20210929003057p:plain


    今回は使用しませんが、localhost:9222にアクセスすることで、VNCにて起動したChromeブラウザのDeveloper Toolを確認することができます。
    f:id:buzz_tkc:20210924010918p:plain


    テストシナリオの実行

    Karateコンテナの起動に成功したので、google.featureをコンテナ上から、実行してみたいと思います。
    ただ、そのままのソースコードでは、デフォルトのPC上にある、Chromeドライバーを使用して起動してしまいます。(Windowsで言うと、C:\Program Files\Google\Chrome\Application\chrome.exe)


    今回は、コンテナ起動したChrome上で動くようにするため、google.featureのBackground(シナリオが実行前に呼び出される前処理)に、デフォルトのChromeドライバを呼び出さないよう、start:falseを追加してあげます。
    その他に、ログ出力、UIテスト実行をブラウザで録画するための設定も追加しておきましょう。

    Background:
       * configure driver = { type: 'chrome', start: false, showDriverLog: true, beforeStart: 'supervisorctl start ffmpeg', afterStop: 'supervisorctl stop ffmpeg', videoFile: '/tmp/karate.mp4'}
    


    google.featureシナリオの内容自体は、GitHubにアクセスして、ログインの失敗を行った後、Googleのトップページから、"karate dsl"と検索し、GitHubのKarateのレポジトリにアクセスするという、シンプルな内容になっています。

    Feature: web-browser automation
    
    Background:
       * configure driver = { type: 'chrome', start: false, showDriverLog: true, beforeStart: 'supervisorctl start ffmpeg', afterStop: 'supervisorctl stop ffmpeg', videoFile: '/tmp/karate.mp4'}
    
    
    Scenario: try to login to github
        and then do a google search
    
      Given driver 'https://github.com/login'
        And input('#login_field', 'dummy')
        And input('#password', 'world')
      When submit().click("input[name=commit]")
      Then match html('.flash-error') contains 'Incorrect username or password.'
      
      Given driver 'https://google.com'
        And input("input[name=q]", 'karate dsl')
      When submit().click("input[name=btnI]")
      Then waitForUrl('https://github.com/karatelabs/karate')
    


    これで設定は完了です。
    それでは、Karateコンテナからgoogle.featureを実行してみましょう。

    docker exec -it -w /src karate-chrome mvn clean test -Dtest=web.GoogleRunner


    VNCにて起動したChrome上で、UIテストが動き始めました!
    f:id:buzz_tkc:20211003102519g:plain

    テスト実行結果の確認

    出力されたレポートを確認してみましょう。
    target/karate-reports/src.demo.web.google.htmlを開きます。
    UIテストの動画付きのレポートが確認できます。
    エビデンスとして、テストのキャプチャを取る必要もなくなるので、これはとても嬉しいですね。
    f:id:buzz_tkc:20211003122127g:plain

    Chromeヘッドレスモードでの追加検証

    今までは、ヘッドフルモード(GUIがあるブラウザ)での動作確認を行いましたが、追加で、ヘッドレスモード(GUIがないブラウザ)での検証を行いたいと思います。ヘッドレスモードでの起動ができれば、CI/CD パイプラインの自動テストに組み込むことができます。

    設定自体は簡単で、Backgroundにheadlessオプションを指定してheadless: true 、起動をするだけ。

    configure driver = { type: 'chrome',start:false, headless: true }
    

    ・・・・のはずですが、ヘッドフルモードで実行した場合と、挙動は変わらず、VNC上で起動されたブラウザで、テストが実行され、テストの録画も実行されていました。

    実際にパイプライン(GitLab CI)に組み込んでみたところ、自動テストが実行できたので、headlessオプションの値に関係なく、CI/CDパイプラインにも組み込んで、自動化できそうです。

    まとめ

    KarateのDockerイメージを使って、コンテナ起動したChrome、Karateで、簡単にUIテストを実施することができました。
    コンテナを使うメリットとして、自分以外の他の開発メンバの環境でも同様に動かせる、ということがあると思います。

    先日、Java 17がリリースされましたが、テスト自動化を行う上で環境のバージョンの統一は重要ですよね。
    これで、バージョンの不整合で、自分以外の他の人の環境で動かない、、、なんてことも無くなりそうです。
    また、コンテナ実行とすることで、パイプラインにも簡単に組み込めたので、今後パイプライン構築の幅も広がりそうです。

    それでは。

    顧客のビジネスをインフラから加速するエンジニア募集! - Acroquest Technology株式会社のインフラエンジニアの求人 - Wantedlywww.wantedly.com