僕(24歳)「レタスとキャベツの違いが分からないっ！！！」


#0.レタスとキャベツ

そもそもずっと野菜が嫌いだった僕は、**レタス**と**キャベツ**の違いを大人になるまで分からないで生きてきた。
今でも時々スーパーで野菜を見かけて、どっちが**レタス**だっけ...どっちが**キャベツ**だっけ...となってしまう。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661133/c1b61f14-293c-c57f-b4e1-142f1462ccb8.jpeg" width="400"><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661133/44202fb3-0b0a-6920-8074-9b54f7f6f903.png" width="400">

<hr>

僕くんと彼女は付き合って3ヶ月、半同棲をしながら楽しい日々を過ごしていた。
そんなある日...


彼女「今日の夜ごはんは僕くんの大好きな餃子にするよ！」
彼女「ん...**キャベツ**を切らしてるわ...！僕くん、買ってきてくれないかしら。」

僕「（餃子は好きだけど**キャベツ**入れちゃうのかぁ…しょうがないか…）」
僕「分かったよ～。」


僕「いやぁ...餃子は美味しいんだけどキャベツかぁ。近くのスーパーに買いに行くか～。」


#1.スーパーへ向かう僕くん

僕「ん...待って...**キャベツ**ってどういう形だっけ...**レタス**って...買ったことも見たことも見たくも無いけど！！！」
僕「彼女ちゃんに聞こうか...いや、そんな事したら**キャベツ**と**レタス**の違いも分からない恥ずかしい男だと思われてしまう...」

僕「どうしよう...どうしよう...」

大谷「あれ、僕くん・・？？」


僕「大谷くん！！！久しぶりだね！！」

大谷「僕くんも久しぶりだね！何か困っているようだけどどうしたの？？？」

僕「いやぁ実は・・・」

#2.大谷との再会

大谷「なるほど・・・**キャベツ**と**レタス**の違いか・・・残念だけど僕も分からないんだ・・・」

僕「そうだよね。**キャベツ**と**レタス**ってそっくりで分からないよね・・・！どうしよう。」

大谷「大丈夫だよ。科学が進歩した21世紀では僕くんの悩みを解決してくれるツールがたくさんあるんだ」

僕「！？！？詳しく聞かせてよ大谷くん！！！」

大谷「任せて！とりあえずパソコンが必要だから家に来て！」

<hr>

僕「さて、どうすればいいんだい。レタスとキャベツの違いなんてパソコンで調べられるのかい？」

大谷「僕くんは**TensorFlow**って聞いたことあるかな？」

僕「**TensorFlow**・・・？？？？」

大谷「**TensorFlow**はね、Googleが開発しオープンソースで公開している、機械学習に用いるためのソフトウェアライブラリなんだよ。」
>wikipediaより引用 https://ja.wikipedia.org/wiki/TensorFlow

僕「つまりよく分からないんだけど、とりあえずレタスとキャベツの違いが分かるんだね？」

大谷「そういう事だよ！とりあえず時間も無い事だから、始めよう！」
大谷「まずは環境構築だ！とりあえずAWSのEC2にインスタンスを作ろう。」

#3.初めてのTensorFlow

大谷「Amazon Linuxの標準AMIを使ってもいいんだけど、python系のライブラリはバージョンの互換性で上手くいかない事が多いから、今回は**Anaconda**のAMIを使っちゃおう！」
![gdshhtr.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661133/152eb407-2a29-fa00-75ce-66467da3c3a0.png)

僕「**Anaconda**...？なんか蛇みたいだね...」
大谷「**Anaconda**は、 科学計算のためのPythonおよびR言語の無料のオープンソースディストリビューションであり、パッケージ管理とデプロイメントを簡略化することを狙ったものである。パッケージのバージョンは、パッケージ管理システム conda によって管理されているんだよ！」
>wikipediaより引用 https://ja.wikipedia.org/wiki/Anaconda_(Python%E3%83%87%E3%82%A3%E3%82%B9%E3%83%88%E3%83%AA%E3%83%93%E3%83%A5%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3)

僕「う～んよく分からないけど、今回は急いでいるから説明はまた次の記事にしよう！！」
大谷「そうしよう。説明してるとスーパーが閉まっちゃうよ！」

僕「大谷くん、インスタンスのサイズはいくつがいいの？」
大谷「機械学習で使うインスタンスは、webサービスとかと違って常に起動しておく必要もないし、瞬間的なスペックが求められる事が多いから、高めのインスタンスを起動さえちゃう！」
僕「うへぇ・・・切り忘れに気を付けないとだね・・・」

大谷「とりあえずインスタンスが起動したら、インストールされている**conda**と**python**のバージョンの確認をしよう」

```bash
[ec2-user@ip-***-***-**-** ~]$ conda info

     active environment : base
    active env location : /opt/conda
            shell level : 1
       user config file : /home/ec2-user/.condarc
 populated config files :
          conda version : 4.8.3
    conda-build version : 3.18.11
         python version : 3.7.6.final.0
       virtual packages : __glibc=2.17
       base environment : /opt/conda  (writable)
           channel URLs : https://repo.anaconda.com/pkgs/main/linux-64
                          https://repo.anaconda.com/pkgs/main/noarch
                          https://repo.anaconda.com/pkgs/r/linux-64
                          https://repo.anaconda.com/pkgs/r/noarch
          package cache : /opt/conda/pkgs
                          /home/ec2-user/.conda/pkgs
       envs directories : /opt/conda/envs
                          /home/ec2-user/.conda/envs
               platform : linux-64
             user-agent : conda/4.8.3 requests/2.22.0 CPython/3.7.6 Linux/4.14.186-110.268.amzn1.x86_64 amzn/2018.03 glibc/2.17
                UID:GID : 500:500
             netrc file : None
           offline mode : False
```

僕「どこを見ればいいの！？」
大谷「とりあえず**conda**と**python**のバージョンさえ把握してれば大丈夫だよ。今回は**conda**が4.8.3で**python**が3.7.6だね。」

大谷「じゃあ早速**Tensorflow**をインストールしよう！」

```bash

[ec2-user@ip-***-***-**-** ~]$ conda create -n tensorflow python=3.7.6
```

大谷「インストールが始まったね。」
大谷「途中で警告や、(y/n）が出る事があるけど、スーパーが閉まっちゃうから適当にyを入れてエンターで進めちゃおう！」

僕「（大丈夫かな大谷くん・・・）」

大谷「次にtensorflowをアクティベートして、本体のインストールをしよう！」

```bash

[ec2-user@ip-***-***-**-** ~]$ conda activate tensorflow
(tensorflow)[ec2-user@ip-172-31-25-43 ~]$ pip install tensorflow
(tensorflow)[ec2-user@ip-172-31-25-43 ~]$ pip install tensorflow-hub
```

大谷「全部終わったら、学習のための画像を集めよう！今回だったら**キャベツ**と**レタス**の画像をたくさん探してきて！」
僕「分かった！じゃあキャベツとレタスの画像を検索して1枚ずつ保存して、メールで大谷くんに送るね！」

大谷「それもいいけど、ちょっと時間が掛かるから、今回はGoogle画像からクローリングして集めようか！」
大谷「下の記事を参考にクローリングするためのスクリプトを作ろうか」
>「API を叩かずに Google から画像収集をする」
>https://qiita.com/naz_/items/efc296ae1bf0e62f6704

大谷「ただしSSLが通らない場合があるから、google画像のURLの**https**を**http**にしておくとスムーズにクローリングが進むかもしれないよ！」

僕「ほえー・・・」

大谷「じゃあ画像を集めようか！」

```bash
[ec2-user@ip-***-***-**-** ~]$ python image_collector.py -t キャベツ -d /tmp/retakyabe/ -n 1000
```
大谷「とりあえず**キャベツ**の画像をたくさん集めよう！」

＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿


大谷「キャベツの画像が767枚集まったね！次にレタスの画像を集めようか！」

```bash
[ec2-user@ip-***-***-**-** ~]$ python image_collector.py -t レタス -d /tmp/retakyabe/ -n 767
```
大谷「この時、画像の枚数が同じくらいになるように-nを調整しておくと、いい結果が出やすいかもしれないよ！」

大谷「それと、終わったら**レタス**と**キャベツ**っていう名前のフォルダが出来てると思うんだけど、日本語名だと読み込みに失敗する事があるから、それぞれアルファベット名に名前を変えておこう！」

```bash
[ec2-user@ip-***-***-**-** ~]$ mv /tmp/retakyabe/レタス/ /tmp/retakyabe/retasu/
[ec2-user@ip-***-***-**-** ~]$ mv /tmp/retakyabe/キャベツ/ /tmp/retakyabe/kyabetsu/ 
```
＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿

僕「大谷くん・・・ようやく画像を集め終わったみたいだね・・・」

大谷「そうだね！ここからは学習をさせていこうか！」
大谷「本当はここに血と汗を流して、戦う時間が掛かるんだけど、僕くんはスーパーに急いでいるから今回は画像分類のチュートリアルによく使われるretrain.pyをお借りしようか！」
https://raw.githubusercontent.com/tensorflow/hub/r0.1/examples/image_retraining/retrain.py

大谷「これをそのままEC2に落としちゃおう！」

```bash
[ec2-user@ip-***-***-**-** ~]$ wget https://raw.githubusercontent.com/tensorflow/hub/r0.1/examples/image_retraining/retrain.py
```

大谷「あとはあらかじめ画像がフォルダで分けてあるディレクトリを指定してあげて、retrain.pyを呼んであげよう！」

```bash
[ec2-user@ip-***-***-**-** ~]$ python retrain.py --image_dir /tmp/retakyabe
```

大谷「この時、気を付けて欲しいのはクローリングして保存した画像だから、jpg以外の形式だったり、内部的にファイルが他の形式になっている場合があるから、その時は個別にそのファイルを削除しなきゃいけないんだ！」

僕「そうなんだ！大谷くんは頭がいいね。勉強になるよ！」

大谷「学習はいくらスペックが高くても時間が掛かっちゃうからね。待ってる間はゲームでもしようか！」

<hr>

大谷「さて、学習が終わったみたいだね。」
僕「ここからはどうすればいいの？」

大谷「まずはtensorboardで学習の結果を確認してみようか！」
僕「tensorboardってなんだい大谷くん？」

大谷「tensorboardはTensorFlowの訓練の結果や過程を視覚的に確認する事が出来るツールなんだ」
大谷「まずは見てみようか」

```bash
[ec2-user@ip-***-***-**-** ~]$ tensorboard --logdir /tmp/retrain_logs
```

大谷「EC2で起動しているローカルサーバーをクライアント側から見る時は、インバウンドでポートを開けておいて、SSHでトンネルをしておくと楽だね！」

```bash
 ssh -i ローカルのpem -NL 6007:localhost:6007 ec2-user@3.21.228.144
```

大谷「IPやポートやpemのディレクトリは自分の環境のものを入れようね。」
大谷「あとはブラウザでlocalhost:6007へつなげば・・・」

![hrtjtyjt.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661133/7fd0f0e1-855e-626d-c8eb-a851240f255e.png)

僕「よくわからないけどすごい・・・！」

![gerjtrtr.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661133/cbb1c1c3-aacb-a1f9-6dbd-361c90cb9c71.png)

大谷「こんなデータだったり、色々な形で訓練を可視化することができるんだよ！」

僕「詳しい人がきっとたくさん解説してくれてるよね・・・！！！僕はスーパーに急がなきゃ！」

大谷「じゃあ早速スーパーへ行って、今訓練したデータでキャベツとレタスを判別しよう！」

#4.スーパー

僕「ふぅ。野菜売り場についたけど、やっぱりキャベツとレタスが横に並んでいて分からない・・・」
僕「しかもよりによって、隣に置いてあるし、なぜか値札も付いていないからどっちかキャベツか分からない・・・」

大谷「任せて、僕くん！」
大谷「スマホでそのキャベツかレタスかどっちか分からない野菜の画像を送るんだ！」

大谷「学習した画像の判別にはlabel_image.pyを使おう」
https://github.com/tensorflow/tensorflow/raw/master/tensorflow/examples/label_image/label_image.py

大谷「今回はTensorFlow2を使っているから、importの部分を書き換えて・・・」

```python
import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()
```

![5156115.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661133/3bd091f0-0696-ee21-5636-20b2f183d45f.jpeg)

大谷「あとはこの画像をEC2に送って・・・」

```bash
[ec2-user@ip-***-***-**-** ~]$ python label_image.py --graph=/tmp/output_graph.pb --labels=/tmp/output_labels.txt --input_layer=Placeholder --output_layer=final_result --image=yasai.jpg
```

```bash
-- 出力
kyabetsu 0.99413127
retasu 0.005868726
```

大谷「つまりこの野菜は99.4%の確率でキャベツだということだ！」
僕「すごい！！！」

僕「もう1個の野菜でも試してみよう！！！」

![yasai2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661133/4e422756-c2c2-9fea-cb06-b35a6804e274.jpeg)

```bash
[ec2-user@ip-***-***-**-** ~]$ python label_image.py --graph=/tmp/output_graph.pb --labels=/tmp/output_labels.txt --input_layer=Placeholder --output_layer=final_result --image=yasai2.jpg
```

```bash
-- 出力
retasu 0.9640751
kyabetsu 0.03592493
```

僕「すごいよ大谷くん！！この野菜は96.4%レタスなんだよ！」
大谷「レタスとキャベツのように、人間でも間違える事があるようなものでも、TensorFlowなら、こんな簡単にわかるんだよ！」

僕「ありがとう大谷くん！これで家にキャベツを買って帰れるよ！」


#5.帰宅

僕「ただいま！！TensorFlowでキャベツ買ってきたよ！！！」
僕「あれ...彼女は...！？！？」

書き置き
「3日経っても帰ってこないので、出ていきます さようなら」


僕「そ、そんなぁ～～～～。。。もう3日も経っていたの！？！？」



「機械学習には時間が掛かるのであった」
              終わり

<hr>

※割とバージョンと環境によって、左右される面が強いので何かあれば調べるか、コメントしてください。
以前書いた記事も良かったら見てください。
「猿には分からないけど、非エンジニアでも分かると思う、ドメイン駆動設計の「ド」の字くらいだけ説明する」
https://qiita.com/ryoya1122/items/502c07410197746e79e4