AutoMLでおせちの価格予測&GANで非実在おせちを作る

# はじめに

この記事は次のAdvent Calendarの12月12日分です
[機械学習の自動化プラットフォームDataRobotを使って楽しむ冬のイベント予測チャレンジ](https://qiita.com/advent-calendar/2020/datarobot)
DataRobotはマネージドな機械学習（ML）プラットフォームです。データセットの用意からモデルの訓練・デプロイまでを、ブラウザを通じて進めていけるそうです。特徴量設計やモデルの選択もカバーしており、AutoMLサービスの一つということにもなります。ちょうどマネージドなAutoMLサービスに興味があったことから、この機会に試してみることにしました。
この記事がいいねと思ったら___LGTM___お願いします！（例のあれ）

## やりたいこと
さて、このAdvent Calendarのお題は『冬ならではのテーマで機械学習モデルを試そう』だそうです。
私はちょうど百貨店のおせちを探していたため、おせち料理の画像からの価格予測（回帰）を扱うことにしました。
__しかし、何かがひっかかります。__おせちと言えば元旦に食べるものですね。元旦・・・？
そう、__GAN旦__です。
『GANで生成された仮想おせち画像を眺めて、新年の学習がうまくいくことを祈る日』ですね。
GAN（Generative Adversarial Network）については後述することにして、この記事は次の2本立ての内容です。

__1. おせち画像からの価格予測__
![スクリーンショット 2020-12-12 19.11.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162798/23819527-18dd-4568-5097-4f5e2f3dda31.png)

__2. GAN（Generative Adversarial Network）によるおせち画像生成__
おせちGANで生成した画像の一部です
![36.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162798/82820dbb-27ac-2e8c-94d2-57992b95a083.jpeg)

では、始めましょう。

# おせち画像からの価格予測
## データセットの用意
Data Robotは入力データとして画像を扱うことができます。おせち画像のデータセットはさすがになかったので、頑張って約500枚の画像と価格データを集めました。根性で集めるか、Beautiful Soupなど使ってECサイトからスクレイピングするのが順当でしょう。
ところで、おせちは季節アイテムなので、年末以外はデータセットの入手難易度が高いです。もし似たような興味ある人はお早めに。数年分集めて年ごとの傾向を分析したりすると面白いかもしれませんね。

用意したデータセットをData Robotにアップロードすると次のようになります。
いい感じですね。価格の平均値は32,096円、標準偏差は29,393円で、値は6000円〜32万円まで幅があります。
![スクリーンショット 2020-12-10 17.17.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162798/7a0fffd3-5fc9-2aec-8438-be57ab4416df.png)

もしデータに欠損や外れ値があればここで警告を出して教えてくれます。
また、データセットからのtest data分割やクロスバリデーションの設定は機械学習ビギナーがミスりがちなステップですが、DataRobotではここは自動でやってくれるので安心です。クロスバリデーションでモデルを検証した後、最終ステップでtest dataによる検証ができます。
なお、trainとtest dataをユーザーが指定することはできないようです。時系列データやグループ属性をもつデータだとデータ分割は厄介な問題になるのですが、今回は未検証です。


## 機械学習モデルの自動構築
さて、ここからが本番です。
押してくれと言わんばかりにダッシュボードで存在感を放っている『開始』ボタンを押すと、自動で特徴量設計と機械学習モデルの訓練が始まります。
![スクリーンショット 2020-12-10 17.15.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162798/2be1681f-19e3-d9e2-262e-c2ffa90a14fb.png)

デフォルトではオートパイロットモード（=AutoML）が選択されており、複数の試行を通じて、性能の良い機械学習モデルを自動的に選択してくれます。今回は15分程度でオートパイロットが終了し、結果が一覧で表示されます。
今回は、機械学習アルゴリズムとしてElastic Netを使ったモデルが良い性能を示しています。[^1]
![スクリーンショット 2020-12-10 18.25.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162798/8f4addb6-23bc-a251-d516-10edf7b5e31e.png)

ベストなモデルの__テストデータでの予測性能は、平均絶対誤差 13,373円、標準偏差 24,817円、相関係数（ピアソンのR^2） 0.515__となりました。ランダムよりはマシな程度に学習できたことはわかりましたが、正直ちょっと残念な性能です。
この後、他のモデルも追加してもう少し試行錯誤してみましたが上記がベストでした。

### 予測誤差の原因を分析
予測誤差が大きくなってしまった原因を調べるために、テストデータにおける予測結果の散布図を見てみましょう。
![おせち.zipの予測分布 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162798/dac9a263-127d-767c-e5b9-233afce9cf97.png)
この図から、価格が10万円を超えてくる少数の高級おせちを大幅に安く予測している傾向が認められます。機械学習を用いている以上、学習データが少ない領域では最頻値に寄った予測をしがちで、正しい予測をするのは難しいと言えます。よって、十分な性能が得られなかった原因の一つはデータの不足と考えられます。今回の学習データは500枚程度と少ないことから、データの量を鑑みると、簡単に達成できる性能としてはこのあたりが壁かもしれません。ちなみにもし私がここから業務で携わるとしたら、モデルのエンジニアリングはさておき、まずはより多くの学習データを集める試みに注力すると思います。そもそもの問題として、おせちの値段が見た目と相関していない可能性もあるのですが。。

このモデルのアクティベーションマップ（≒モデルが予測のために注目している箇所）[^CAM]を見ると、おせち本体より背景にフォーカスしてしまっていることがわかります。直感的には、おせちの具を見て判断して欲しいところですが、どうもそうではないようです。ちなみに、このようなアクティベーションマップを自分で用意するのは結構面倒なので、数回クリックするだけで可視化できるのは便利です。
![スクリーンショット 2020-12-12 3.52.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162798/ddd76cf9-29c2-2ea4-0e3a-74214da2b457.png)

ここで終わらず、もう少し深堀りしてみましょう。一般的に、重箱の段数と価格には相関がありそうですね。
正方形の画像において、重箱が2段,3段のおせちは、1段のおせちより背景の白領域が多くなるはずです。
そこで、__『おせち画像の背景の白エリアの面積が有効な特徴量として機能しているのでは』__という仮説を立てました。
この仮説は、白エリアの面積と価格の相関を見れば簡単に検証できそうです。（ここは手元のPCで分析しました）
![アートボード 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162798/1794fe8e-86e0-4f48-b66c-71fcb7bd551f.png)
調べてみると、相関係数は0.15程度と、全体ではほぼ無相関でした。しかし、この散布図を見ると、画像背景である白エリアの面積（`white region ratio`）が大きいおせちでは価格にバラつきが大きく、5万円を超える高額おせちのほとんどは、画像の半分以上が白エリアであることがわかります。やや恣意的ですが、この結果の解釈の一例として次が考えられるでしょう。
>価格のボリュームゾーンである2-3万円のおせちでは、白領域と価格に相関は見られない。
一方、5万円を超える高額おせちは、2段や3段の重箱で提供されることが多く、おせち画像の白領域の割合が大きいほど高額となる傾向がある。高額おせちは数としては少数だが、価格のスケールが大きいためモデルの学習に大きな影響を与え、結果として価格予測モデルが背景の白領域に着目するに至った。

さらに調べるなら、大外ししたデータ具体的に見ていったり、画像をt-SNE等で次元圧縮して可視化[^tSNE]して調べたりと色々やりたいことはありますが、長くなるのでこのあたりにします。
性能はともかく、これでおせち画像から価格を予測する機械学習モデルを構築できたとして、次に進みましょう。

# Lightweight GANによるおせち画像生成
元旦もといGAN旦に食べるおせち画像を、GANを使って生成してみましょう。
## Generative Adversarial Networkって？
Generative Adversarial Network（GAN）とは、DNNを用いた深層生成モデルの一つです。GANは生成モデルという名前の通り、新しいデータを生成することができる手法です。詳しい説明は他の解説記事や論文に譲りますが、2014年にGoodfellowらによって発明されて以来、凄まじい勢いで進化を重ねている技術です。GANがもっとも成功しているのは画像への応用で、近年では本物と見分けがつかないほど綺麗な画像の生成が可能になっています。一例として、GANによる顔画像の生成結果の変遷を示します。
![GANによる画像生成結果の変遷](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162798/709e869f-73f2-1388-b4a0-c11f9c4e2a7b.png)
[Which face is real? (https://www.whichfaceisreal.com)](https://www.whichfaceisreal.com/index.php)というwebサイトでは、人間の顔画像を見て、それがGANで生成されたものか、本物の顔かのクイズで遊ぶことができます。かなり難しいです。

GANの実用上の大きな課題の一つは、学習に大量のデータと計算リソースが必要になる点です。
例えば上記画像右の[StyleGAN](https://github.com/NVlabs/stylegan)の学習には、7万枚の画像データセットと8個のGPUで1週間の計算が必要です。これを普通のゲーミングPCで実行したら2ヶ月ほどかかり、おせちを用意する前に2020年が終わってしまいます。
この問題を解決しようとする試みは多数ありますが、つい最近（2020年11月末）発表された[Towards Faster and Stabilized GAN Training for High-fidelity Few-shot Image Synthesis](https:![Something went wrong]()
//openreview.net/forum?id=1Fqg133qRaI)という論文で、Lightweight GANという手法が提案されました。DNNの構造と学習方法を工夫することによって、100枚程度の画像と1GPU・数時間の学習により高解像度かつ品質の良い画像生成を可能にした手法だそうです。上記論文では、様々なドメインで非常に高品質な画像生成に成功した結果が示されています（図5を一部改変）。
![lightweight_gan_paper@400x-80.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162798/18fd01ef-3e49-cf4f-1f7b-ab1632801383.jpeg)

## Lightweight GANによるおせち画像生成
今回はこのLightweight GANを用いておせち画像を生成します。ありがたいことに、Lightweight GANはPyTorchで書かれた使いやすい再現実装が公開されています。今回はこちらを使います。
[https://github.com/lucidrains/lightweight-gan](https://github.com/lucidrains/lightweight-gan)
使い方は簡単で、上記リポジトリをcloneし `pip install lightweight-gan`を実行した後に、次の1行で動きます。詳しい使い方やオプションについてはREADMEを参照してください。

```shell

lightweight_gan --data ./path/to/images --image-size 256
```

Google ColabのGPUランタイムでLightweight GANを12時間学習した後、生成した画像がこちら。価格予測モデルの学習に使用したのと同じ約500枚のおせち画像を学習に用いました。
![36.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162798/1d5ca0bb-ad99-d6dd-eb21-be8c21a0732e.jpeg)
かなりそれっぽい結果ではないでしょうか。ところどころ破綻してるのも味わい深いですね（？）
遠目から見るとおせちにしか見えませんが、拡大するとおせちじゃないのが不気味で良いです。

GANの潜在空間上を移動しながら画像を生成するとこんな感じになります（Interpolation）。
![interporate@400x-80.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162798/63414599-a538-7329-3f89-bf9c756abefa.jpeg)
GIFにしました。ぐにぐに動きます。悪夢に出そうです。
![generated-12-11-2020_06-14-48.mp4.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162798/bd49ef1b-670e-09fb-bbc6-b2feb97f5639.gif)

これでGAN旦のおせちの準備ができましたね。好きなだけおせち画像を生成できます。


## おまけ：GANで作ったおせちの値段は？
初めにDataRobot上で構築した、おせちの価格予測モデルを用いて、GANで生成したおせち画像の価格を予測しました。ここでは予測モデルとGANの学習では違うデータセットを用いるべきですが、おまけの遊びということで。。
みなさんの直感とは合っていますか？
![generated_predict@400x-80.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162798/4c457d72-3b42-ed81-628c-429e5e655289.jpeg)

# 終わりに
Data Robotは初めて使いましたが、最初にモデルを学習させるまでの技術的・心理的ハードルをなるべく下げていることが伝わってきました。まず手元のデータでPoCしたいなど、サクッと試したい時には有用そうです。個人的な印象ですが、ユーザーペルソナとしては「専任のデータサイエンティストではないが業務のために機械学習を使いたい方」かなと思います（『商品の仕入れ数を経験で決めているが、データに基づいて予測したい』など、）。
UIや用語にはややクセがあるように感じましたが、他のAWSやGCPのサービスを使う場合に比べ、覚えるべきことが少なそうです。一方で、利用できる機械学習アルゴリズムには制約があったり、特徴量設計や前処理まで戻ってのトライアンドエラーはワークフロー上しづらいなど、システム上の制約があるのも確かです。簡便さと多機能さはトレードオフなので、ここは道具の使い分けの問題と思います。詳しい人はGoogleのAI Platform Notebooksなど使うほうが所望のことができるでしょう。

GANの学習は非常に難しく、同じ画像しか生成されなくなったり（mode collapse）よくわからない理由でバグったりと、様々なハマりどころが知られています。しかし今回は何のトラブルも無くあっさり動いたので、画像の品質と合わせて最新のGANの進化に驚きました。
興味がある方はぜひ自分の好きなデータで試してみてください。

[^1]: MLに明るい方は、「画像なのにElastic Net？」と疑問に思うかもしれません。Elastic Netは非常に古典的なアルゴリズムで、画像を直接入力として扱うのは苦手だからです。Data Robotでは、予め学習済みのDNNに入力画像を通して、そのDNNの出力を特徴量として他の様々なアルゴリズムの入力に使うことで対応しています。

[^CAM]: ところで、オリジナルのクラスアクティベーションマップ（CAM）は分類問題において各クラスについてのfeature mapの重みや勾配を用いてCNNの着目領域を可視化する手法ですが、Data Robotでは、回帰問題でもアクティベーションマップが出力できるようCAMを拡張しているそうです。実装が気になるところですが、詳しい情報は記載がありませんでした。プロプライエタリなサービスの難しいところです。

[^tSNE]: Data Robotには画像の特徴量を次元圧縮して2次元で可視化する機能（画像埋め込み）がありますが、現状ではUIに難があり意味のある分析ができなかったので今回はスキップします。