Google ColabからDriveに大規模データをアップロードするときの注意

#はじめに
高専5年で画像処理系の卒業研究をしている弱い学生です。
GPUが手軽に使えて、時勢的に家からでも研究を進められるように[Colab](https://colab.research.google.com/notebooks/welcome.ipynb?hl=ja)を実行環境にしています。便利な時代になったなあ...

所謂機械学習云々をしているのでデータセットとして[COCO Dataset](https://cocodataset.org/#home)を用いているのですが、色々問題が発生したので書いておきます。少しでも参考になれば...

#起こった問題
いくつか問題が発生したので列挙していきます。
##その1：大規模ZIPが解凍できない
画像系に限らず、Web上で収集できる学習用のデータセットは大抵圧縮された状態でダウンロードするかと思います。
Colab上でデータセットのダウンロード・解凍をするのであれば、

~~~python
    #ドライブのマウント
from google.colab import drive
drive.mount('/content/drive')
    
    #URLから対象のファイルをドライブにダウンロード
!wget -P "/content/drive/My Drive/ダウンロード先のディレクトリ名" https://Dataset.No.URL
    #指定ZIPの解凍
!unzip "/content/drive/My Drive/ダウンロード先のディレクトリ名/filename.zip" -d "/content/drive/My Drive/解凍先のディレクトリ名"
~~~
という記述をすると思うのですが、ここで詰まったことが。

[train2017](http://images.cocodataset.org/zips/train2017.zip)(18GB,約12万ファイル)を解凍中、途中で*zipfile read error*を吐きました。（タイムアウトとは違うっぽい...？）
詳しいボーダーはわかりませんが、フォーラムをいくつか覗く限り、一度に扱えるファイル数は制限がある模様。自分も含め、**約15,000**くらいっぽいです。
かといってDriveにて対象ZIPを直接ZIP Extractorで解凍しようと試みてもエラーを吐きます。うーん。

###解決策
Colabにてファイルを扱うにはいくつか方法がありますが、セッションストレージ上にアップロードすることはランタイムリセット時に消滅してしまうため、あまり好ましくありません。
どうにかして最終的にはドライブにデータセットを揃えたいところです。

とりあえず無理やり感が強いですが、以下の流れでどうにかすべてドライブにアップロードできました。
####1. ローカルにてファイルを複数ディレクトリに分割
おそらく一度に処理できるファイル数は15,000程であるので、12万枚の画像ファイルを10個のディレクトリに分割して配置し、それぞれ圧縮してDriveにアップロードしました。
億劫だったので手動で行いましたが、githubでソースを上げている方がいたので、リンクを貼っておきます。※当方未検証のため要検証
　⇒[Unable to read file from a large folder (Input/output error) ](https://github.com/googlecolab/colabtools/issues/450)

####2. アップロードしたZIPをそれぞれ解凍
先に挙げたZIP解凍のソース通りです。出力先はデータセットを置いておきたいディレクトリの下とかでいいと思います。

####3. 解凍されたディレクトリ内部のファイルを統合
流石に /My Drive/Dataset とかの下にディレクトリが乱立しているのは面倒なので、中身だけまとめたいところ。Colabにて、

~~~python
import os
%cd "/content/drive/My Drive/dataset/001" #分割したデータセットファイルがまとまっているディレクトリ
!mv *.jpg "/content/drive/My Drive/dataset" #移動先
~~~
でまとめて上位の階層に中身を移動できます。なんとなく*.jpgで拡張子を指定して拾っていますが、ここはディレクトリの中身と相談するところです。

##その2：一気にファイルのやり取りを行うとDriveが死ぬ
Driveは仕様上、例えば1万枚の画像をColabでスクリプトを用いたりしてアップロードしたときに反映のラグが結構あります。**ランタイム上ではアップロード処理は完了しているのに、Driveをのぞくとファイルが見当たらない**...というのは結構ザラです。

そんなDriveへの反映がスタックしている中、さらに処理を続けたり、失敗したと思って再度アップロードのスクリプトを走らせる（本当はもうアップロードは済んでいるのに）と、やばいことが起きます。

<font color = "red">**指定したパスを無視して最上位ディレクトリにアップロードされる**</font>のです。
そしてさらに、
<font color = "red">**最上位ディレクトリにファイルがあふれた結果、Colabからのマウントを受け付けなくなる**</font>のです。
詳しく説明していきます。

###1. Driveへの反映・処理遅延について
一気にデータを動かそうとするとどうしてもDriveへの反映は遅くなります。処理が進んでいるのに失敗したと思って再度走らせたりした場合、パスの指定が無視されてDrive最上位の /content/drive/My Drive に中身がすべて展開されることがありました。

自分は2回ほど経験していて、2万超の画像ファイルがMy Drive直下に展開されました。泣きたかった。

###2. Driveへのマウント制限について
別にColabからコマンド使って一括で削除してしまえればそんなに苦しい話ではないのですが、Driveの仕様に阻まれました。
Driveのファイルをあれこれする場合、前述したスクリプトを用いてColabとDriveをマウントさせる必要があるのですが、以下の時、アクセスできないことがあるようです。

 - フォルダ内のファイル数やサブフォルダ数が増えすぎたとき
 - 「マイドライブ」直下に多量のファイルがあるとき
 - 既定のユーザー単位およびファイル単位のオペレーション数を超過したとき　など

⇒詳細：https://research.google.com/colaboratory/faq.html#drive-timeout

この中でも自分がぶつかったのが**"「マイドライブ」直下に多量のファイルがあるとき"**です。
前述の事象により、マイドライブは大量のファイルで埋め尽くされています。これにより、ドライブへのマウントが行えず、手作業で消去するにも量が多すぎるため、途方にくれました。

サポセンにチャットで問い合わせをし、ドライブ内の一括削除（初期化）をお願いしましたが行っていないとのことで、ひたすら手作業での消去がはじまりました。
（ドライブはShift+Aでファイルの全選択ができますが、表示件数と処理の都合により頑張っても1000枚くらいしか一気に消せない、しかもめっちゃ時間がかかる、そしてごみ箱の削除も時間がかかる、苦行）

###解決策
まずはこうならないように気をつけることが大事だと思いますが、起きてしまった場合の対応策を書いておきます。無理だったら手作業で消去です。つらい。

####1. ランタイム接続を解除せず、My Driveのファイル数の監視をする
Driveへの反映が遅いなと感じたら、反映が終わるまで待ってみるのが吉です。ただ、膨大な処理を実行していた場合、My Drive直下にファイルが生成されることがあるかもしれません。
そこで、実行後から反映までの間、事故ると再マウントできなくなるのでランタイムをリセットせず、

~~~python
%cd "/content/drive/My Drive"
import os
!echo | xargs ls | wc
~~~
というような感じでMy Driveのファイル数の推移を監視しておくことをおすすめします。

出力は↓のような感じ。

~~~
/content/drive/My Drive
      5       6      73
~~~

####2. My Drive下にある特定ファイルを一括消去する
仮にMy Drive下にめっちゃファイルを広げてしまったとしても、マウントが維持されていればrmを用いて一括での削除が可能です。

~~~python
%cd "/content/drive/My Drive"
import os
!rm ./*jpg #ワイルドカードで拡張子を指定
~~~

#さいごに
自分の備忘録的な側面もありますが、お役に立てれば幸いです。
初学者なので気になる点等あればお手柔らかに...