初Kaggle体験記

Kaggleのコンペを初めてやったので、その体験記。

参加したコンペは

結果は残念ながら、791/1304位(※現時点では未確定)ぐらい。

でも、初めてやったなりに面白かったので書きます。
機械学習初心者です。

概要

f:id:kocha2012:20181205164439p:plain

↑こんな感じでスコア遷移してました。

最高が0.8892だったので、公開Kernelより低いのでぉぃぉぃって感じですが
自分でやった際にはこんな感じでした。

やってきたトピックをあげるとすれば、以下のような感じです。
それぞれ書いていこうと思います。

  • 1.CPU メモリの壁
  • 2.GPU メモリの壁
  • 3.実行時間の壁

実行環境

自分の手持ちパソコンのスペックが低すぎて、時間制限あるなかでの無料枠トライでした。
(次回はパソコン買って出直すぞ)

1.CPU メモリの壁

初めてなので、Kernel見ながらやり方を学んでた。
CNNで判別しようと考えていたので、データは simplifiedのほうを選択して、
csv→suffle→imageという流れでtrainデータを作ろうとしていたらメモリオーバー。。。

判別が340種類で、1種類あたり10万を超えるデータ数でsuffleする前からアウトオブメモリ
Kernelや自分も試してみてだいたい、3万くらいが上限だった。
Kernelでは suffleして tar.gzにしているやり方があったけど今にして思えば真似しとけばよかったかなと。
その当時はGoogle Colabのほうがメインで、Kaggle Kernelで人のデータを使えることを知らなかった。

最終的には、1種類あたり1-2万のデータ(計340-640万)で学習させました。

2.GPU メモリの壁

モデルはMobileNet v2を使用。
当初、画像サイズ64x64で 1種類当たり500のデータをtrainデータへ
batchsizeは32
→ ココらへんが最初の頃の50%前後の遷移。。。

認識率が上がらないので、どうしたものかと思っていた。
施策として

  • データを変える
  • データを増やす
  • 画像サイズをを大きくする
  • batchsizeを増やす
  • モデルを変える

データを変える

データには「Recognized」というフィールドがあり、Trueでフィルタを変えたほうが良いというのがKernelに上がっていたので試した。
結果、あんまり変わらないかった。

データを増やす

trainデータ多くすると、メモリが溢れてしまった。。。

画像サイズを大きくする

trainデータ多くすると、メモリが溢れてしまった。。。

fit_generator との出会い

WebではClassを作るような記事が多かったが、私は関数のみで書いてた。

def data_generator():
  while True:
    #なんかしらのデータ生成
    yield x,y

model.fit_generator(generator=data_generator(), ...

これでbatchsize分だけ容量となり、画像サイズ:128x128, batchsize=256までいけるようになった。 (Kaggle Kernel)
→ 最高70%近くまで遷移

3.実行時間の壁

Kaggle Kernelは 6h
Google Colabは 12h?
と時間制限があるので、どうしても長時間学習することが難しかった。
(つらい)

Google Colab(TPU)

11/8 に参加した TFUG 福岡 #2 (2018/11/08 19:30〜) で、TPUについてあったので試してみた。
コメント部分は、TPUにするために書き直した部分。
Kerasからの変換は制限があるもよう。
fit時のcallbacksも指定なしにしないといけなかった。

# TPU
tpu_model = tf.contrib.tpu.keras_to_tpu_model(
    model,
    strategy=tf.contrib.tpu.TPUDistributionStrategy(
        tf.contrib.cluster_resolver.TPUClusterResolver(tpu='grpc://' + os.environ['COLAB_TPU_ADDR'])
    )
)

def top_3_accuracy(x,y): return keras.metrics.top_k_categorical_accuracy(x,y, 3)

tpu_model.compile(
#    optimizer=tf.keras.optimizers.Adam(lr=0.002),
    optimizer=tf.train.AdamOptimizer(learning_rate=0.002, ),
    loss=tf.keras.losses.categorical_crossentropy,
#    metrics=['accuracy', top_3_accuracy]
    metrics=['accuracy']
)

TPUにしたことで、画像サイズも256x256にできbatchsizeも1024まで増やせた。
(今思うと画像サイズそこまで必要だったかは不明)

そのおかけで、認識率は 80%以上を超えて、90%近くまでいった。
それ以降、3epochぐらい実行するとcolabが再接続するという謎の現象にあってしまいスコアあがらず。。。

過学習にもなってきて、どうしたものかと思って試したのが、
ImageDataGenerator

教師データを水増ししてなんとかならないかと。。。
data_generatorに埋め込んだ。

datagen = ImageDataGenerator(
    rotation_range=20,
    width_shift_range=0.2,
    height_shift_range=0.2,
    horizontal_flip=True)

def data_generator(batchsize):
  #なんかのコード
  for img in datagen.flow(x, batchsize=batchsize)
    

結果は後半の劣化の結果となってしまった。
Google Colabで再接続が頻繁に起こらなければ。。。と思いつつ無念な結果に。

やってた状況は 昼間はKaggleやれず、作業は夜のみで夜投入して朝確認の繰り返しだったので 途中エラーや再接続とかなると1日がパァーになった。

まとめ

  • Kaggle楽しい
  • KernelやDiscussion読んでて色々ためになった
  • 自分で環境揃えないと厳しい><
  • fit_generator 良い
  • ImageDataGenerator 楽
  • 高スコアのモデルや手法を知りたいので暫く待とう
  • Kaggleも昼間にやれる職に変えたい

次回、別コンペでリベンジです!