【X’mas間近】非エンジニア経営者がABEJA Platformを使ってオシャレ服を推薦するLINE Botを作ってみた


はじめまして、外木です。ABEJAでは、約5年間日本の事業・組織・ファイナンスなどの責任者を担当して、1年半前から日本以外の責任者をしております。今回の記事は主に、①技術に苦手意識を持つ非エンジニア経営者や、②「AIで何とかしてくれ」と情報発信をする経営者に気付きの材料を与えたいエンジニアの方に是非読んでいただければ幸いです。（この記事は[ABEJA Platform Advent Calendar 2018](https://qiita.com/advent-calendar/2018/abejaplatform)の23日目の記事です。）

## 2019年は「経営者によるAI/MLモデル実装元年」

![IMG_3807.jpg](https://qiita-image-store.s3.amazonaws.com/0/139372/3b511721-8ee5-5f55-88db-e640daf0aee5.jpeg)

AI/ML含めた本場の最先端テクノロジーに触れるために、2018年11月末日から12月上旬にラスベガスで開催されたAWS re:Invent2018に参加しました。Keynoteで、AWSCEOのAndrew Jassyより、[AI/ML活用をサポートする多数のサービスの紹介](https://www.youtube.com/watch?v=ZOIkOnW640A)がありました。

- [SageMaker RL](https://aws.amazon.com/jp/blogs/aws/amazon-sagemaker-rl-managed-reinforcement-learning-with-amazon-sagemaker/)や[SageMaker Neo](https://aws.amazon.com/jp/sagemaker/neo/)などのワークフローを支えるサービス
- [Amazon Forecast](https://aws.amazon.com/jp/forecast/)・[Personalize](https://aws.amazon.com/jp/personalize/)・[textract](https://aws.amazon.com/jp/textract/)などAPIを叩くだけで、AI/MLを有効活用できるサービス
- [Amazon Elastic Inference](https://aws.amazon.com/jp/machine-learning/elastic-inference/)・AWS Inferentiaなどインスタンスに関わるサービス
- [AWS Marketplace for ML](https://aws.amazon.com/marketplace/solutions/machinelearning/)などのマーケットプレイスサービス

このような便利な技術・サービスを駆使して、クイックにトライアンドエラーを重ねる会社が世界中に多々ある一方で、日本の大半の経営者は、昨今のAI/MLブームで氾濫したAI/MLの二次情報の収集を続けて、意思決定をするための判断材料が不足して前に進まなかったり、パートナーや技術担当者に丸投げで、目的のないPoCが動いて成果が出ずに費用対効果も見えずと、苦しい現状に直面しています。AI/MLプロジェクト成功には<b>AI/MLの実プロジェクトで、全プロセスを自らが苦労をしながら経験することが成果創出の最短経路になることを認識する</b>ことが大切です。今回はABEJA Platformを活用した中で得た学びを、経営視点で共有します。

## Tl;dr
- <b>AI/ML市場は2018年末でまだまだ黎明期</b>、基礎的なスキルは非エンジニアであっても、キャッチアップすることで、今後の事業開発機会を広げておく
    - 経営者自身が率先して経験値を積んでおくことが、会社の未来創りにつながる
- <b>AI/MLの社会実装の実現に向けて、実は面倒で複雑なプロセスがいまだ多数</b>存在
    - 意思決定に関わるすべての経営者にAI/MLの知見、特に基本的なプロセスの理解は必須
    - 自社の優秀なエンジニアは本質的に解くべき問いに集中できず、運用や保守対応で逼迫
- ABEJA Platformは<b>AI/MLに関わる多くの"面倒くさい"開発プロセスをスキップ</b>できる
    - 代表的なIaaSに関する深い知見がない自分のような経営者でも頑張れば使えるPlatform
    - AI/MLモデルの構築だけではなく、先の運用を見据えた設計ができるとムダなく実装が可能
- <b>経営者や事業責任者こそ、楽をせず自分で手足を動かして</b>技術の尊さを理解する
    - （自分の出来なさを理解した上で）エンジニアメンバーの日々の業務の楽しさや大変さを少しでも理解する
    - ROI含めた意思決定をする上での勘所を理解できるようになる
    
## 会社を6年半経営して失った「あるもの」を取り戻す旅路

![hair_biyou_bosabosa_ojiisan.png](https://qiita-image-store.s3.amazonaws.com/0/139372/f3ab87ce-3934-e052-85c5-824e2ec712ac.png)


大学生の頃は、アパレルショップで働いたり、古着屋もどきを経営したり、ファッションには興味があったにも関わらず、ABEJAを6年半経営するなかで、<b>経営者として大切な身なりを意識していない非
モテ
エンジニアになっていることにふと気付いてしまいました。</b>

[美意識を重視している会社](https://newspicks.com/news/3448587/body/)を体現するリーダーとして、ファッションもABEJAらしく深く広く理解を深め直すために、アイデンティティ・ジェンダー・美学・創造性・身体性・唯物論などと密接に紐付けながら思考するようにしました。

同時に、プライベートでズボラな自分だからこそ、より楽にオシャレができる方法を考えてみようと妄想をする中で、最近メンバーが投稿していた[LINEとかで写真を共有しただけで、何かしら返答が来る](https://qiita.com/peisuke/items/f46e46a98692c3490f15)Interfaceにヒントを貰い、美意識を取り戻すために、<b>ABEJA Platformを駆使して、LINE Botに自分の
もさい
洋服写真を投稿したら、オシャレな人が着ている似た服装をレコメンドしてくれるモデル</b>を作ることにしました。

## LINE Botを使って、デートでオススメなオシャレ服を推薦してくれるAL/MLモデルを構築
### ファッションデータセットを準備
今回はファッションに関する著名なデータセットである[DeepFashion](http://mmlab.ie.cuhk.edu.hk/projects/DeepFashion.html)を活用します。要するに大量の写真1枚1枚に意味が付与されたデータの集まりです。

そして、ABEJA Platform SDKを活用して、DeepFashionの約20万枚の画像とラベルの登録をします。
![図1.png](https://qiita-image-store.s3.amazonaws.com/0/139372/67ba5d3c-9cf6-06ec-042d-dcee11985e44.png)

### 洋服の特徴を理解するAI/MLモデルを作る
次に、ローカル環境（自分のPC）で、洋服の特徴を理解し、洋服の写真を入力すると、センスの良いコーディネート写真が出力されるモデルを作ります。

はじめにABEJA Platform上に`deep-fashion-classification`というTraining Job Definitionを作成します。次に、ローカル環境でTrainingを開始するために `abeja training init`と入れて、ABEJA Platform上にTraining Job Definition Versionを作成します。

```
$ abeja training create-version
```

上記のコマンドを入れることでABEJA Platform上に学習コードがアップロードされ、新しいバージョンが作成されます。

実行と修正を繰り返し、実際にすべてのデータを使って学習を実行します。

<img width="1031" alt="job-running.png" src="https://qiita-image-store.s3.amazonaws.com/0/139372/1655df4f-4631-6657-9181-0c243589d60d.png">

ここからは試行錯誤でよしなに修正しながら、成果（今回は精度）を高めていきます。想定外に学習に時間が掛かり、終わりの見えない戦いを繰り返します。実行中はただひたすらに待ちます。ABEJA Platformの精度比較機能便利ですね！
<img width="1022" alt="job-finished.png" src="https://qiita-image-store.s3.amazonaws.com/0/139372/fdf2d2e3-4bea-be99-f5b1-ee7de505c0c6.png">

学習が完了したら、結果をダウンロードして推論用のコードを実装します。
（今回はDeepFashionデータセットをすべて学習に掛けてしまって膨大な時間が掛かってしまい、通常はLoss関数をみながら30-100回くらい回すとよい（アドバイスありがとうございます！）エポック数も1回になってます。。）

```python
import os
from keras.preprocessing import image
from keras.models import load_model
from keras.applications.vgg16 import preprocess_input
import numpy as np
from PIL import Image

from abeja.datasets import Client as DatasetClient

img_rows, img_cols = 224, 224

# Trainingの結果をロードします
dir_path = os.path.dirname(os.path.realpath(__file__))
model = load_model(os.path.join(os.environ.get('ABEJA_TRAINING_RESULT_DIR', '.'), 'model.h5'))

# Datasetから登録されたLabelの一覧を取得しておきます
dataset_id = '9999999999999'
client = DatasetClient()
dataset = client.get_dataset(dataset_id)

labels = dataset.props['categories'][0]['labels']
label_mapping = dict((l['label_id'], l['label']) for l in labels)


def decode_predictions(result):
    result_with_labels = [{"label": label_mapping[i], "probability": score} for i, score in enumerate(result)]
    return sorted(result_with_labels, key=lambda x: x['probability'], reverse=True)


def handler(_iter, ctx):
    for img in _iter:
        img = Image.fromarray(img)
        # 入力画像をリサイズします
        img = img.resize((img_rows, img_cols))

        x = image.img_to_array(img)
        x = np.expand_dims(x, axis=0)
        x = preprocess_input(x, mode='tf')

        result = model.predict(x)[0]
        sorted_result = decode_predictions(result.tolist())
        yield {'results': sorted_result}
```

実際にローカルで推論コードを実行して画像を送って反応を確認します。

![naoki_jacket.jpg](https://qiita-image-store.s3.amazonaws.com/0/139372/0e815a99-311f-3321-aa43-4d8a5881f331.jpeg)

```json
{
  "result": [
    {
      "label": "Jacket",
      "probability": 0.5076533555984497
    },
    {
      "label": "Blazer",
      "probability": 0.2561381161212921
    },
    {
      "label": "Cardigan",
      "probability": 0.07291409373283386
    },
    ...(省略)
}
```

確かにジャケット（Jacket）を識別できているようですね！（確かにブレザー（Blazer）と間違えるのも何となくは分かる）

### Line Botでセンスの良いコーディネートを発見する
最後に、Line Botにつなげて、LINEで写真を共有すると、センスの良いコーディネート写真を跳ね返してくれるようにしてきます。これで皆さん、幸せなクリスマスを過ごすことができること間違いなしです。

今回は、推論で出たカテゴリーから `Google Search API`で画像検索した結果を、コーディネイト画像と簡易的にて決め撃ちしております。推論コードに以下のような変更を加えます。

`Google Search API`を叩くため、 `google-api-python-client`を使用します。

```python

from googleapiclient.discovery import build

# 推論結果を元に画像検索した結果をオススメコーディネイト画像として返します
GOOGLE_API_KEY = os.environ.get('GOOGLE_API_KEY')
GOOGLE_CX = os.environ.get('GOOGLE_CX')

service = build("customsearch", "v1", developerKey=GOOGLE_API_KEY)

def handler(_iter, ctx):
    for img in _iter:
        ...

        label = sorted_result[0]['label']
        search_result = service.cse().list(q="{} コーディネイト 男性".format(label), cx=GOOGLE_CX, lr='lang_ja', num=10, start=1, searchType='image').execute()
        yield {'label': label, 'search_result': search_result['items'][0]}
```

ABEJA Platformで実際に実行（デプロイ）できるようにするAPIの反応は以下になります。
`label`の部分が推論結果、 `search_result`の部分が推論結果からレコメンドする画像情報です。

```json

{
  "label": "Tee",
  "search_result": {
    "kind": "customsearch#result",
    "title": "タイトル",
    "htmlTitle": "タイトル",
    "link": "http://www.xxxxx.yyyyy.com/zzz/IMG_9999.jpg",
    "displayLink": "www.xxxxx.yyyyy.com",
    "snippet": "xxx",
    "htmlSnippet": "xxx",
    "mime": "image/jpeg",
    "image": {
      "contextLink": "http://www.xxxxx.yyyyy.com/0000/",
      "height": 1024,
      "width": 768,
      "byteSize": 177928,
      "thumbnailLink": "https://xxxxx.com/images",
      "thumbnailHeight": 150,
      "thumbnailWidth": 113
    }
  }
}
```

LINE Botを作る際には弊社メンバーの「[AWS Lambdaを使ってサーバレスでLINE BotとABEJA Platformを連携させてみた](https://qiita.com/peisuke/items/f46e46a98692c3490f15)」を参考に、実装しました。今回の実装で、ABEJA PlatformにデプロイしたAPI経由でオシャレ服の画像のリンクを返すため、リンクの画像を一部加工して、LINE Botから返すようにしました。

あとは試すのみ！[LINE Developers](https://developers.line.biz/ja/)サイトからLINE Botを作成し友達登録して、QRコードを読み取りLINEで「DeepFashionRecommend」と友達になります。

![図3.png](https://qiita-image-store.s3.amazonaws.com/0/139372/fa6f5400-09c7-e33e-8d77-f3c5c6242252.png)

友達になりました。あとは自分の持っているトップスやボトムスを共有してみると・・・

![図4.png](https://qiita-image-store.s3.amazonaws.com/0/139372/5877c207-43cb-157b-cb59-cfac7d315e8f.png)


無事に（自分の洋服よりも）オシャレな服をレコメンドしてくれました。

本当はここからECに飛ばして、実際に商品の購入ができる導線を設計したかったのですが、残念ながら力尽きましたので、特に何も行動は変わらず<b>まったくオシャレになりませんでした</b>。来年は少しでもオシャレに気を遣えるように努力しようと密かに心に誓うクリスマス直前でした。

![hair_biyou_kirei_ojiisan.png](https://qiita-image-store.s3.amazonaws.com/0/139372/d2407ccf-5485-5368-b4b8-ec2fe4bcc58b.png)


## ABEJA Platformに「面倒くさい」を任せて試行錯誤を加速
せっかく走りきったので、よかったことや今後の検討事項を備忘録的にメモします。
### まずはやってみる、から得られる多数の示唆
- AI/MLのモデルの構築・運用などABEJA Platformの便利さ・大変さを追体験できた
    - 多分全部をフルスクラッチで開発していたら何もできなかった、ABEJA Platformはテクニカルサポートも充実していました
    - <b>社内の技術もビジネスも高いレベルで理解しているメンバーたちに感謝</b>
- <b>まずはシンプルに何がしたいのか、を突き詰めるようにした</b>
    - 目的は思考せずに自分のセンスを超越したオシャレ服に出会うこと
    - やりたい事をフワりとしないように、各プロセスを具体的に言語化した
- ボロボロでも最後までやりきることができた
    - 途中で何度も止まり、心が折れることばかりです、でも諦めないで動くまでやりきった
    - 自分の写真を送ったら、反応が返ってくる感動はすごいです
- <b>やりながら次回につながる改良点を多数出せた</b>
    - <b>「分かっていない」ということが分かる、それも含めて多数のアドバイスを貰える
    - Deep Learningモデルの学習で、どのパラメータをどう修正すると精度がどのくらい変わるのか、データセットの取捨選択をしたら精度がどのくらい変わるのかをやりたい、とか
- 何より2019年は身なりに気を付けてセンスの良い大人になりたいなと思いました（笑）

### 限られた時間の中で成果を出す難しさを再認識
- 時間との勝負の中で「とりあえず動くものを作ること」でさえ難しかった
    - そもそもの基礎から圧倒的に理解が不足していたので、年末年始は復習です
    - 限られた時間の中で納品（＝ブログ公開）をするプレッシャーも辛かった。<b>案件獲得前後の成果物に対しての適切な期待値調整や余白のある見積もり設計は最重要</b>
- はじめる前の問題設定はやっぱり難しい
    - <b>一にも二にも「目的」が重要</b>、今回はとりあえず入出力ができた程度、オシャレ服を手に入れるまでは至らず
- 実現をするためのプロセスを言語化することも難しい
    - プロセスを自分で言語化すること、<b>自分のやりたいことは決して丸投げをしない</b>
- （あたりまえであるが）モデルの学習には時間が掛かる（というか難しい）
    - AnnotationToolsを使って、必要最低限のデータセットでやるべき、<b>[Annotationが本当に大事](https://tech-blog.abeja.asia/entry/ml-annotation)です</b>

## AI/MLの民主化の加速に貢献し続けるABEJA Platform

ABEJA Platformに関しては多くの記事で紹介がありますので、今回は省略しますが、AI/ML系のサービスの民主化が進んで、よく誰でも簡単にAI/MLのすべてが扱えるようになった、と誤解される方も多いようです。以下の[NIPS2015論文"Hidden Technical Debt in Machine Learning Systems"](https://papers.nips.cc/paper/5656-hidden-technical-debt-in-machine-learning-systems)でも指摘されているとおり、モデル構築"以外に"実運用をする上でやらねばならぬこと、がいまだ多く存在しております。（詳しくは[推論のための機械学習基盤を本番稼働させる際に気をつけるn個のこと](https://qiita.com/shogomuranushi/items/6af61b9f24d59eee9606)をご覧ください）

![図2.png](https://qiita-image-store.s3.amazonaws.com/0/139372/60f72007-83d5-cdcc-f42d-43987a6d184d.png)

機械学習技術は手元のPCで動かすだけではなく、それをサービス化・運用するところまでが大切であり、<b>多くの機械学習エンジニアにとって、サービス化するためのインフラ（データ蓄積・学習・推論基盤）を自社で用意し、常に最先端をキャッチアップしながら継続的に運用するのは、大変な労力が掛かります。</b>ABEJA Platformを用いることで、簡単・安全にモデルを学習・デプロイ・追加学習することができ、よりイノベーティブで本質的な業務に集中することができます。

昨日までの[ABEJA Platform Advent Calendar 2018](https://qiita.com/advent-calendar/2018/abejaplatform)を読み<b>「エンジニアの話で、経営者には関係ない」と思った方こそ、経営戦略、特にAI/ML方針に関するプロジェクトROIを正しく計算し、意思決定をするためには、AI/MLにおける技術的な原理原則を自身で理解するべきではないでしょうか。</b>

そんなAI/MLの実装に関するノウハウを得られる2DAYカンファレンスのSIX2019の登録は<b>[こちら](https://six.abejainc.com/)</b>です。（締め切るまえにぜひ！）

## 経営者自らが機会を創造し、機会により自社AI/ML事業を牽引する
さいごに要点をまとめます。

- ①<b>1998年当時のインターネット（＝AI/ML）に投資をしませんか</b>
    - 2018年末のAI/ML市場はまだまだ黎明期、非エンジニアこそ、今のうちに自ら習得しておく
- ②AI/MLモデル構築自体はまだスタート地点、<b>イノベーションに集中できる環境を作りませんか</b>
    - AI/MLプロジェクトはモデルを作る以外にも、目に見えない運用の複雑な業務が多々存在
    - 貴重なエンジニアメンバーには本質的なJobs to be doneに集中してもらう
- ③経営者こそ<b>徹底的に手を動かして、（AI/ML含めた）技術に関する自信を付けませんか</b> 
    - 経営者や事業責任者こそ、自分で手を動かして何ができるか、できないかを正しく理解すべき
    - 何より自分で苦労して頑張った結果が、すぐにPC・スマホ越しに反応する感動をぜひ知ってほしいです！

日々葛藤をしながら経営をした約6年半があったからこそ、技術の幅広さや深さなどの全体像をほんの少しだけ知ることができて、技術への知的好奇心、尊敬がより強くなり、会社には本当に感謝しています。ABEJAでは[テクノプレナーシップ](https://newspicks.com/news/3010017/body/)という、テクノロジーとリベラルアーツ、それらを循環させるアントレプレナーシップを磨く良い環境があります。一人で技術の習得に取り組むと躓くことが多い（経験済み）ですし、本当は興味があるけど、分からないからどうすれば良いか分からずということも多い（経験済み）なので、ぜひAI/MLに興味がある経営者の方は一緒に切磋琢磨していけるよう、ご連絡お待ちしております！

[@naoki0423](https://twitter.com/naoki0423)
[ABEJAに興味がある方はこちらへ](https://www.wantedly.com/projects/264011)