現在地

まずやってみる機械学習 ~AWS SAGEMAKER/REKOGNITIONとVUEで作る画像判定WEBアプリケーション(後編)

WEBアプリケーション開発(設定~コーディング~配置)

前編では機械学習の設定まで行いましたが、後編からは機械学習した結果を利用して画像判定を行うためのWebアプリケーションを開発します。
開発環境にはAWS Cloud9を使用します。

2-1. 設定

Webアプリケーションをコーディングする開発環境であるCloud9、および、コーディングしたファイルを配置するS3の設定を行います。

2-1-1. CLOUD9

開発環境作成

AWZ Cloud9を開き、「Create environment」ボタンを押下します。

「Name」に任意の開発環境の名称を入力し、「Next」ボタンを押下します。

デフォルト設定のまま、「Next」ボタンを押下します。

「Create environment」ボタンを押下すると環境が作成されます。

環境が作成されると以下のような画面が表示されます。必要な設定やライブラリのインストールを行います。

PYTHON設定(PYTHON3を使用するように変更)

AWS Cloud9では現在(2018/8時点)、デフォルトではPython2.7を使用するようになっています。これを、Python3.6を使用するように変更します。変更手順は次のとおりです。

  1. Pythonバージョン確認
  2. Cloud9設定(Python Support)変更
  3. エイリアス変更
  4. pythonのシンボリックリンク管理の変更

順に実施していきます。

1. Pythonのバージョン確認

以下のコマンドを実行し、Pythonのバージョンが2.7であることを確認します。すでにPython 3系であれば以降の手順は不要です。

$ python -V
Python 2.7.14
2. Cloud9設定(Python Support)変更

Cloud9の画面左上のメニューから「Preferences」をクリックし(またはショートカットキー Ctrk+,)、Preferences画面を表示します。Preferences画面にて、「Python Support」の「Python Version:」の設定を、「Python 2」から「Python 3」へ変更します。

3. エイリアス変更

エイリアスが記述されている設定ファイルをviエディタで編集します。

$ vi ~/.bashrc

「alias python=python27」と定義されている行まで移動します。

# .bashrc

export PATH=$PATH:$HOME/.local/bin:$HOME/bin

# load nvm
export NVM_DIR="/home/ec2-user/.nvm"
[ "$BASH_VERSION" ] && npm() {
    # hack: avoid slow npm sanity check in nvm
    if [ "$*" == "config get prefix" ]; then which node | sed "s/bin\/node//";
    else $(which npm) "$@"; fi
}
# [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"  # This loads nvm
rvm_silence_path_mismatch_check_flag=1 # prevent rvm complaints that nvm is first in PATH
unset npm # end hack


# User specific aliases and functions
alias python=python27
(略)

27の2までカーソルを移動し、キーボード「i」キーを押下して編集モードに、そのまま「36」に修正します。

alias python=python36

上述の状態になったら「ESC」キーで編集モードを終了し、「:wq」で保存&viエディタを終了します。

alias設定の変更を反映させます。

$ source ~/.bashrc
function
4. Pythonのシンボリックリンク管理の変更

pythonのシンボリックリンク管理を変更するため、以下のコマンドを実行します。

$ sudo update-alternatives --config python

python2.7とpython3.6のどちらを使用するか尋ねられます。「2」キーを押下します。

There are 2 programs which provide 'python'.

  Selection    Command
-----------------------------------------------
*+ 1           /usr/bin/python2.7
   2           /usr/bin/python3.6

Enter to keep the current selection[+], or type selection number: 2

これでPythonに関する設定は終了です。
引き続き開発に利用するライブラリのインストールを行います。

ライブラリのインストール

以下3つを順次インストールします。

No.ライブラリ名概要
1ChaliceサーバーレスアプリケーションをPythonで記述するためのマイクロフレームワーク
2boto3PythonのAWS用ライブラリ (AWS SDK for Python)
3numpyPythonにて数値計算を効率的に行うライブラリ (本コラムでは配列操作に利用)
Chaliceインストール
$ sudo pip install chalice
boto3インストール
$ sudo pip install boto3
numpyインストール
$ sudo pip install numpy

以上でライブラリのインストールは終了です。
次にフロントエンドのファイルを配置するための設定を行います。

2-1-2. S3

S3ではバケットに対してウェブサイトホスティング用の設定を行うことにより、静的ウェブサイトをホスティングすることが可能なため、今回はこの機能を利用します。
設定方法を以下に示します。

1. S3にてバケットを作成します。

2.「バケットの作成:①名前とリージョン」画面にて以下の情報を入力し、「次へ」ボタンを押下します。

バケット名: リージョン内でユニークな任意のバケット名を入力 [入力例:ita-web-sample]
リージョン: 米国東部 (バージニア北部)

3.「バケットの作成:②オプションの設定」画面、および、「バケットの作成:③アクセス許可の設定」画面、「バケットの作成:④確認」画面では値を変更せず「バケットを作成」ボタンを押下し、バケットの作成を完了させます。

4. 作成したバケットを選択し、「プロパティ」タブから「Static website hosting」を選択します。

5.「このバケットを使用してウェブサイトをホストする」を選択し、「インデックスドキュメント」に「index.html」を入力します。

次節より、このバケットに配置するHTML等を作成します。
作成したHTMLファイルなどを配置すると、「エンドポイント」として表記されているURLからアクセスできるようになります。

2-2. コーディング

本コラム内の全てのコードはGitHubリポジトリから取得可能です。

https://github.com/hirofumi-tagawa/serverless-aws-column01

取得したファイルは一部SageMakerの実行結果に応じた修正が必要です。
AWS Cloud9にて以降の作業は実施します。

2-2-1. バックエンド(ラムダ)

バックエンドの開発にはChaliceを利用します。開発するバックエンドではLambdaをトリガーにしてSageMakerのエンドポイントを呼び出します。ChaliceはAPI Gatewayエンドポイントの作成、Lambdaを使用するアプリケーションのひな型の作成などを行ってくれます。

CHALICEプロジェクトの新規作成

以下のコマンドを実行し、Chaliceの新規プロジェクトを作成します。

$ chalice new-project image-classification
コマンドの実行により作成されたファイル構成
 image-classification/
├── .chalice
│   └── config.json
├── .gitignore
├── app.py
└── requirements.txt

Cloud9の画面上では以下のようになっているかと思います。「app.py」、「requirements.txt」について編集します。

以下に示すコードをコピペするか、GitHubからcloneしたコードをご利用ください。

APP.PY

app.pyでは、フロントエンドからアップロードされた画像に対するSageMakerのエンドポイントの呼び出しと結果の返却、および、AWS Rekognition API、Translate APIを使用した判定結果の返却を行います。
<<YOUR SAGEMAKER ENDPOINT NAME>>」を手順1-2-3で作成したSageMakerのエンドポイントに書き換えます。
なお、このコードではアップロードされた画像に対するチェックやエラー処理を省略しています。実業務の際は仕様に応じた処理が必要となるかと思いますのでご注意ください。

import boto3
import base64
import json
import numpy as np
import logging
import traceback,sys
from chalice import Chalice

app = Chalice(app_name='image-classification')
app.debug = True

logger = logging.getLogger()
logger.setLevel(logging.DEBUG)

@app.route('/classification', methods=['POST'], content_types=['application/octet-stream'], cors=True)
def classification():

    try:
        body_data = app.current_request.raw_body
        body_data = body_data.split(b'base64,')

        image = base64.b64decode(body_data[1])

        sagemaker_client = boto3.client(service_name='sagemaker-runtime', region_name='us-east-1')

        logger.info('Invoke Endpoint')
        res = sagemaker_client.invoke_endpoint(
                        EndpointName='<<YOUR SAGEMAKER ENDPOINT NAME>>',
                        ContentType='application/x-image',
                        Body = image
                    )

        result = res['Body'].read()
        result = json.loads(result)

        # the result will output the probabilities for all classes
        object_categories = ['ak47', 'american-flag', 'backpack', 'baseball-bat', 'baseball-glove', 'basketball-hoop', 'bat', 'bathtub', 'bear', 'beer-mug', 'billiards', 'binoculars', 'birdbath', 'blimp', 'bonsai-101', 'boom-box', 'bowling-ball', 'bowling-pin', 'boxing-glove', 'brain-101', 'breadmaker', 'buddha-101', 'bulldozer', 'butterfly', 'cactus', 'cake', 'calculator', 'camel', 'cannon', 'canoe', 'car-tire', 'cartman', 'cd', 'centipede', 'cereal-box', 'chandelier-101', 'chess-board', 'chimp', 'chopsticks', 'cockroach', 'coffee-mug', 'coffin', 'coin', 'comet', 'computer-keyboard', 'computer-monitor', 'computer-mouse', 'conch', 'cormorant', 'covered-wagon', 'cowboy-hat', 'crab-101', 'desk-globe', 'diamond-ring', 'dice', 'dog', 'dolphin-101', 'doorknob', 'drinking-straw', 'duck', 'dumb-bell', 'eiffel-tower', 'electric-guitar-101', 'elephant-101', 'elk', 'ewer-101', 'eyeglasses', 'fern', 'fighter-jet', 'fire-extinguisher', 'fire-hydrant', 'fire-truck', 'fireworks', 'flashlight', 'floppy-disk', 'football-helmet', 'french-horn', 'fried-egg', 'frisbee', 'frog', 'frying-pan', 'galaxy', 'gas-pump', 'giraffe', 'goat', 'golden-gate-bridge', 'goldfish', 'golf-ball', 'goose', 'gorilla', 'grand-piano-101', 'grapes', 'grasshopper', 'guitar-pick', 'hamburger', 'hammock', 'harmonica', 'harp', 'harpsichord', 'hawksbill-101', 'head-phones', 'helicopter-101', 'hibiscus', 'homer-simpson', 'horse', 'horseshoe-crab', 'hot-air-balloon', 'hot-dog', 'hot-tub', 'hourglass', 'house-fly', 'human-skeleton', 'hummingbird', 'ibis-101', 'ice-cream-cone', 'iguana', 'ipod', 'iris', 'jesus-christ', 'joy-stick', 'kangaroo-101', 'kayak', 'ketch-101', 'killer-whale', 'knife', 'ladder', 'laptop-101', 'lathe', 'leopards-101', 'license-plate', 'lightbulb', 'light-house', 'lightning', 'llama-101', 'mailbox', 'mandolin', 'mars', 'mattress', 'megaphone', 'menorah-101', 'microscope', 'microwave', 'minaret', 'minotaur', 'motorbikes-101', 'mountain-bike', 'mushroom', 'mussels', 'necktie', 'octopus', 'ostrich', 'owl', 'palm-pilot', 'palm-tree', 'paperclip', 'paper-shredder', 'pci-card', 'penguin', 'people', 'pez-dispenser', 'photocopier', 'picnic-table', 'playing-card', 'porcupine', 'pram', 'praying-mantis', 'pyramid', 'raccoon', 'radio-telescope', 'rainbow', 'refrigerator', 'revolver-101', 'rifle', 'rotary-phone', 'roulette-wheel', 'saddle', 'saturn', 'school-bus', 'scorpion-101', 'screwdriver', 'segway', 'self-propelled-lawn-mower', 'sextant', 'sheet-music', 'skateboard', 'skunk', 'skyscraper', 'smokestack', 'snail', 'snake', 'sneaker', 'snowmobile', 'soccer-ball', 'socks', 'soda-can', 'spaghetti', 'speed-boat', 'spider', 'spoon', 'stained-glass', 'starfish-101', 'steering-wheel', 'stirrups', 'sunflower-101', 'superman', 'sushi', 'swan', 'swiss-army-knife', 'sword', 'syringe', 'tambourine', 'teapot', 'teddy-bear', 'teepee', 'telephone-box', 'tennis-ball', 'tennis-court', 'tennis-racket', 'theodolite', 'toaster', 'tomato', 'tombstone', 'top-hat', 'touring-bike', 'tower-pisa', 'traffic-light', 'treadmill', 'triceratops', 'tricycle', 'trilobite-101', 'tripod', 't-shirt', 'tuning-fork', 'tweezer', 'umbrella-101', 'unicorn', 'vcr', 'video-projector', 'washing-machine', 'watch-101', 'waterfall', 'watermelon', 'welding-mask', 'wheelbarrow', 'windmill', 'wine-bottle', 'xylophone', 'yarmulke', 'yo-yo', 'zebra', 'airplanes-101', 'car-side-101', 'faces-easy-101', 'greyhound', 'tennis-shoes', 'toad', 'clutter']

        out = ''
        index = np.argsort(result)
        for i in index[::-1]:
            out += '{} / [probability] {:.2%},'.format(object_categories[i], result[i])
            if result[i] < 0.1:
                break

        return out[:-1]

    except Exception as e:
        tb = sys.exc_info()[2]
        return 'error:{0}'.format(e.with_traceback(tb))

@app.route('/rekognition', methods=['POST'], content_types=['application/octet-stream'], cors=True)
def rekognition():

    try:
        body_data = app.current_request.raw_body
        body_data = body_data.split(b'base64,')

        image = base64.b64decode(body_data[1])

        rekognition_client = boto3.client(service_name='rekognition', region_name='us-east-1')

        logger.info('Invoke Rekognition')
        res = rekognition_client.detect_labels(
                        Image = { 'Bytes': image },
                        MaxLabels=5,
                        MinConfidence=10
                    )

        translate_client = boto3.client(service_name='translate', region_name='us-east-1')
        out = ''
        for label in res['Labels'] :
            trans = translate_client.translate_text(Text=label['Name'], 
                        SourceLanguageCode='en', TargetLanguageCode='ja')

            out += '[en] {} / [ja] {} / [Confidence] {:.2f}%,'.format(
                        label['Name'], trans.get('TranslatedText'), label['Confidence']
                    )

        return out[:-1]

    except Exception as e:
        tb = sys.exc_info()[2]
        return 'error:{0}'.format(e.with_traceback(tb))

コードのポイントは以下のとおりです。

[15-16行目] SageMakerの機械学習結果を利用した推測を行う関数の定義

ここではブラウザからアップロードされた画像をデコードし、SageMakerのエンドポイントの呼び出し、および、その結果の整形と返却を行います。

[24-31行目] SageMakerのエンドポイントの呼び出し

アップロードされた画像データをパラメータとしてSageMakerのエンドポイントを呼び出します。

[52-53行目] AWSサービス(Rekognition, Translate)を利用する関数の定義

アップロードされた画像に対してRekognitionサービスを利用して画像判定を行います。また、その結果に対してTranslateサービスを利用して日本語訳し、返却します。

[61-68行目] Rekognitionサービスによる画像判定を行います
[70-74行目] Translateサービスを利用し判定結果を日本語訳します
REQUIREMENTS.TXT

boto3とnumpyを使用するための定義を「requirements.txt」に記述します。

boto3
numpy
デプロイ

「app.py」、「requirements.txt」の2つのファイルの編集完了後、AWSへデプロイします。
デプロイはChaliceの「deploy」コマンドにより実行しますが、デプロイ処理においてLambdaやIAMなどへの権限が必要となるためCredentialsを設定します。
「AWS_ACCESS_KEY_ID」、「AWS_SECRET_ACCESS_KEY」の値を書き換えて以下のコマンドを実行します。

$ export AWS_DEFAULT_REGION=us-east-1
$ export AWS_ACCESS_KEY_ID=********************
$ export AWS_SECRET_ACCESS_KEY=****************************************

なお、もしChaliceを使った開発を継続的に行われる場合は、chaliceの公式ページにあるとおりconfigへCredentialsを書き込んでもよいかと思います。

「deploy」コマンドを実行します。

$ chalice deploy
Creating deployment package.
Creating IAM role: image-classification-dev
Creating lambda function: image-classification-dev
Creating Rest API
Resources deployed:
  - Lambda ARN: arn:aws:lambda:us-east-1:************:function:image-classification-dev
  - Rest API URL: https://**********.execute-api.us-east-1.amazonaws.com/api/

「Rest API URL」に示されるURLの「**********.execute-api.us-east-1.amazonaws.com」の部分を次節にて使用します。

権限設定

デプロイの結果、ロールが作成されます(本コラムの例では「image-classification-dev」という名称)。
IAMから作成されたロールを選択し、アクセス権限にて「ポリシーの編集」を行います。
「さらにアクセス許可を追加する」をクリックし、「SageMaker」、「Rekognition」、「Translate」の各サービスを利用するため、これらに対するアクセス許可を追加します。
指定する「アクション」や「リソース」は可能な範囲で制限することをお勧めします。ここでは以下のように設定しています。

SageMaker

サービス: SageMaker
アクション: 「読み込み」-「InvokeEndpoint」
リソース: 下図のように指定

Rekognition

サービス: Rekognition
アクション: 「読み込み」-「DetectLabels」
Translate

サービス: Translate
アクション: 「読み込み」-「TranslateText」

各サービスの指定が完了したら「Review policy」ボタンを押下し、「ポリシーの確認」画面にて「Save changes」ボタンを押下します。

2-2-2. フロントエンド(VUE)

フロントエンドはVue.js + axiosで作成しており、CSSにsiimpleを使用しています。いずれもCDNから読み込んでいますのでインストールは不要です。

ファイル構成

フロントエンドは以下の2ファイルで構成されます。

front /
├──index.html
└──main.js
INDEX.HTML

「index.html」はユーザが操作するインターフェースになります。修正箇所はないため、そのままご利用ください。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>ITA</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/siimple@3.1.0/dist/siimple.min.css">
</head>
<body>
  <div id="app">
    <div>
      <div class="siimple-navbar siimple-navbar--extra-large siimple-navbar--primary">
          <div class="siimple-navbar-title">Image Classification Example</div>
          <div class="siimple-navbar-subtitle">ITA</div>
      </div>
      
      <div class="siimple-content siimple-content--extra-large">
          <div class="siimple-grid">
              <div class="siimple-grid-row">
                  <div class="siimple-grid-col siimple-grid-col--6 siimple-grid-col--sm-6">
                      <div class="siimple-h2">Select Image file</div>
                    	<input type="file" id="file" @change="onFileChange">
                      	
                      <div class="siimple-content siimple-content--Medium">
                          <div v-if="image">
                              <img :src="image" /><br>
                              <div class="siimple-btn siimple-btn--primary siimple-btn" v-on:click="uploadImage()">Upload</div>
                          </div>
                      </div>
                  </div>

                  <div class="siimple-grid-col siimple-grid-col--6 siimple-grid-col--sm-6">
                      <div class="siimple-h2">Result - SageMaker</div>
                        <div class="siimple-list">
                            <div class="siimple-list-item" v-for="result in results">{{ result }}</div>
                        </div>
                      <div class="siimple-h2">Result - Rekognition</div>
                        <div class="siimple-list">
                            <div class="siimple-list-item" v-for="result in responses">{{ result }}</div>
                        </div>
                  </div>
              </div>
          </div>
      </div>
    </div>
  </div>

  <script src="https://unpkg.com/vue@2.5.17/dist/vue.min.js"></script>
  <script src="https://unpkg.com/axios@0.18.0/dist/axios.min.js"></script>
  <script src="./main.js"></script>
</body>
</html>

コードの主なポイントは以下のとおりです。

[21行目] 画像ファイルをアップロードするためのボタン定義です。
画像が選択され、changeイベント時にonFileChange関数を実行します。

[24-27行目] 選択された画像ファイルを画面上に表示します。
画像のアップロードを行うuploadImage関数を実行するためのボタン定義です。

[34行目] SageMakerの画像判定結果をリスト表示します。

[38行目] Rekognitionサービスによる画像判定結果をリスト表示します。

[47-49行目] Vueやaxiosなど利用するライブラリの定義です。

JavaScriptフレームワークであるVue.jsを利用しています。Vue.jsのディレクティブは「v-if」や「v-for」など「v-」の接頭辞がついています。
ここではイメージの表示の切り替えやリストの表示などに使用しており、アップロード処理などのメインの処理は次の「main.js」に記述しています。

MAIN.JS

「main.js」には画像のアップロード処理などを記述します。サーバのURLについて2か所修正が必要です(修正内容は同一)。
コード内の「<<YOUR ENDPOINT URL>>」を、手順2-2-1にてデプロイしたエンドポイントのURLに修正します。

let app = new Vue({
  el: '#app',
  data: {
    image: '',
    results_classification: [],
    results_rekognition: [],
  },
  methods: {
    onFileChange: function(e) {
      let files = e.target.files || e.dataTransfer.files;
      if (!files.length)
        return;

      this.showImage(files[0]);
      this.results_classification = [];
      this.results_rekognition = [];
    },
    showImage: function(file) {
      let freader = new FileReader();

      freader.onload = (e) => {
        this.image = e.target.result;
      };
      freader.readAsDataURL(file);
    },
    uploadImage: function(e) {
      let config = {
        headers: {
          'content-type': 'application/octet-stream',
        }
      };

      axios
        .post(
          "https://<<YOUR ENDPOINT URL>>/api/classification",
          this.image,
          config
        )
        .then(response => {
            this.results_classification = response.data.split(",");
        })
        .catch(error => {
            console.log(error);
        });

      axios
        .post(
          "https://<<YOUR ENDPOINT URL>>/api/rekognition",
          this.image,
          config
        )
        .then(response => {
            this.results_rekognition = response.data.split(",");
        })
        .catch(error => {
            console.log(error);
        });
    }
  }
})

「main.js」には3つのメソッドを定義していますが、サーバへ画像をアップロードするメインの処理は「uploadImage」になります。「uploadImage」はファイルアップロード時に呼び出され、axiosを利用してバックエンドに定義した関数をリクエストします。
この際、ヘッダに「'content-type': 'application/octet-stream'」を定義していますが、「content-type」の値はリクエスト先(Chalice)の「content-type」設定と合わせるようにしてください。

デプロイ

「index.html」、「main.js」の2つのファイルの編集完了後、S3へデプロイします。
<<YOUR BUCKET NAME>>」を手順2-1-2にて作成したバケット名に書き換え、ファイルのディレクトリにて以下のコマンドを実行します。

$ aws s3 cp index.html s3://<<YOUR BUCKET NAME>>/ --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers
$ aws s3 cp main.js s3://<<YOUR BUCKET NAME>>/ --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers

2-3. 動作確認

1. S3に配置したウェブサイトを表示すると以下のような画面が表示されます

2. ファイルアップロードボタンから判定したい画像を選択します

任意の画像を選択いただいて問題ありませんが、本コラムではラムダに直接画像ファイルを送信しており、そのためラムダの仕様によりリクエストサイズが最大でも5M以内に収まっている必要があります。さらに選択された画像はエンコードしてアップロードされるため、画像のサイズは4M程度までを目安にしていただければと思います(ちなみに、この制限を超えたサイズの画像をアップロードしたい場合はファイルをS3へ格納するなどの対応が考えられます)。

テスト用の画像データとして指輪とバスタブのファイルを用意しているため、こちらを使用いただいても問題ありません。右クリックしてファイルをローカルにコピーしてご利用ください。

3. 実行結果を確認します

ファイルを選択後、「Upload」ボタンを押下することにより、画像がアップロードされAWSにて判定が行われます。
指輪の画像をアップロードした場合、以下のような結果になりました。

caltech-256のデータセットを利用してSageMakerにて学習した結果:
diamond-ring / 98.13%
AWS Rekognitionの判定:
Diamond / 96.95%
Gemstone / 96.95%
Jewelry / 96.95%
Ornament / 96.95%

SageMakerで学習したcaltech-256のデータセットにはダイアモンドリングの画像も含まれているため、このアップロードしたテスト画像の場合は高い精度が出ています。一方、AWS Rekognitionの結果にはDiamondやGemstoneなど複数の結果が表示されており、何れも高い精度を示しています。

この結果を含め、いくつかの画像をアップロードしてみるとサービスの使い分けについて考えることができるかと思います。一般的な画像の認識であればAWS Rekognitionが実装も容易で使いやすく、一方、SageMakerなどを利用して自身で機械学習を行う場合は独自性のあるものを扱うことが向いており、それぞれのサービスの強みを活かせるように目的に合わせて検討するとよさそうです。

2-4. クリーンアップ

動作確認完了後、エンドポイントを削除します。
SageMakerの「エンドポイント」画面から、作成したエンドポイントを選択します。「アクション」から「削除」を実行します。

まとめ

本コラムではブラウザからアップロードされた画像に対し、SageMakerによる機械学習の結果と、AWSが提供する画像分析サービスのRekognitionを利用した画像判定を行いました。

実業務では独自に収集したデータを用いて機械学習を行いたい場合や、スピード優先で画像識別だけを行いたい場合など様々なシーンがあるかと思います。
これまで見てきたようにAWSにはそうした多様なニーズに対応するために複数の手法が選択肢としてあります。
画像分析を行うRekognitionサービスを利用するだけであればAPIを呼び出すだけですし、独自のデータを利用した機械学習の場合もAWS上にリソースやサンプルが複数用意されており開発が支援されています。

今回はRekognitionサービスについては多数提供される機能のなかで、画像に写っているもののラベル付けを行う機能のみを使用していますが、Rekognitionサービスは他にも顔分析や顔認識、安全でないコンテンツの検出など多数の機能が提供されています。また、SageMakerについても本コラムで使用したサンプルでは画像分類を行うのみでしたが、他のサンプルでは物体検出や機械翻訳を行うものなどもあり、そうしたコードを元に自由に拡張することができます。
他にも、会話型インターフェースを構築するLexや自然言語処理のComprehendなどがあり、それぞれに目的や用途が異なるため現時点では万能なサービスはありませんが、どのサービスも上手く使うと非常に有用なツールになるかと思います。

また、今回はAWSのみを使用しましたが、AWS以外のクラウドサービスにおいても機械学習を活用するための様々なサービスが提供されています。それぞれのサービスごとに特徴も異なるため、特定ベンダーのクラウドサービスのみを利用するのではなく組み合わせて利用することも可能です。

従来はGPUの導入コストや環境構築、学習に時間をとられるなどハードルの高いイメージがあった機械学習ですが、クラウドサービスを利用することで一気にそのハードルが下がっています。
まずはとりあえず試してみてはいかがでしょうか?

最後に

普段AWSを操作されない方にとってはあちこちのサービスを操作することになり煩雑に感じられたかもしれません。ですが、AWSの複数のサービスを組み合わせることにより、GPUやサーバー導入などのイニシャルコストを抑えつつ機械学習を利用したWebアプリケーションが比較的短期間に開発から公開までできると実感いただけたかと思います。

もちろん、今回紹介したアプリケーションや構成そのままでは多数のユーザーが利用し高負荷が発生する本番利用にはパフォーマンスやセキュリティ面などで問題が出ることが想定されます。もしクラウドや機械学習について本格利用を検討される場合はAWSなど各ベンダーから提供されているドキュメントなどのリソースを十分にご確認いただくことをお勧めします。

また、弊社ではクラウドや機械学習のエンジニアが講師を担当する各種のトレーニングコースを提供しています。そのためクラウドにおける本番利用を想定した構成の実例や、機械学習の勘どころなど実践的な情報を短期間で効率的に獲得いただくことができます。 研修時間内であれば自由にクラウドを操作して体験していただくこともできるため、GPUやクラウドの導入を検討されている皆様、ぜひ受講をご検討ください!

(田川 浩史)