nikkie-ftnextの日記

イベントレポートや読書メモを発信

LT報告 | #jawsdays で機械学習を組み込んだPython製アプリのデモLTをしました

はじめに

いつも心は虹色に! nikkieです。
2/23のJAWS DAYS 2019に参加し、懇親会でLTしてきました。
デモアプリを使ったLT(いわゆるLT駆動開発)をして思うところをまとめます。

勉強会の概要

About | JAWS DAYS 2019

JAWS-UGによる全国規模の交流イベントを開催いたします!
AWS初心者から上級者までのエンジニア、経営者や人事、マーケティングエンタープライズからスタートアップ、中小企業など職種や業態・会社規模を問わず、たくさんの方に参加いただけるイベントです。

今年のテーマは「満漢全席」
海外UGのセッションも含め、多岐にわたるテクニカルセッション、ビジネスセッション、ランチセッション、OpenMic、LTも含めて「100以上のセッション」を用意します。

AWSの情報収集がしたくてJAWS DAYSに参加しました。1
今回が初めてのAWS関連のイベントです。

LT駆動開発の動機

1月くらいに「懇親会LT募集」が告知され、「Amazon MLについて話せそうだし、AWSを触ってみるLT駆動開発をやってみよう」と応募しました。
LTをすることで、

  • 聞き手(AWS経験豊富な方々):機械学習Amazon MLを使用)が選択肢に上がるようになる
  • 私(AWS初学者):Amazon ML以外のAWSサービスを触ってみる

という狙いがありました。

LT: Amazon Machine Learningで機械学習始めませんか?

懇親会を盛り上げるため、デモを中心に構成しました。(デモ→理論の順)
このレポートでは、本来想定していた講義形式(理論→デモ)で説明していきます。

伝えたかったこと

手元にたまったデータをもとに、未知のデータを予測する推論のルールを作るのが、機械学習で可能なことの一つです。
デモアプリの例では、手元にタイタニック号の乗客データがたまっています。(26歳・男性は死亡、28歳・女性は生存、といったデータが800〜900あります)
乗客データから推論のルール(=モデル)を作ることで、生存/死亡が不明のデータ(28歳・男性)についてモデルで予測できます
そして、モデルをAPIにすることで、モデルの推論結果をプログラムから利用しやすくできます。
28歳・男性という属性情報をAPIに送ると、APIは生存または死亡という予測結果を返します。

モデルの作成〜API化までをウィザード操作で可能にするのが、Amazon Machine Learning(以下Amazon MLです)
ウィザード操作ですのでコーディングは不要ですし、APIにまでしてくれるので、得意な言語から呼び出して、モデルの推論結果を利用できます。
Amazon MLで作ったモデルの使い方がイメージしてもらえるよう、「あなたがタイタニック号に乗っていたら助かるでしょうか?」というデモアプリを用意しました。

タイタニック乗客の生死の予測では、現実にアプリに機械学習を組み込む場面を想像しにくいかもしれません。
ビジネス面に即せば、例えば、優良顧客の判定といった事例が考えられます。
(年齢・性別などの顧客属性と優良顧客か否かというデータからモデルを作り、属性から優良顧客か判定する機能を実現します)

使った技術

AWSサービス

機能について補足します。
生存/死亡を予測するモデルには、入力として属性情報(年齢・性別など)が必要です。
学習した際に使ったデータと丸々同じデータをモデルに入力しなければエラーとなってしまいます。
ですので、手元のデータから作ったモデルでは、顔写真から生死を予測することはできません。

顔写真から年齢・性別情報を取り出せば、今回のモデルで生死を予測できます。
顔写真から年齢・性別情報の取り出しにRekognitionを使いました。 Rekognitionで取り出した年齢・性別情報2を手元のモデルに渡すと、生存/死亡が予測されます。

f:id:nikkie-ftnext:20190224004329p:plain

Pythonパッケージ

  • Flask
  • boto3
  • zappa

パッケージの所感はこちら:イベントレポート | #pyhack にてAmazon MLの機械学習モデルを組み込んだFlask製アプリをzappaでLambdaにデプロイしました - nikkie-ftnextの日記

顔写真から助かるかどうかを予測する機能について解説します。(boto3を使って、Amazon MLやRekognition、S3を呼び出しています)

アップロードされた顔写真を画面に表示する(imgタグ)ため、まずS3に画像をアップロードしています。

  1. S3の画像を指定してRekognitionを叩く
  2. S3の画像について制限時間付きで有効なURLを取得(imgタグに使う)

当初はアップロードされた画像を(バイナリで)Rekognitionへ送り、その後S3へアップロードし、imgタグ用のURLを取得の順で考えていました。
ところが、Rekognitionへ送った段階でファイルがクローズしてしまうようで、Rekognitionへ送るかS3へアップロードするか一方しかできないと認識しました。
S3の画像指定でRekognitionが呼び出せたので、後者を選択して上記の流れになりました。

なお、ソースコードはこちらです

フロントエンドに挑戦

サーバサイドに比べて経験が少ないのですが、デモできるくらいには見た目を整えることに挑戦しました。

懇親会ではスマホでデモアプリにアクセスしてもらう想定でしたので、Bootstrapを採用しました。
exampleを真似してモバイルでも崩れない表示にすることはできました。
Checkout example · Bootstrap

f:id:nikkie-ftnext:20190224004403p:plain

顔写真から予測する処理は処理時間が長く、処理中ということをユーザにフィードバックする必要がありました。(連打されて同一画像が複数回アップロードされるのは望んでいません)
jQueryフォーム送信時(formのsubmitイベント)に、ボタンをdisabledにすることにして対応しました。

やろうとしてできなかったこと

期間内に実装が終わらなかったアイデア一覧です。

  • 画像アップロード処理のスレッド化
    • Rekognition呼び出しとimgタグ指定用のURLの指定は並列化できると考えています(処理時間がどれだけ変わるかわからないですが)
    • Amazon MLで作ったモデルの呼び出しをJSで実装してみたいです
  • ローディング表示(ajax?)
  • 利用データのDB保存
    • loggingでCloudWatchに流しています3が、DynamoDB4にためて分析の余地を用意しておきたいです
  • zappaでdebug=TrueのFlaskアプリのデプロイは、ベストプラクティス?

ネタバラシ

繰り返しになりますが、今回はモデル(推論のルール)を手元にたまったタイタニック乗客データから作っています。
つまり、モデルは手元のデータの傾向を反映します。
実はタイタニックの乗客の生存と死亡には、性別と年齢が大きく関わっています。(チケットのクラスと乗船した港は寄与が小さいです)
救命ボートの数が足りず、「女性と子供優先」という方針が取られたため、生存者には女性と子供が多いです。
つまり、女性(でかつ、低い年齢)として情報を送れば、生存と予測されます。

f:id:nikkie-ftnext:20190224004444p:plain

終わりに

LT駆動開発してよかった」この一言につきます。
決して現在のアプリに満足しているわけではありません。
フロントエンドはまだまだですし、サーバサイドは試したいことが多々あります。
それでも作りたいものを時間内で実現するため、通勤時間で必死に調べ、睡眠時間を少し削って実装時間を確保し、「これでいけるだろう」という案が動いたときの高揚感!
資料を作って登壇するという経験とは別種の学びがありました。
不完全なアプリでもアウトプットするのは重要ですね。
自分のスキルアップのために、機能の追加(ブラッシュアップ)に挑戦していきます!

AWSを触ってみたところ、Lambdaへのzappaでのデプロイは非常に快適で5、Lambdaを触れたのがとりわけ大きいと思っています。

最後になりますが、初参加のJAWS DAYSで、AWS初学者にLT駆動開発の機会をくださった運営の皆さまにお礼申し上げます。
LTを聞いてくださった皆さま、デモアプリで遊んでくださった皆さま(50名超!)、Twitterでツイートしてくださった方々、誠にありがとうございました。
ここまでお読みいただき、ありがとうございました。


  1. これまでAzureメイン、k8s体験をGCPといった感じで触ってきています。Python界隈では「Azureでハマっている人」という認識もされているようです。

  2. 説明中は年齢と性別に代表させていますが、データにはチケットのクラスと乗船した港も含まれています。「ネタバラシ」で述べますが、年齢と性別が予測への寄与が大きいです

  3. loggingで書くだけでCloudWatchに記録されるのは驚きです。ref: Python の AWS Lambda 関数ログ作成 - AWS Lambda

  4. サーバレスで実装するアプリはRESTで叩けるNoSQL DBがプラクティスとのことです(初心者ハンズオンより)。RDBだとConnection Poolがないので同時に大量のConnectionが張られてしまう

  5. かつて WebAppsにデプロイは難しい というLTをしたことがあります