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)) ネットワーク構造に応じてリサイズサイズを選択する必要があります
このスクリプトは 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 完了)
6.GPU メモリが常に占有される問題について(2018.03.22 完了)
7. より多くのネットワークモデル文書の準備(2018.03.19 mobilenet、2018.03.22 resnet)
8.GPU を選択(2018.03.19 完了)
9. 可視化のネットワーク構造図の最適化(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 のマシンの検証が終了するのを待っています。):
私が考えた解決策は、ログと検証を 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 で検索しましたが、解決策は見つかりませんでした。しかし、全体のトレーニングには影響しないので、無視します!
-
1 つの疑問がありますが、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 コードにデバッグコードを追加しました、たった 1 行です。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 更新 ----- ネットワークモデルの追加 -------
1.arg_parsing.py、test.py、train.py を修正しました。
- mobilenet と mobilenet v2 ネットワークモデルを追加しました。
** --------- 2018.03.22 更新 ----- ネットワークモデルの追加、GPU メモリ問題の解決 ------- **
1.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 を再実装し、ログと検証をそれぞれ 2 つの hook に書き込み、同期モードでは index=0 の worker マシンでのみ検証を行います。
---------2018.04.10 更新 ----- ログ出力ステップ不一致問題の解決 -------
- 分散、同期トレーニング環境下で、hook 内で run_context.session.run (global_step) を使用してグローバルステップを読み取り、ログと検証を制御し、異なるマシン間のステップ不一致問題を解決しました。
---------2018.04.11 更新 ----- 非同期トレーニングで最後のイベント記録失敗問題の解決 -------
- 非同期トレーニングも global_step を読み取ることで制御するように変更し、ExitHook 内で強制的に index=0 のホストが最後の段階で 1 回検証を行うようにし、他のマシンが先に run_context.request_stop () を実行するようにしました。これにより、最後のイベント記録失敗の問題が解決されました。私の理想的な解決方法は、index=0 のホストが現在の global step がトレーニング終了回数に達したとき、他のマシンがすべて request stop を実行するのを待ってから、自分が request stop を実行することです。
---------2018.04.13 更新 -----SSD コードの追加 -------
-
具体的なモデル保存パスとデータパスを設定する必要があります。
-
データパス内の画像と xml ファイルはそれぞれ 2 つのディレクトリに保存する必要があります。