Macで画像データセットを作成する

ディープラーニングで自分で用意した画像を使用したい場合、データセットとして用意する必要があります。その際のシンプルなポイントをまとめます。多くのみなさんがMacで作業を行なっていると思いますが、Macでこれを行う場合には落とし穴があるので、Macでの作業を前提に記載します。

###1. 画像の用意
####1.1. 画像はjpg形式で用意しましょう。
png等の形式でも可能ですが、データセットの大きさが無駄に大きくなるのでjpgが妥当です。jpgで遜色はありません。
####1.2. ファイル名と拡張子は小文字で統一しましょう。
実際に大文字を含むとデータ処理に不都合が生じるわけではありませんが、小文字に統一しておいたほうがデータ処理時のコードを読んだ時にスムーズに見えます。
####1.3. サイズは最大480px程度またはそれ以下にしましょう
Macで画像を一括で「縦または横の最大寸法を480pxにリサイズ」するには、サイズ変更する画像があるフォルダにcdで移動して下記のSIPS(Scriptable Image Processing System) コマンドを使います。

```
sips -Z 480 *.jpg
```
####1.4. フォルダ構成
上記で作成した画像は下記のようなフォルダ構造の「LabelName-n」フォルダに分類して入れます。「LabelName-n」は具体的には「犬」「猫」のような分類（ラベル）です。この分類名が一般的にはそのまま画像の分類属性として使われます。このフォルダ名も小文字で統一しましょう。

DatasetName
├ LabelName-1
├ LabelName-2
├ LICENSE.txt

なお、データセットの中には複数のラベルがなくても問題ありません。犬だけの画像データセットを作りたければフォルダがひとつでも問題ありません。しかし、そのデータをテンソルに変換して扱う際、生成されるテンソルは値が０の要素を多分に含む（スパース行列という）ことになるので、例えば下記のようにモデルをコンパイルする際にエラーが出ることがあります。

```python
model.compile(optimizer=tf.train.AdamOptimizer(), 
              loss=tf.keras.losses.categorical_crossentropy,
              metrics=["accuracy"])
```
このようなスパース行列を学習データとして用いるケース向けに損失関数が別に用意されているので

```python
model.compile(optimizer=tf.train.AdamOptimizer(), 
              loss=tf.keras.losses.sparse_categorical_crossentropy,
              metrics=["accuracy"])
```

のように「sparse_categorical_crossentropy」を使います。

###2. 画像のライセンス
データセットを作る上では必須ではありませんが、データセットに含まれる画像の著作権を明記することが一部で推奨されています。例えば、グーグルが公開するデータセットには「LICENSE.txt」と言うファイルがデータセットに含まれています。「LICENSE.txt」に記載する情報フォーマットは下記の通り。

```
All images in this archive are licensed under the Creative Commons By-Attribution License, available at:
https://creativecommons.org/licenses/by/2.0/
The photographers are listed below, thanks to all of them for making their work available, and please be sure to credit them for any use as per the license.

LabelName-1/SampleImage-11.jpg CC-BY by NameOfCopyrightHolder - https://CopyrightHolder.com/
LabelName-1/SampleImage-12.jpg CC-BY by NameOfCopyrightHolder - https://CopyrightHolder.com/
LabelName-2/SampleImage-21.jpg CC-BY by NameOfCopyrightHolder - https://CopyrightHolder.com/
（以下同様に続く）
```
各行に「各画像ファイルへのパス」、「著作権者の名前」、「その画像の元URL」が記載されて、このデータセットが実利用時に読み込まれた際には「各画像ファイルへのパス」と「著作権者の名前」「その画像の元URL」を紐つける形で著作権情報の表記に利用できるようにしています。
このような記述を一気に生成するには、下記のようなシェルスクリプトを作って自動で生成すると楽です（ざっくりイメージです）。

```bash
#!/bin/bash

DIR=/Volumes/TensorFlow/Datasets/DatasetName/LabelName-1

for pathfile in $DIR/*.jpg; do
    echo "${pathfile} CC-BY by NameOfCopyrightHolder - https://CopyrightHolder.com/"
done
```

###3. データセットの圧縮
####3.1. リソースフォークを除外して圧縮
データセットは圧縮せずに置いておいても普通に使えますが、圧縮しておいた方が複数回の再利用には便利です。Macのコマンドでtarを使ってシンプルに「tar zcvf DatasetName.tar.gz DatasetName」とtar.gzファイルを生成すると、MACが自動的に生成し非表示ファイルにしている「.DS_Store」「._Filename」のような「リソースフォーク」と呼ばれるファイルが勝手に含まれてしまいます。このリソースフォークが含まれた状態で作成されたデータセットをDeepLearningの学習過程に用いるとTensorFlowはエラーを起こします。これを避けるためには下記のようにリソースフォークを除外することを明示的に指示して圧縮することがポイントです。

```bash
env COPYFILE_DISABLE=1 tar zcvf DatasetName.tar.gz --exclude ".DS_Store" DatasetName
```

####3.2. tar.gzか？tgzか？
tarにzオプションをつけて圧縮（実際はアーカイブ）すると、まずtarアーカイブを生成してからgunzipで圧縮します。その際の生成物の拡張子はコマンドライン内で指定（上記の例では.tar.gz）しますが、拡張子は「.tar.gz」と「.tgz」のどちらにすべきなのでしょうか？答えは「どっちでもいい」です。

###4. 作ったデータセットの確認

作ったデータセットが正常に読み込まれるか確認するには、下記のようにどっか（この例ではyourserver.com）に作成したDatasetName.tar.gzを置いて「tf.keras.utils.get_file()」を使って取得し、正常に展開されるかどうかを見てみると、クイックに最低限のチェックはできます。

```python
import tensorflow as tf
tf.enable_eager_execution()
tf.__version__
import pathlib

data_root = tf.keras.utils.get_file('datasetname','https://yourserver.com/DatasetName.tar.gz', untar=True)

for item in data_root.iterdir():
    print(item)
```

実際にはデータをテンソルに変換したり、実際にモデルに流し込む際に問題が発生する場合があるので、最終確認は実際に使用して行いましょう。