Github コードアドレス: https://github.com/HansRen1024/Tensorflow-preprocessing-training-testing
** すべてのコードは Github から取得してください、ファイル名を対応させてください。 **
** TF バージョンは少なくとも 1.4.0 です。 **
**MonitoredTrainingSession に関する情報は非常に少なく、公式 API とソースコードを長い間研究しました。 **
** 2018.04.13 更新 SSD 単機トレーニング + テストコード: https://github.com/HansRen1024/Tensorflow-SSD
**
2018.03.16 更新 可視化コードを追加
2018.03.19 更新 デバッグコードを追加
2018.03.20 更新 平均値を除去し、正規化コードを追加
2018.03.21 更新 mobilenet と mobilenet v2 ネットワークモデルを追加
2018.03.22 更新 resnet-50, **resnet-101, **resnet-152, resnet-200 **
** ネットワークモデル
実行時に GPU メモリが満杯になる問題を解決しました(単機ではうまくいきますが、分散環境ではうまくいきません)
2018.03.23 更新 GPU を選択
** 2018.03.26 更新 検証段階を追加し、tensorboard で train と val 段階の loss を同時に監視できるようにしました
**
** ** 2018.03.29 更新 finetune 機能を追加しました
** ** 2018.04.02 更新 可視化効果を最適化し、計算ステップの方法を再設定しました。
** ** 2018.04.09 更新 分散環境下で同期・非同期トレーニングスイッチを追加し、MonitoredTrainingSession を再実装しました
** ** 2018.04.10 更新 カスタムの i または step を global step に置き換え、ログ出力の不一致問題を解決しました
2018.04.11 更新 非同期トレーニングで最後のイベント記録が失敗する問題を解決しました
前書き#
新しいビジネスで分散クラスターを構築する必要があり、以前は caffe を使用していましたが、今は Tensorflow を使用する必要があります。
ネット上には公式デモをそのままコピーしたものがほとんどで、データの読み込み処理からトレーニング、テストまでの詳細な説明がある記事はありません。私が書きます。
一、データセットの準備#
以前は caffe を使用しており、データセットは異なるディレクトリに分類されていました。ここで 2 つのスクリプトを公開します、それぞれの機能は説明を見てください。
スクリプト 1(img2bin.py)はこの使用をお勧めしません、後続の更新がありません:
classes は images ディレクトリ内の各データセットのディレクトリ名です。
img=img.resize ((227,227)) ネットワーク構造に応じて resize サイズを選択する必要があります。
このスクリプトは images ディレクトリと同じ階層にあり、images ディレクトリ内には「0」、「1」、「2」という 3 つのディレクトリがあり、それぞれ 3 つのカテゴリのすべての画像データセットが格納されています。最後に「train.tfrecords」という名前のバイナリファイルが生成されます。
スクリプト 2(list2bin.py):
最後に一組の bgr 三チャネル平均を印刷し、トレーニングセットの平均を記録し、arg_parsing.py に配置して平均除去操作に使用します。
必ず RGB 三チャネルに変換してください、さもないと後のデータ読み込みで問題が発生します。
以前 caffe を使用していたとき、最初に txt 文書を生成する習慣があり(形式は以下の通り)、その後文書に基づいて lmdb データセットを生成しました。
スクリプト 2 はこの txt 文書に基づいて tfrecords バイナリデータセットを生成します。
txt 文書を生成するスクリプトのブログアドレス(Github のimg2list.sh):
【Caffe】自分のデータをトレーニングするための迅速なスタート《Caffe について真剣に話す》
コードはデータセットの準備の中で train.txt と val.txt を生成する.sh スクリプトです。
2 番目のスクリプトを書くのは、トレーニング段階で val の出力を基にトレーニングプロセスが正しいかどうかを判断するための習慣です。 しかし後にいくつかの理由で、トレーニング段階で val を行うことができませんでした。さらに研究が必要です - 0-。
二、構成準備段階#
上記で生成した.tfrecords バイナリデータセットを取得したら、環境を整えてトレーニングを開始できます。
コードが多いため、説明はコード内に記載しますので、見やすくなります。正直、多くの tf の API も理解できていませんが、今はただ動かすことができました。今後も多くの時間をかけて学習研究する必要があります。
文書 1(arg_parsing.py):
この文書は主に実行入力パラメータを設定するためのもので、理解しやすいです。コード内で大文字の文字の後ろのデフォルトパラメータを変更することも、コマンドラインでパラメータを指定することもできます。
文書 2(dataset.py):
データを読み込み、平均を除去し、正規化し、ネットワークに入力するために一つのバッチに統合します。
文書 3(main.py):
コマンドラインで実行する文書で、内容は非常にシンプルです。
if tf.gfile.Exists(FLAGS.model_dir):
#コメントの 3 行は models ディレクトリを空にし、このディレクトリがない場合は作成します。誤操作を防ぐために、私はこの 3 行をコメントアウトしました。
文書 4(net/squeezenet.py):
ネットワーク構造文書で、別に書き出しておくと、将来的にネットワーク構造を変更するのが便利です。
私のは squeezenet ネットワークで、公式デモでは 3232 データセットしか処理できませんが、私は変更しました。今このネットワークは正常に 227227 を処理できます。
network.py は見るだけで、後に私が捨てて更新を停止しました。
文書 5(test.py):
テスト用の文書です。
文書 6(train.py)
トレーニング文書で、3 つのトレーニング方法があります。最も疲れた文書です、面倒です~~~。
train ():# 単機単カード + 単機多カード共通トレーニング方法。
train_dis_():# 使用可能な分散多機多カード。
train.py についてはもう少し言いたいことがあります。
1. セッションについて、一般的には tf.Session () を使用します。ここでは tf.train.MonitoredTrainingSession () を使用しています。これは公式 API の推奨と cifar-10 デモでの使用を見たからです。このインターフェースのhook部分は非常に便利で、いくつかの機能を柔軟に定義して使用できます。公式 API 文書では、ほとんどすべての hook がここで使用できます。例えばデバッグ、サマリーなど、研究する価値があります。(
2018.03.23
この MTS マネージャーを通じて検証段階を追加するのは非常に難しいです。共有パラメータを使用して検証する場合、問題は主に global_step の競合です。ローカル ckpt を読み込む場合、ckpt を保存する頻度と検証の頻度をバランスさせるのが難しいです。
)
なぜトレーニングを開始するとすべての GPU のメモリがすぐに占有されるのか理解できません。batch_size を 1 に設定しても 32 でも 64 でも結果は同じです。したがって、val を実行すると GPU メモリ不足のエラーが発生し、しばらくするとマシンがフリーズします - 0-。この問題は後でゆっくり解決しましょう~
3.3 番目の train_dis () メソッドは同期または非同期を制御できますが、少し問題があります。急いでプロセスを通過させるために気にしませんでした。後で時間があれば見ます。
4.2 番目の train_dis_() は使用可能な分散多機多カード方法で、私はそれが非同期であると判断しています。
5.CUDA_VISIBLE_DEVICES=0,1 という文を使用して特定の GPU を制御できます。または main.py に以下の文を追加して設定できます。
三、トレーニング段階の配置#
第一の状況(単機単カード、単機多カード):
main.py で呼び出す train の方法とパスを設定し、直接実行します:
python main.py
デフォルトではトレーニングモードです
第二の状況(多機多カード):
コマンドラインで --job_name を指定するだけで、自動的に分散トレーニングが実行されます。
すべての文書とデータセットをそれぞれのサーバーに分配する必要があります。
例えば、私には現在 2 台のサーバー 10.100.1.151 と 10.100.1.120 があります。
私は 151 サーバーを同時に ps と worker として使用し、
120 サーバーを worker として使用します。
まず arg_parsing.py で ps_hosts と worker_hosts を設定し、カンマで区切り、スペースを入れないでください。
次に 151 サーバーで実行します:
CUDA_VISIBLE_DEVICES='' python src/main.py --job_name=ps --task_index=0
ここで CUDA_VISIBLE_DEVICES='' は GPU を使用しないことを示します。パラメータサーバーとして CPU で処理できます。
次に、151 サーバーで続けて実行します:
CUDA_VISIBLE_DEVICES=0 python src/main.py --job_name=worker --task_index=0
最後に 120 サーバーで実行します:
CUDA_VISIBLE_DEVICES=0 python src/main.py --job_name=worker --task_index=1
CUDA_VISIBLE_DEVICES を使用して有効にする GPU を設定できます。シーケンスはカンマで区切ります。
四、テスト#
特に多機多カードでは、index が 0 のホストでのみ ckpt が保存されることを特に指摘します。
テストセットの.tfrecords を準備し、パスを設定し、コマンドラインで実行します:
python main.py --mode=testing
テストモードを指定する必要があります。
後記#
コマンドラインパラメータを研究してみてください。多くありますが、すべて非常にシンプルです。
今後も継続的に更新していきます。。。
1. 同期・非同期(2018.04.09 完了)
2. 平均除去、正規化(2018.03.20 完了)
3. 可視化(2018.03.16 完了)
4. デバッグ(2018.03.19 完了)
5. 検証(2018.03.26 完了)
-
GPU メモリが常に占有される問題について(2018.03.22 完了)
-
さらに多くのネットワークモデル文書の準備(2018.03.19 mobilenet、2018.03.22 resnet)
-
GPU の選択(2018.03.19 完了)
-
可視化のネットワーク構造図の最適化(2018.04.02 完了)
10.Finetune(2018.03.29 完了)
11. 新しい問題、ネット上で解決策が見つかりませんでした。非同期分散トレーニングが完了した後、最後のイベント記録が失敗します。これは、index=0 のホストが run_context.request_stop () を実行する際に、他のマシンが検証段階にいる可能性があるためです。(2018.04.11 完了)
12. 新しい問題、分散同期トレーニング環境下で、検証段階を経た後、global step と i が一致しない問題。具体的には画像を参照してください。
index=0 のマシン:
index=1 のマシン(990step で停止し、0 マシンの検証が終了するのを待っています。):
私が考えた解決策は、log と検証を hook として MonitoredTrainingSession に追加することですが、試した後、問題は解決しませんでした。(2018.04.10 解決)
これも以下の問題に関連しています:
検証のこのステップに到達すると、性能の異なるマシンが検証を同期して行わないことになります。
順序は:検証ステップに到達すると、性能の良いマシンが先に検証を行い、終わった後、性能の悪いマシンが検証を行います。
これにより、全体のトレーニング時間が増加します。具体的な理由は、検証ステップを 1000 に設定した場合、sess run が 1001 ステップに達すると、1000 ステップのパラメータが ps マシンに渡され、更新されてから worker マシンに戻され、続けて 1001 ステップのトレーニングが行われるからです。(あなたが理解できるかどうかわかりませんが - 0-、MonitoredTrainingSession のこのセッションは毎回実行されるときに実際には 3 つのステップに分かれています。begin、before run、after run。パラメータは ps マシンに渡され、worker マシンに戻されるのは before のステップで行われるはずです。) (2018.04.02 MonitoredTrainingSession を再実装した後、index=0 のマシンでのみ検証を行うようにしました)
同期モードのトレーニングが完了するたびに、index 0 のマシンがしばらく停止し、その後エラーが発生します:
Google で検索しましたが、解決策は見つかりませんでした。しかし、全体のトレーニングには影響しないので、無視します!
-
一つの疑問があります。tensorboard で観察すると、val_loss は 100 ステップごとに記録されます。しかし実際には 1000 ステップごとに検証を行っています。少し混乱しています。
-
同期トレーニング中、性能の良いマシンが先にトレーニングを開始します。もしホストが先にトレーニングを開始しなければ、tensorboard の初期ステップは 1 から始まらないことになります。
---------2018.03.16 更新 ----- 可視化 -------
ネットワーク構造文書(squeezenet.py)を再実装し、パラメータ計算プロセスを最適化し、サマリーコードを追加しました。これにより、tensorboard で多くの内容を確認できるようになりました。
他の文書も相応に更新しました。
古いネットワーク構造文書(network.py)を使用したい場合は、train.py 文書内の inference の行を変更すれば大丈夫です。
index=0 のサーバー上の models ディレクトリを自分のホストに戻し、コマンドラインで実行します:
tensorboard --logdir=models/
ブラウザのアドレスバーに入力します:
localhost:6006
これで可視化内容を確認できます。また、サーバー上で tensorboard コマンドを実行し、自分のホストのブラウザのアドレスバーに IP:ポート番号を入力することで、可視化内容を確認することもできます。
---------2018.03.19 更新 -----DEBUG-------
train コードにデバッグコードを追加しました、たった一行です。tf.train.MonitoredTrainingSession の hook リストに、arg_parsing.py でデバッグモードを有効にするかどうかを設定します。
API の中で tensorboard でデバッグするためのインターフェース tfdbg.TensorBoardDebugHook () も見つけましたが、私のホストの tensorflow バージョン 1.2 にはこのインターフェースがまだないので、テストは行っていません。個人の好みによりますが、コマンドラインでデバッグするのが好きか、tensorboard でデバッグするのが好きかです。
同時にパラメータコードを修正し、毎回実行する際にはトレーニングモードを指定する必要があります。
---------2018.03.20 更新 ----- 平均除去、正規化 -------
-
img2bin_list.py を修正し、最後に bgr 三チャネルの平均を計算して印刷します。
-
arg_parsing.py を修正し、平均パラメータを追加しました。
-
dataset.py を修正し、データ読み込み時に平均除去と正規化操作を追加しました。
---------2018.03.21 更新 ----- ネットワークモデルの追加 -------
-
arg_parsing.py、test.py、train.py を修正しました。
-
mobilenet と mobilenet v2 ネットワークモデルを追加しました。
** --------- 2018.03.22 更新 ----- ネットワークモデルの追加、GPU メモリ問題の解決 ------- **
-
arg_parsing.py、test.py、train.py を修正しました。
-
resnet-50、resnet-101、resnet-152、resnet-200 ネットワークモデルを追加しました。
-
実行時に GPU メモリが満杯になる問題を解決しましたが、単機でしかうまくいかず、分散環境ではうまくいきません。
---------2018.03.26 更新 ----- トレーニング段階で検証段階を追加 ------- ****
train.py の変更が比較的大きく、すべてのネットワーク構造.py にも変更があり、tensorflow バージョンは少なくとも 1.4.0 が必要です。
理由は tf.variable_scope () 内に reuse=tf.AUTO_REUSE がないためです。
もちろん、もしあなたが自分で一つ一つ reuse を設定できるなら、理論的には低バージョンの tensorflow でも使用可能です。
少し面倒ですが、train か val かを判断し、それぞれ reuse を False または True に設定する必要があります。
---------2018.03.29 更新 -----Finetune------- ****
finetune が可能になりました。
私は以前にトレーニングしたモデルを基に finetune しています、
まだオープンソースのトレーニング済みモデルを探していません。 ( 2018.04.02 Github で適切な事前トレーニングモデルが見つからず、たとえ見つかってもいくつかの問題に直面する可能性があります。)
コマンドラインでモデル保存パスを指定するだけで自動的に finetune できます。
--finetune=path/
---------2018.04.02 更新 ----- 可視化効果を最適化 ------- ****
- トレーニング段階と検証段階のサマリーをそれぞれ異なる namespace に配置し、ネットワーク構造図も最適化しました。
---------2018.04.09 更新 ----- 同期・非同期トレーニング ------- ****
-
分散環境で、パラメータの同期または非同期更新を制御するためのブールスイッチ(--issync)を追加しました。
-
worker サーバーは必ず index が 0 から始まるマシンを一つずつ実行する必要があります。順番にプログラムを実行しないと、各サーバーのステップに大きな差が生じます。
-
MonitoredTrainingSession を再実装し、log と検証をそれぞれ 2 つの hook に書き込み、同期モードでは index=0 の worker マシンのみが検証を行います。
---------2018.04.10 更新 ----- ログ出力ステップ不一致問題の解決 -------
- 分散、同期トレーニング環境下で、hook 内で run_context.session.run (global_step) を使用してグローバルステップを読み取り、ログと検証を制御し、異なるマシン間のステップ不一致問題を解決しました。
---------2018.04.11 更新 ----- 非同期トレーニングで最後のイベント記録失敗問題の解決 -------
- 非同期トレーニングも global_step を読み取ることで制御し、ExitHook 内で強制的に index=0 のホストが最後の段階で一度検証を行い、他のマシンが先に run_context.request_stop () を実行することを保証しました。こうすることで、最後のイベント記録失敗問題を解決しました。私が理想とする解決方法は、index=0 のホストが現在の global step がトレーニング終了回数に達したことを発見したとき、他のマシンがすべて request stop を実行した後に自分が request stop を実行することです。
---------2018.04.13 更新 -----SSD コードを追加 -------
-
具体的なモデル保存パスとデータパスを設定する必要があります。
-
データパス内の画像と xml ファイルはそれぞれ 2 つのディレクトリに保存する必要があります。