IBM Cloud Functions 内で深層学習を活用する

Apache OpenWhisk をベースとする IBM Cloud Functions は、サーバーレス・アプリケーションの構築とデプロイを容易にする、サービスとしての関数 (FaaS) プラットフォームです。

このチュートリアルでは、IBM Cloud Functions を利用して、Cloud Object Storage バケットのコンテンツをモニタリングし、ユーザーまたは自動プロセスによってバケットにアップロードされた画像の内容を分析するサーバーレス・アプリケーションを構築します。説明のために、Model Asset eXchange から入手できる深層学習マイクロサービスによる分析を行い、その分析結果を JSON ファイルとして同じバケットに保管します。

チュートリアルのシナリオ

ここで説明する手法は、IBM Watson® で提供されているようなホスト型コグニティブ・サービスを利用する場合にも簡単に適用できます。また、結果を保管する場所として Cloudant® などの NoSQL データストアや、リレーショナル・データベースも使用できます。

学習の目的

この入門チュートリアルの手順を通して、Cloud Functions を利用して Cloud Object Storage バケットをモニタリングし、変更 (オブジェクトの追加、更新、削除) を検出する方法と、Model Asset eXchange で提供されている深層学習マイクロサービスを使用してオブジェクトをほぼリアルタイムで分析する方法を学びます。

チュートリアルが完了した時点で、IBM Cloud CLI を使用して Cloud Object Storage バケットの変更モニタリングをセットアップする方法、さらにほぼリアルタイムの深層学習マイクロサービスを利用して、アップロードされたオブジェクト (画像、音声、動画、テキスト・ファイルなど) から情報を引き出す方法を把握できているはずです。

前提条件

このチュートリアルに従うには、以下の前提条件を満たす必要があります。

  • IBM Cloud アカウント
  • Cloud Object Storage インスタンスに対する管理者アクセス権限 (このチュートリアルに従うには、ライトまたはスタンダード・プランのインスタンスを使用できます)。チュートリアルの手順では、cloud-object-storage-lite という名前のインスタンスを参照します。必要に応じて、この名前を実際の Cloud Object Storage インスタンス名で置き換えてください。
  • バージョン 0.19 以降の IBM Cloud CLI がインストールされていること。インストールされているバージョンを確認する方法とアップグレードする方法については、こちらの資料を参照してください。
  • バージョン 1.0.34 以降の IBM Cloud Functions プラグインがインストールされていること。

Cloud Functions の使用経験がない場合は、ざっと Cloud Functions の概念を確認してから手順を開始してください。

GitHub からチュートリアルの成果物をダウンロードする

ローカル・マシン上に GitHub クライアントがインストール済みの場合、以下のコマンドを使用してチュートリアルのリポジトリーを複製します。

git clone https://github.com/IBM/use-deep-learning-in-ibm-cloud-functions
cd use-deep-learning-in-ibm-cloud-functions

GitHub クライアントがインストールされていない場合は、この ZIP ファイルをダウンロードして解凍してください。

所要時間

このチュートリアルの所要時間は約 30 分です。

手順

サーバーレス・アプリケーションを実装するには、3 つの Cloud Function エンティティーを作成する必要があります。

  • Cloud Object Storage トリガー。画像が Cloud Object Storage バケットにアップロードされるたびに起動します。
  • アクション。画像を分析して、その分析結果を同じバケットに保管します。
  • ルール。トリガーとアクションを関連付けます。

トリガー、ルール、アクションの概要

まず、Cloud Object Storage インスタンス内にバケットを作成します。

リージョン・バケットを作成する

これから作成するサーバーレス・アプリケーションは、複数の Cloud Object Storage トリガーを使用します。これらのトリガーは us-eastus-south、または eu-gb region リージョン内のリージョン・バケットをサポートしますが、リージョン間のバケット、単一サイトのバケット、他のリージョンのリージョン・バケットはサポートしません。

  1. Web ブラウザー内で IBM Cloud リソース・リストを開き、使用しているストレージ・サービスを見つけます。
  2. Cloud Object Storage インスタンス cloud-object-storage-lite を選択します。
  3. サーバーレス・アプリケーションがバケットにアクセスするために使用するサービス資格情報を作成します (書き込み アクセス権限を割り当てます)。 サービス資格情報を作成する画面のスクリーンショット

  4. us-eastus-south、または eu-gb. 内にリージョン・バケットを作成します。

    リージョン・バケットを作成する画面のスクリーンショット

このチュートリアル全体を通して、手順では vacation-pictures という名前のバケットを参照します。パブリック・クラウド内のバケットはグローバル名前空間を共有します。つまり、2 つのユーザーが同じ名前のバケットを作成することはできません。したがって、これとは別のバケット名を選択して、そのバケット名を使用してチュートリアルの手順に従う必要があります。

IBM Cloud CLI を構成する

  1. ターミナル・ウィンドウを開いて IBM Cloud CLI を起動し、IBM ID を使用してログインします。

    ibmcloud login

  2. IBM Cloud CLI がターゲットとするリージョン、リソース・グループ、Cloud Foundry API エンドポイントを表示します。

    ibmcloud target

    以下のような出力が表示されます。

    API endpoint:      https://cloud.ibm.com
    Region:            us-south
    User:              somebody@somewhere.com
    Account:           Somebody's Account (7...g)
    Resource group:    No resource group targeted, use 'ibmcloud target -g RESOURCE_GROUP'
    CF API endpoint:
    Org:
    Space:
    
  3. リストアップされているリージョンが、バケットを作成したリージョンと一致していない場合は、以下のコマンドを実行します。us-south の部分は、使用しているリージョンで置き換えてください。

    ibmcloud target -r us-south

  4. ターゲットとするリソース・グループが設定されていない場合は、以下のコマンドを実行します。

    ibmcloud target -g default

  5. Cloud Foundry API エンドポイントが設定されていない場合は、以下のコマンドを実行します。

    ibmcloud target --cf-api api.ng.bluemix.net

これで、サーバーレス・アプリケーションの作成に取り掛かる準備が整いました。

Cloud Object Storage トリガーを作成する

Cloud Object Storage トリガーは、事前インストール済みの Cloud Functions パッケージです。トリガーを使用すると、バケット内のオブジェクトの変更 (追加、更新、削除) を listen できます。このような変更が発生するたびにトリガーが起動します。

このトリガーを作成するには、その前に、Identity and Access (IAM) 管理の名前空間を作成し、その名前空間に Cloud Object Storage インスタンスに対する 通知マネージャー 役割を割り当てる必要があります。

IAM 管理の名前空間を使用して、関連する Cloud Function エンティティー (トリガーやアクションなど) をグループ化します。例えば、開発用エンティティー、QA 用エンティティー、本番環境用エンティティーをそれぞれ別個の名前空間に保管するといった具合です。

Cloud Functions を利用してサーバーレス・アプリケーションを実装した経験があるとしたら、 Cloud Foundry ベースの名前空間についてご存知のことでしょう。Cloud Foundry ベースの名前空間は同じ目的を果たすものの、Cloud Object Storage バケットのモニタリングを実装するために必要な機能をサポートしていません。

  1. IAM 管理の Cloud Functions 名前空間 analyze_images を作成します。ここに、チュートリアルの成果物を格納します。これとは別の名前にする場合、以降にリストアップするコマンドでは、必ずその名前を指定してください。

    ibmcloud fn namespace create analyze_images --description "identify objects in images"

    名前空間をリストアップするには、ibmcloud fn namespace list を実行します。

  2. IBM Cloud CLI のコンテキストを analyze_images 名前空間に設定します。一度設定すると、新しいすべての Cloud Functions エンティティーはこの名前空間内に作成されます。

    ibmcloud fn property set --namespace analyze_images

    現在の名前空間内にあるエンティティーをリストアップするには、ibmcloud fn list を実行します。

  3. analyze_images 名前空間に通知マネージャー役割を割り当てます。この役割を割り当てると、Cloud Functions が Cloud Object Storage バケットに関する通知を表示、変更、削除できるようになります。source-service-instance-name パラメーターは名前空間 (analyze_images) を識別します。target-service-instance-name パラメーターは、役割を付与する対象の Cloud Object Storage サービス・インスタンス (cloud-object-storage-lite) を識別します。

    ibmcloud iam authorization-policy-create functions cloud-object-storage "Notifications Manager" --source-service-instance-name analyze_images --target-service-instance-name cloud-object-storage-lite
    

    このコマンドが、通知マネージャー役割が見つからないというエラーで失敗した場合、それはインストールされている IBM Cloud CLI または Cloud Functions プラグインが古すぎることを意味します。最新バージョンにアップグレードしてから、もう一度試してください。

前提条件が揃ったので、次は、選択した名前空間と Cloud Object Storage インスタンスを対象とした Cloud Object Storage トリガーを作成します。これらのトリガーがモニタリングするのは、リージョン・バケットの変更だけであることに注意してください。リージョン間バケットと単一サイトのバケットは、現在のところサポートされていません。

  1. bucket_jpg_write_trigger という名前の Cloud Object Storage トリガーを作成します。このトリガーは、Cloud Object Storage バケット vacation-pictures 内に画像 (.jpg 拡張子) が正常に追加されたとき、またはこのバケット内の画像が変更されたときに起動します。

    ibmcloud fn trigger create bucket_jpg_write_trigger --feed /whisk.system/cos/changes --param bucket vacation-pictures --param suffix ".jpg" --param event_types write
    

    上記のコマンドで使用されている 3 つのパラメーターについて確認しましょう。

    • bucket は、このトリガーでモニタリングするバケットを識別します。上記では、vacation-pictures に設定されています。
    • suffix は、オプション・パラメーターです (ここでは使用していませんが、prefix と同様です)。上記では、.jpg に設定されています。このパラメーターはフィルターを定義するために使用します。上記で定義しているフィルターにより、キー名が .jpg で終わるオブジェクトが追加または変更された場合にのみ、トリガーが起動することになります。したがって、動画がアップロードされた場合や、後でわかるように分析結果がこのバケット内に保管された場合には、このトリガーは起動しません。注: 複数のサフィックス (例えば、.jpg.png) を使用してフィルタリングする場合は、サフィックスごとに 1 つのトリガーを作成する必要があります (bucket_jpg_write_trigger および bucket_png_write_trigger)。プレフィックスについても同様です。
    • event_types もオプション・パラメーターで、トリガーを起動する変更のタイプを識別するために使用します。上記では、write に設定されています。このパラメーターを指定しない場合、すべての変更によってトリガーが起動します。

      このチュートリアルでは、画像が削除された場合には、このトリガーが起動されないようにする必要があります。存在しない画像から分析情報を引き出すことはできないためです。

    サポートされているトリガーのパラメーターと値の完全なリストについては、このドキュメントを参照してください。

    現在の名前空間内にあるトリガーのリストを表示するには、ibmcloud fn trigger list を実行します。

  2. トリガーのプロパティーを確認します。

    ibmcloud fn trigger get bucket_jpg_write_trigger

次は、画像を処理するコードを含む Cloud Function アクションを定義します。

アクションを作成する

アクションとは、Python や Node.js などのサポート対象のプログラミング言語で作成されたコードを指します。このチュートリアルで作成するアクションは、画像内のオブジェクトを検出し、その結果を JSON ファイルに含めて、画像が配置されている Cloud Object Storage バケット内に保管します。

このアクションには、以下の入力パラメーターが必要です。

  • モニタリング対象のバケットに追加された画像の名前、またはこのバケット内で変更された画像の名前
  • バケット名
  • アクションのソース・コードでバケットから画像をダウンロードする際、または分析結果を保管する際に使用できる、Cloud Object Storage インスタンスの接続情報

画像の名前とバケット名はトリガーのペイロード内にありますが、接続情報はありません。したがって、パッケージを作成し、そのパッケージに Cloud Object Storage インスタンスをバインドして (これにより、パッケージ内のアクションで接続情報を使用できるようになります)、分析アクションをパッケージ内に保管する必要があります。

  1. manage_pictures という名前のパッケージを作成します。

    ibmcloud fn package create manage_pictures

    現在の名前空間内にあるパッケージのリストを表示するには、ibmcloud fn package list を実行します。

  2. パッケージのプロパティーを表示します。

    ibmcloud fn package get manage_pictures

    このように、リソースのバインディングは存在しません。

     ...
     {
      "namespace": "...",
      "name": "manage_pictures",
      "version": "0.0.1",
      "publish": false,
      "binding": {}
     }
    
  3. cloud-object-storage-lite Cloud Object Storage インスタンスを manage_pictures パッケージにバインドします。

    ibmcloud fn service bind cloud-object-storage manage_pictures --instance cloud-object-storage-lite

    このインスタンスのサービス資格情報が定義されていなければ、この処理は失敗します。複数の資格情報が定義されている場合は、--keyname <資格情報名> パラメーターを使用して必要な資格情報を指定できます。

  4. もう一度パッケージのプロパティーを表示します。

    ibmcloud fn package get manage_pictures

    今回の出力には、パラメーター __bx_creds が定義されていることが示されているはずです。これで、このパッケージ内 のアクションが、前のステップでこのパッケージにバインドした cloud-object-storage-lite インスタンスに接続する際に、この接続情報にアクセスして使用できるようになりました。

    {
     "namespace": "...",
     "name": "manage_pictures",
     "version": "0.0.1",
     "publish": false,
     "parameters": [
         {
             "key": "__bx_creds",
             "value": {
                 "cloud-object-storage": {
                     "apikey": "...",
                     "cos_hmac_keys": {
                         "access_key_id": "...",
                         "secret_access_key": "..."
                     },
                     "credentials": "...",
                     "endpoints": "https://cos-service.bluemix.net/endpoints",
                     "instance": "cloud-object-storage-lite",
                     ...
                 }
             }
         }],
     ...
    }
    

    関連するアクションのソース・コードはこの後すぐ、アクションを作成してから確認できます。

  5. manage_pictures パッケージ内に、提供されている actions/python/detect_objects.py Python ソース・コードを使用して bucket_write_action を作成します。kind パラメーターは、Cloud Functions がコードを実行する際に使用するランタイム環境を定義します。

    ibmcloud fn action update manage_pictures/bucket_write_action actions/python/detect_objects.py --kind python:3.7

    現在の名前空間内にあるアクションのリストを表示するには、ibmcloud fn action list を実行します。

  6. アクションのプロパティーを表示して、ランタイム設定を確認します。

    ibmcloud fn action get manage_pictures/bucket_write_action

    Cloud Object Storage 接続情報がパラメーターとしてリストアップされているはずです。

  7. actions/python/ ディレクトリー内にある、アクションの detect_objects.py ソース・コードの内容を確認します。

    GitHub リポジトリーの actions/js/ 内に、このアクションおよび後述のアクションの Node.js 実装も格納されています。

    Python で実装されているこのアクションは、Cloud Object Storage SDK を使用してオブジェクトの読み取りと書き込みを行います。

    • 画像は指定の Cloud Object Storage バケットからメモリーにロードされます。
    • クラウドでホストされている Object Detector マイクロサービスに画像が送信されて、画像内で描写されているオブジェクトのタイプが識別されます。

      説明のために、このチュートリアルのアプリケーションは、Center for Open Source Data and AI Technologies がホストしている評価マイクロサービス・インスタンスを利用するように事前構成されています。本番目的では決して評価インスタンスを使用しないでください。定期的にマイクロサービスを利用してデータを分析することを予定している場合、例えば Red Hat® OpenShift® コンテナー・プラットフォーム上に独自のコピーをデプロイしてください。その手順については、チュートリアル「Deploy deep learning models on Red Hat OpenShift」で確認できます。

    • マイクロサービスから返された結果は、画像が置かれているバケット内に JSON 形式で保存されます。
    • アクションから返されるのは、バケット名、オブジェクトのキー、アノテーションのタイプ、オブジェクトのアノテーション・キーです。

    定義したトリガーは JPG でエンコードされた画像がアップロードされた場合にのみ起動しますが、このアクションでは任意のエンコード方式の画像を処理できます。このことから、アクションの名前は bucket_jpg_write_action ではなく bucket_write_action としています。

ここまでのところ、bucket_jpg_write_trigger トリガーと manage_pictures/bucket_write_action アクションを作成しましたが、トリガーとアクションはまだ関連付けられていません。そのため、トリガーが起動しても何の処理も行われません。

ルールを作成する

ルールによって、トリガーをアクションまたはシーケンス (基本的には一連のアクション) に関連付けます。これにより、トリガーが起動すると、トリガーに関連付けられたアクション (またはシーケンス) が実行されて、トリガーのペイロードがパラメーターとしてアクションに渡されます。

  1. bucket_jpg_write_rule という名前のルールを作成します。このルールで、bucket_jpg_write_triggermanage_pictures/bucket_write_action に関連付けます。

    ibmcloud fn rule create bucket_jpg_write_rule bucket_jpg_write_trigger manage_pictures/bucket_write_action

    現在の名前空間内にあるルールのリストを表示するには、ibmcloud fn rule list を実行します。

  2. ルールのプロパティーを調べて、ルールがアクティブであること、正常にトリガーとアクションを関連付けていることを確認します。

    ibmcloud fn rule get bucket_jpg_write_rule

ルールが作成されました。これで、新しい JPG 画像がバケットにアップロードされるたびにアクションが実行されます。

  1. サーバーレス・アプリケーションを実装する Cloud Function エンティティーを確認します。

    ibmcloud fn list

    以下のような出力になっていれば、アプリケーションのテストを開始できます。

    packages
    /.../manage_pictures                  private
    actions
    /.../manage_pictures/bucket_write_action private python:3.7
    triggers
    /.../bucket_jpg_write_trigger         private
    rules
    /.../bucket_jpg_write_rule            private              active
    

サーバーレス・アプリケーションをテストする

GUI を使用してアプリケーションをテストするには、以下の手順に従います。

  1. JPG 画像 (例: greenland.jpg) を vacation-pictures バケットにアップロードします。数秒後に、annotations/greenland.json という名前の新しいオブジェクトがバケット内に現れるはずです。

    画像をアップロードした後のバケットの内容を示す画面のスクリーンショット

  2. PNG 画像 (または拡張子が .jpg 以外の任意のファイル) をバケットにアップロードします。バケット内に新しい JSON ファイルは現れません。bucket_jpg_write_trigger が起動しなかったためです。

Cloud Function エンティティーの実行をモニタリングするには、以下の手順に従います。

  1. ブラウザー内で Cloud Functions ダッシュボードを開きます。
  2. Monitor (モニタリング)」タブを選択します。
  3. 右側にあるドロップダウンから、「analyze_images」名前空間を選択します。

    Cloud Function の実行をモニタリングする画面のスクリーンショット

  4. manage_pictures/bucket_write_action のアクティビティー・ログ出力を開きます。それには、アクティべーション ID (上述のスクリーンショットでは 25...64) をクリックします。ログには生成されたすべての出力がレスポンスと併せて記録されて、以下のような内容になっています。

    "response":
       {
         "result":
           {
             "annotation_key":"annotations/greenland.json",
             "annotation_type":"max-object-detector",
             "bucket":"vacation-pictures",
             "key":"greenland.jpg"
           },
         "status":"success",
         "success":true
       }
    

サーバーレス・アプリケーションを拡張する

アクション・コードを (Cloud Object Storage 内に保管されているあらゆる種類のメディアに対して) 別のタイプの分析を行うように変更するだけで、簡単にサーバーレス・アプリケーションを拡張またはカスタマイズできます。このチュートリアルの締めくくりとして、画像キャプションを生成するようにアクション・コードを変更し、画像がバケットから削除されると、その画像に対して生成された JSON ファイルを削除するようにアプリケーションを拡張します。

別のタイプの分析を実行する

前に作成した (actions/python/detect_objects.py 内に実装されている) bucket_write_action は、画像内のオブジェクトを検出する、Model Asset eXchange のマイクロサービスを利用しています。別のタイプの分析 (例: 画像キャプションの生成) を行うには、目的のタスクを実行する別のクラウド・サービスを呼び出すようにアクションのソース・コードを変更します。

このチュートリアルのリポジトリーに、サンプル・アクションの実装として 画像キャプション・ジェネレーター マイクロサービスが格納されています。この実装と actions/python/detect_objects.py との主な違いは、呼び出すサービス URL とペイロードにあります。

  1. 画像キャプションを生成するように bucket_write_action を更新します。

    ibmcloud fn action update manage_pictures/bucket_write_action actions/python/generate_image_caption.py --kind python:3.7

  2. JPG 画像を manage_pictures バケットにアップロードします。これによって生成された JSON ファイルに、画像の内容を説明するテキストが含まれていることを確認します。

分析結果ファイルを自動的に削除する

バケットから画像が削除されるたびに、その画像に対して作成された JSON ファイルを自動的に削除するようにサーバーレス・アプリケーションを拡張するのは簡単です。

  • バケットから JPG ファイルが削除されると起動するトリガーを作成します。
  • 削除された画像に関連付けられている JSON ファイルを削除するアクションを作成します。
  • 削除トリガーと削除アクションを関連付けるルールを作成します。

以下の手順に従ってください。

  1. 削除トリガーを作成します。event_types パラメーターが delete に設定されていることに注目してください。

    ibmcloud fn trigger create bucket_jpg_delete_trigger --feed /whisk.system/cos/changes --param bucket vacation-pictures --param suffix ".jpg" --param event_types delete
    
  2. 削除アクションを作成します。アクションのサンプル・ソース・コードは、actions/python/bucket_delete_action.py 内にあります。

    ibmcloud fn action update manage_pictures/bucket_delete_action actions/python/delete_annotation.py --kind python:3.7

  3. トリガーとアクションを関連付けるルールを作成します。

    ibmcloud fn rule create bucket_jpg_delete_rule bucket_jpg_delete_trigger manage_pictures/bucket_delete_action

  4. 新しく作成された Cloud Function エンティティーを確認します。

    ibmcloud fn list

    以下のような出力が表示されます。

    packages
    /.../manage_pictures                  private
    actions
    /.../manage_pictures/bucket_delete_action private python:3.7
    /.../manage_pictures/bucket_write_action private python:3.7
    triggers
    /.../bucket_jpg_delete_trigger        private
    /.../bucket_jpg_write_trigger         private
    rules
    /.../bucket_jpg_delete_rule           private              active
    /.../bucket_jpg_write_rule            private              active
    

更新後のアプリケーションをテストするには、前にアップロードした JPG 画像を vacation-pictures バケットから削除します。対応する JSON ファイルが自動的に削除されるはずです。

他のオブジェクト・タイプもサポートする

このチュートリアルで作成した Cloud Function トリガーは、JPG でエンコードされた画像がアップロードされた場合にのみ起動します。他の画像エンコーディング (PNG など) もサポートするには、チュートリアルの GitHub リポジトリーに格納されている create_serverless_app.* シェル・スクリプトおよびバッチ・スクリプトに示されているように、トリガーとルールを追加します。

まとめ

このチュートリアルでは、Cloud Object Storage バケットの内容をモニタリングし、Model Asset eXchange の深層学習マイクロサービスを使用して画像の内容を分析するサーバーレス・アプリケーションを作成する方法を学びました。

Model Asset eXchange の詳細を学ぶには、「ラーニング・パス: Model Asset Exchange 入門」を参照してください。

IBM Cloud Functions とその一般的な使用ケースについて詳しくは、IBM Cloud Functions ドキュメントのセクション「Cloud Functions はどのような目的に使用できますか?」を参照してください。