オフライン環境 +  CPU環境でも動く画像キャプション文生成モデルをMacbookで動かしてみた


###今回、動かしたコード

- [（GitHub） yunjey/pytorch-tutorial/tree/master/tutorials/03-advanced/image_captioning](https://github.com/yunjey/pytorch-tutorial/tree/master/tutorials/03-advanced/image_captioning)
- [PyTorch 画像から文章をサクッと生成してみる](http://cedro3.com/ai/pytorch-image-captioning/)

###動かした結果

__ここで、MacbookのWifi接続を切りました。オフライン環境で、推論工程を行えることを確認しました。__

推論を行うたびに、Torch.hubにアクセスをかけるスクリプト・ファイルの場合は、インターネットにつながっていないと、実行エラーが発生します。

以前、取り組んだCATRモデルの実装コードは、Huggingfaceのサイトにアクセスするタイプであったため、Wifiがつながらない環境では、推論処理を行うことができませんでした。

- [画像キャプション生成モデル 「CATR」の出力文を入力画像に埋込んでファイル出力するように書き換えてみた](https://qiita.com/electronics_diy721/items/03b8d601da4280c8368b)

###[出力文] *<start> a man is riding a horse in a field . <end>*

![スクリーンショット 2021-08-07 21.42.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1754134/ccf1b4fe-e0a1-1dfa-1386-6d5e64dd17fe.png)
 
```bash:Terminal
electron@diynoMacBook-Pro image_captioning % python3 sample.py --image='png/test001.png'                                     
<start> a man is riding a horse in a field . <end>
electron@diynoMacBook-Pro image_captioning %
```

###[出力文] *<start> a group of people standing around a table with a frisbee . <end>*


![スクリーンショット 2021-08-07 21.43.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1754134/4f3ca07b-d4be-6117-1125-9aa760e0d049.png)

```bash:Terminal
electron@diynoMacBook-Pro image_captioning % python3 sample.py --image='png/test003.jpg'
<start> a group of people standing around a table with a frisbee . <end>
electron@diynoMacBook-Pro image_captioning % 
```

###[出力文] *<start> a man holding a tennis racket and a tennis ball . <end>*


![スクリーンショット 2021-08-07 21.44.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1754134/db9572ad-bf69-9cc0-ebc1-5594003ce777.png)

```bash:Terminal
electron@diynoMacBook-Pro image_captioning % python3 sample.py --image='png/test005.jpg'
<start> a man holding a tennis racket and a tennis ball . <end>
electron@diynoMacBook-Pro image_captioning % 
```

###[出力文] *<start> a man is holding a large umbrella in a room . <end>*

![スクリーンショット 2021-08-07 21.43.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1754134/f5db4d04-dabf-6944-ecc0-5e6d40e0509f.png)

```bash:Terminal
electron@diynoMacBook-Pro image_captioning % python3 sample.py --image='png/test007.jpeg'
<start> a man is holding a large umbrella in a room . <end>
electron@diynoMacBook-Pro image_captioning % 
```

###[出力文] *<start> a woman and woman with a teddy bear in a room . <end>*

![スクリーンショット 2021-08-07 21.45.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1754134/e40a57af-720a-f4a4-d03a-c416ba871599.png)


```bash:Terminal
electron@diynoMacBook-Pro image_captioning % python3 sample.py --image='png/test010.jpg' 
<start> a woman and woman with a teddy bear in a room . <end>
electron@diynoMacBook-Pro image_captioning % 
```

###環境構築

まずは、git cloneします。

```bash:Terminal
electron@diynoMacBook-Pro Desktop %  git clone https://github.com/yunjey/pytorch-tutorial.git
```

```bash:Terminal
electron@diynoMacBook-Pro Desktop % cd pytorch-tutorial 
electron@diynoMacBook-Pro pytorch-tutorial % ls
LICENSE		README.md	logo		tutorials
electron@diynoMacBook-Pro pytorch-tutorial % 
electron@diynoMacBook-Pro pytorch-tutorial % cd tutorials/03-advanced/image_captioning 
electron@diynoMacBook-Pro image_captioning % ls
README.md		build_vocab.py		data_loader.py		model.py		png			resize.py		train.py
__pycache__		data			download.sh		models			requirements.txt	sample.py
electron@diynoMacBook-Pro image_captioning %
```

####続いて、いくつかの作業をします。

- [PyTorch 画像から文章をサクッと生成してみる](http://cedro3.com/ai/pytorch-image-captioning/)

> Google Driveに接続し、pytorch-tutorial/tutorials/03-advanced/image_captioning に移動し、models フォルダー、img フォルダー、 data フォルダーを作成します。
>
> まず、pretrained model をダウンロード・解凍し、下記の様に2つのファイル名を変更して、models フォルダーの中に格納します。
>
> encoder-5-3000.pkl → encoder-2-1000.ckpt
> decoder-5-3000.pkl → decoder-2-1000.ckpt


> __Pretrained model__
>
> If you do not want to train the model from scratch, you can use a pretrained model. You can download the pretrained model __[here](https://www.dropbox.com/s/ne0ixz5d58ccbbz/pretrained_model.zip?dl=0)__ and the vocabulary file __[here](https://www.dropbox.com/s/26adb7y9m98uisa/vocap.zip?dl=0)__. You should extract pretrained_model.zip to ./models/ and vocab.pkl to ./data/ using unzip command.

ここで書いてある２つの__*here*__は、それぞれ次のURLです。

- __*the pretrained model*__

> https://www.dropbox.com/s/ne0ixz5d58ccbbz/pretrained_model.zip?dl=0

![スクリーンショット 2021-08-07 21.30.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1754134/ca9b6cac-84b1-e73b-b4c5-16a653c62103.png)

![スクリーンショット 2021-08-07 21.30.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1754134/f87192b1-cfa6-63d2-310e-7f561f83aa5f.png)

![スクリーンショット 2021-08-07 21.30.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1754134/1759e149-6fe9-af73-fdff-88ab203dc6b0.png)

![スクリーンショット 2021-08-07 21.31.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1754134/bc61cadc-99f3-ef51-bff9-13bf22604977.png)

- __*the vocabulary file*__

> https://www.dropbox.com/s/26adb7y9m98uisa/vocap.zip?dl=0

![スクリーンショット 2021-08-07 21.32.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1754134/cc7fbb42-67bd-b5b0-de3a-1d5f924440e4.png)

![スクリーンショット 2021-08-07 21.32.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1754134/e2ecaf6a-209e-b537-0bf7-e29a664db104.png)

![スクリーンショット 2021-08-07 21.32.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1754134/32948d08-a224-6ac8-2ddc-bf5df1a71497.png)

![スクリーンショット 2021-08-07 21.32.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1754134/1f3c9d6e-083c-f39a-3da3-d02bab02780e.png)

__modelsという名前のディレクトリ__と__data__というディレクトリを、__*pytorch-tutorial/tutorials/03-advanced/image_captioning*__デジレクトリの直下に作る。

```bash:Terminal
electron@diynoMacBook-Pro image_captioning % mkdir models
electron@diynoMacBook-Pro image_captioning % mkdir data
```

そして、ダウンロードした資源を、各ディレクトリに配置する。
その際、解説日本語サイトで書かれていたように、モデルファイルのファイル名を変更する。

> encoder-5-3000.pkl → encoder-2-1000.ckpt
> decoder-5-3000.pkl → decoder-2-1000.ckpt

```bash:Terminal
electron@diynoMacBook-Pro image_captioning % ls models 
decoder-2-1000.ckpt	decoder-5-3000.pkl	encoder-2-1000.ckpt	encoder-5-3000.pkl
electron@diynoMacBook-Pro image_captioning %
```

```bash:Terminal
electron@diynoMacBook-Pro image_captioning % ls data
vocab.pkl
electron@diynoMacBook-Pro image_captioning %
```

####画像ファイルの準備

__pngディレクトリ__に、最初から何点か、画像ファイルが収められています。

```bash:Terminal
electron@diynoMacBook-Pro image_captioning % ls png
example.png		model.png
```

ここで、自分の好きな画像ファイルを自由に置きます。
拡張子は、__*jpg, jpeg, png*__どれでも、推論用のスクリプトファイルに食わせることができました。

```bash:Terminal
electron@diynoMacBook-Pro image_captioning % ls png
example.png		model.png		test003.jpg		test007.jpeg	
image_captioning.png	test001.png		test005.jpg		test010.jpg
```


```bash:Terminal
electron@diynoMacBook-Pro image_captioning % open png/test001.png 
```

![スクリーンショット 2021-08-07 21.42.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1754134/ccf1b4fe-e0a1-1dfa-1386-6d5e64dd17fe.png)

```bash:Terminal
electron@diynoMacBook-Pro image_captioning % open png/test003.jpg 
```

![スクリーンショット 2021-08-07 21.43.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1754134/4f3ca07b-d4be-6117-1125-9aa760e0d049.png)


```bash:Terminal
electron@diynoMacBook-Pro image_captioning % open open png/test005.jpg
```

![スクリーンショット 2021-08-07 21.44.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1754134/db9572ad-bf69-9cc0-ebc1-5594003ce777.png)

```bash:Terminal
electron@diynoMacBook-Pro image_captioning % open png/test007.jpeg
```

![スクリーンショット 2021-08-07 21.43.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1754134/f5db4d04-dabf-6944-ecc0-5e6d40e0509f.png)

```bash:Terminal
electron@diynoMacBook-Pro image_captioning % open png/test010.jpg
```
![スクリーンショット 2021-08-07 21.45.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1754134/e40a57af-720a-f4a4-d03a-c416ba871599.png)

###ソースコード （*sample.py*）の肝の部分を確認


##### 画像ファイルの読み込んでいるところ

- 全部で81行ある。

```bash:Terminal
electron@diynoMacBook-Pro image_captioning % wc -l sample.py
81 sample.py
electron@diynoMacBook-Pro image_captioning % 
```

- Image.open()で読み込んでいる

```bash:Terminal
electron@diynoMacBook-Pro image_captioning % cat sample.py | grep open                           
    image = Image.open(image_path).convert('RGB')
    with open(args.vocab_path, 'rb') as f:
 #   image = Image.open(args.image)
electron@diynoMacBook-Pro image_captioning %
```

- Imageは、PILモジュールを使っている

```bash:Terminal
electron@diynoMacBook-Pro image_captioning %  cat sample.py | grep Image
from PIL import Image
    image = Image.open(image_path).convert('RGB')
    image = image.resize([224, 224], Image.LANCZOS)
    # Image preprocessing
 #   image = Image.open(args.image)
 electron@diynoMacBook-Pro image_captioning % cat sample.py | grep model  
 ```
 
####モデルの指定
 
 - 環境構築の中で、2つのモデルをダウンロードして、__modelsディレクトリ__に配置しました。
 - コマンドライン引数でモデルを指定する仕様になっている。何も指定しないと、エンコーダー側もデコーダー側も、__*5-3000.pkl*__が選択される。
 
```bash:Terminal
electron@diynoMacBook-Pro image_captioning % cat sample.py | grep model                          
from model import EncoderCNN, DecoderRNN
    # Build models
    # Load the trained model parameters
    parser.add_argument('--encoder_path', type=str, default='models/encoder-5-3000.pkl', help='path for trained encoder')
    parser.add_argument('--decoder_path', type=str, default='models/decoder-5-3000.pkl', help='path for trained decoder')
electron@diynoMacBook-Pro image_captioning %
```

```bash:Terminal
electron@diynoMacBook-Pro image_captioning % ls models                 
decoder-2-1000.ckpt	decoder-5-3000.pkl	encoder-2-1000.ckpt	encoder-
```

###モデルを指定して、実行してみる

結論として、どのモデルをしした場合も、今回読み込ませた画像については、出力される文に違いは見られませんでした。

![スクリーンショット 2021-08-07 21.43.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1754134/4f3ca07b-d4be-6117-1125-9aa760e0d049.png)

```bash:Terminal
electron@diynoMacBook-Pro image_captioning % python3 sample.py --image='png/test003.jpg' --encoder_path='models/encoder-2-1000.ckpt'
<start> a group of people standing around a table with a frisbee . <end>
electron@diynoMacBook-Pro image_captioning %
```

```bash:Terminal 
electron@diynoMacBook-Pro image_captioning % python3 sample.py --image='png/test003.jpg' --encoder_path='models/encoder-2-1000.ckpt' --decoder_path='models/decoder-2-1000.ckpt'
<start> a group of people standing around a table with a frisbee . <end>
electron@diynoMacBook-Pro image_captioning %
```

```bash:Terminal 
electron@diynoMacBook-Pro image_captioning % python3 sample.py --image='png/test003.jpg'                                                                                        
<start> a group of people standing around a table with a frisbee . <end>
electron@diynoMacBook-Pro image_captioning % 
```