efficientnetで学習させてみる
efficientnetのコードはこちらで公式に公開されている
これを使ってcolaboratory上で学習を試してみたのでメモ
データセット準備
以下のスクリプトを使えば画像をtf_record化してgcsへuploadできる
このスクリプトで想定しているdatasetのディレクトリ構造はこういう形。trainはlabel名のディレクトリ毎に分かれているが、validationはすべてのファイルが直下に入っているので注意。
dataset ├── train │ ├── labelA │ │ └── IMG_20170309_023302.JPEG │ └── labelB │ └── IMG_20170401_102412.JPEG └── validation ├── IMG_20170923_172045.JPEG └── IMG_20170924_095022.JPEG
ちなみに画像名は拡張子が.JPEGになってればOK(以下で拡張子を直に指定しているので) 手元の画像の拡張子が.jpgとかだったら、ここを書き換えるだけでちゃんと動く
また、validation直下のファイル名を辞書順にsortして並べたsynset_labels.txtというファイルが必要なため以下のコマンドで作成
$ ls dataset/validation | sort > dataset/synset_labels.txt
スクリプトの実行コマンドはこちら どうやらpython2系で動かすことを想定しているらしくpython3.6で動かしたらエラーが出たため、dockerを使ってpython2系で動かした
$ cd <path/to/tpu repo> $ docker run -v `pwd`:/root -w /root -it tensorflow/tensorflow:1.14.0 bash -c "python /root/tools/dataset/imagenet_to_gcs.py --raw_data_dir /root/dataset --local_scratch_dir /root/tf_records --nogcs_upload" $ gsutil -m cp -r tf_records/train/train-* gs://<bucket name>/dataset/tf_records/ $ gsutil -m cp -r tf_records/validation/validation-* gs://<bucket name>/dataset/tf_records/
上記を実行するとtf_recordsというディレクトリができてその中に元の画像をtf_records化したものが生成される また、dockerだとgcloudの設定がめんどそうだったので、--nogcs_uploadを指定して一旦ローカルに生成してからgsutilを使ってuploadするようにした(gsutil -mで並列にuploadした方が早いというもある)
imagenet2012の場合150Gを1024に分けてtf_record化しているので、一つあたり150M程度の大きさになる。 自前のデータセットが小さいものである場合、一つあたりのサイズが小さくなりすぎるかもしれないので、その場合は以下の設定を変えて調整
ちなみに私は一つあたり10M程度でやってみたが特に問題なかった。
学習
学習のエントリーポイントはこちらのスクリプト
google公式であるためもちろんtpuで学習できる。 デフォルトの設定値はmain.pyの引数設定に書いてあるもので、imagenet2012のデータセットを350epochまわすようになっている模様
以下で学習開始できるが、自分のデータセットの大きさに合わせてstep数などを調整する
# GCSへのアクセス権取得 from google.colab import auth auth.authenticate_user() # 学習用環境準備 !git clone https://github.com/tensorflow/tpu.git !export PYTHONPATH="$PYTHONPATH:/content/tpu/models" %cd tpu/models/official/efficientnet/ !git checkout 7e0ad3aabe888ce25599c5d9cbd804e99714f060 # 私が試したときのcommit # 学習実行 TPU_ADDRESS="grpc://"+os.environ["COLAB_TPU_ADDR"] !python main.py \ --tpu=$TPU_ADDRESS \ --model_name='efficientnet-b0' \ --skip_host_call=true \ --data_dir=gs://<bucket name>/dataset/tf_records \ # uploadしたtf_recordsが存在するディレクトリ --model_dir=gs://<bucket name>/dataset/model \ # これは学習時の出力ディレクトリの設定なので任意の場所でOK --num_label_classes=100 --num_eval_images=10000 --num_train_images=100000 --train_batch_size=2048 --eval_batch_size=1024 --train_steps=17090 --steps_per_eval=488 --iterations_per_loop=244
上記の設定は
- 100クラス
- trainingデータ10万件
- validationデータ1万件
- 合計350 epoch、10 epoch毎にvalidation
の場合のもので、計算は
- train_steps = 100000 / 2048 * 350
- steps_per_eval = train_steps / 35
iteration_per_loopはcheckpointの保存間隔の設定で今回は5epoch毎にしてある
steps_per_evalとiteration_per_loopはなるべく大きい値にしておく方が早い(tpuの処理を中断する回数が減るため)
ちなみに10GB程度のデータセットで試してみたところ、学習時間は7時間程度だった
loss確認
loss、accuracyの確認にはtensorboardを使う。出力されたファイルの中にtensorboardのファイルがあり、そこにlossとtop1, top5 accuracyの推移が保存される。colaboratory上であれば以下のようにして出力できる。
# driveをmount from google.colab import drive drive.mount('/gdrive') # GCSからdriveへファイルをコピー !gsutil -m cp -r gs://<bucket_name>//dataset/model/eval "/gdrive/My Drive/" # tensorboardの表示 %load_ext tensorboard %tensorboard --logdir "/gdrive/My Drive/eval/"