Watson Studioで類似画像検索(1)

Watson Studioを使用して類似画像検索を試して見たので、手順を記載しておきます。

# 参照先
方法やコードは以下リンク先の情報をだいぶ活用させていただきました。
https://jifuzhao.github.io/2018/04/13/landmark.html
https://github.com/JifuZhao/Landmark-Recognition

# データセット
上記リンク先の通り [Google Landmark Recognition Dataset](https://www.kaggle.com/c/landmark-recognition-challenge/data) を使用しています。こちらのデータセットには世界各地のランドマーク（名所等）の画像（約11万箇所、120万枚）が提供されており、トレーニングデータ(train.csv)には以下のようなフィールドが含まれています。


|列名 |説明  |例|
|---|---|---|
|id  |各画像に固有のid  |97c0a12e07ae8dd5|
|url |画像のダウンロード先|http://lh4.ggpht.com/-f8xYA5l4apw/RSziSQVaABI/AAAAAAAAASE/V8rWCdC0cvI/s1600/|
|landmark_id |ランドマーク毎に固有のid|6347|

ここではデータセットのサブセット（1000箇所、1万枚、224x224にリサイズ）を使用して類似画像検索を実装します。

# 1. データの準備
以下から上記に記載のデータのサブセットdata.zipをダウンロードします。
https://ibm.box.com/shared/static/edtoxjtlvtvd1jdlyls2hqzwoey0js6q.zip

Watson Studioで新規プロジェクトを作成後に、以下のURLからNotebookを作成します。
https://github.com/schiyoda/ImageSimilaritySearch/blob/master/1_Data_Preparation.ipynb

![image.png](https://qiita-image-store.s3.amazonaws.com/0/235649/8cbce38b-bc03-315d-c3cc-44aa92244f0c.png)

Notebook右側のDataパネルから先ほどダウンロードしたdata.zipを追加します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/235649/a86419fc-0b9a-9310-b161-b4d2ea2d0098.png)

Notebook一番上の空のセルにカーソルを合わせ、追加したデータの "Insert to code" -> "Insert Credentials" を選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/235649/78743bac-e187-d3cd-8e3a-888f9a1e8e6a.png)

以下のようにNotebookにcredentialが追加されます。(credential名が"credential_1"になっていない場合は修正します)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/235649/f85f953c-3d5a-ff53-5aa9-1e3eeef30711.png)

Notebookのセルを全て実行し、データの中身を確認します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/235649/bcdca913-0ffc-ee6e-175f-a9c5b98de934.png)

# 2. 学習済みモデルを使用した類似画像検索
ここではCNNで学習済みのモデルInception V3を使用して画像の類似検索を実装します。学習済みのモデルに画像を投入すると、特徴量をベクトルとして抽出することができます。K-NN（K近傍法）でベクトル間の距離を計算することで、距離が短いほど類似しているとみなすことができます。

## 2.1. 特徴ベクトルの抽出
特徴ベクトルの計算は計算量が多く時間がかかるため、Watson Studioに実装されたディープラーニング機能(DLaaS)を使用します。

まず、先ほどダウンロードしたdata.zipをDLaaSで使用できるようにObject Storageにアップロードします。アップロードの仕方は以下のリンク先等を参照してください。

https://qiita.com/ishida330/items/b093439a1646eba0f7c6#icosibm-cloud-object-storage%E5%81%B4
https://qiita.com/schiyoda/items/c1fe7438e50087ff97ef

私はCyberduckでアップロードしましたが、アップロード後にバケットの直下にdata.zipが置かれています。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/235649/88c74124-a606-caac-91f0-57e9c25f3c1f.png)

以下のpython のコードをダウンロードして zip に圧縮します。こちらのコードでは Train、Validation、Test の各画像から各々2048次元の特徴ベクトルを抽出し、NumPy array としてObject Storageに保存します。
https://raw.githubusercontent.com/schiyoda/ImageSimilaritySearch/master/2.1_extractFeatureInceptionV3.py

Watson Studioで新規experimentを作成します。
Machine Learning Serviceは新規あるいは既存のサービスを設定します。
"Cloud Object Storage bucket for storing training source files" の "Select"をクリック -> "New Connection" タブで適当な名前を指定します。さらに、source dataとしてdata.zipをアップロードしたバケットを指定します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/235649/feceae28-0c1e-0f50-48a7-1964454b714b.png)

"Cloud Object Storage bucket for storing results"も同じものを指定すればOKです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/235649/328f2812-19d9-29e2-a1d7-17296f4223da.png)

右側の![image.png](https://qiita-image-store.s3.amazonaws.com/0/235649/7f0514a4-2586-f5a7-f6d1-2ab405e47737.png)をクリックします。

適当な名前をつけて、"Training source code"に先ほどzip にしたコードを指定、"Framework"は "tensorflow 1.5"、"Execution command" は以下のように指定します。

```console
python3 2.1_extractFeatureInceptionV3.py
```

右側のCompute planを選択し、"Create"を選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/235649/c854c713-4f07-5b7e-22d6-6d28f8252a6f.png)


さらに次の画面で"Create and run"を選択すると、処理が待ち行列に入り(Queued)、しばらくすると実行中(In progress)になります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/235649/0f738073-21a4-faca-a437-02f4f4708607.png)


処理が完了すると、以下のように表示されます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/235649/272a1430-074e-1b1a-bd39-e93c060e7d06.png)

Object Storageに特徴ベクトルが保存されたようです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/235649/249241e2-f02b-edb7-1a18-ecd10fdcab00.png)


> エラーになった場合はログを確認し、エラー箇所を修正した上で、"Add training runs"で再度 training definition を作成します。

## 2.2 画像類似度の算出
抽出された各画像の特徴ベクトルから、画像間の類似度を算出します。
以下のURLから新規Notebookを作成します。
https://github.com/schiyoda/ImageSimilaritySearch/blob/master/2.2_predictInceptionV3.ipynb

Notebook一番上の空のセルにカーソルを合わせ、Connectionsの "Insert to code"を選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/235649/c9c0256c-44ea-c8ba-9f2d-9018ac99d7e4.png)

以下のようにNotebookにcredentialが追加されます。(credential名が"credential_1"になっていない場合は修正します)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/235649/0319ddab-6a93-4790-79f3-4253f3b4e65d.png)

2つ目のセルでバケット名を指定した上で、セルを全て実行します。以下のように Accuracy が表示されます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/235649/ed15df80-38d4-30a5-e5f2-48d8f551fdf7.png)

検索された画像は以下の通りです。一番左の画像が Queryの画像で、左から類似度が高い順に10件表示しています。青枠で囲った画像がQuery画像と同じlandmark_id（同じ場所）を表しています。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/235649/4bcc9da6-5f26-305c-2c91-129b18dc6b5f.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/235649/2a153fe3-7c50-1ec1-d383-0b25f922dec2.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/235649/b700a18e-effd-a070-ac1d-b1bbebc7f843.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/235649/20d9d7ed-e25f-605e-8931-848fb161f5e2.png)