Tensorflow Object Detection API分布式训练模型

说明:Tensorflow官方的models项目(https://github.com/tensorflow/models)中已经支持了各种模型的训练和验证,并且有详细的教程,但是在models/research/Object_detection的教程中并没有提及如何进行分布式训练,本文旨在介绍如何进行分布式的Object_detection训练。

环境

  • 3台ubuntu 16.04(一台ps,两个worker)
  • tensorflow-gpu 1.4.1(不确定ps那台机器需要安装显卡不)

我是两台台式当worker,每台台式一张1070显卡,然后笔记本当ps,笔记本有1050ti的显卡,因此也装的tensorflow-gpu,不知道ps需要安装gpu版本不


#一、准备工作

1.下载models项目

**注意:**官网上的https://github.com/tensorflow/models更新特别快,我是2017年12月装的tensorflow-gpu1.4.1,2018年3月从官网上下models项目进行编译就报错了,如果你使用的最新版tensorflw,可以下载去官网下载models。

如果版本跟我一致,是tensorflow-gpu1.4.1,可以从这里下载models项目:
链接: https://pan.baidu.com/s/1Afesy1s_5XaQ98eg4mY1RQ 密码: b3g8

**注意:**下载下来后可以进行解压,解压出来的文件名应该叫models-master,官网一般使用的models表示models-master这个文件夹,解压后的文件夹最好直接放在用户目录下,不要出现中文字符在路径中,否则可能会报Cython的错误。比如我的models-master的绝对路径为:/home/hadoop/tensorflow/models-master/ 其中hadoop是我ubuntu的用户名。

2.安装object_detection相关依赖库

这里是官方文档: https://github.com/tensorflow/models/tree/master/research/object_detection,里面有相关说明,这里简单介绍一下,详细说明可以去看官网的。

使用如下命令安装依赖:

1sudo apt-get install protobuf-compiler python-pil python-lxml python-tk 2sudo pip install jupyter 3sudo pip install matplotlib 4 5

或者使用:

1sudo pip install pillow 2sudo pip install lxml 3sudo pip install jupyter 4sudo pip install matplotlib 5 6

可能还需要安装Cython,通过以下命令安装:

1sudo pip install Cython 2 3

如果想使用COCO的评估指标的话,可以进行下载配置。默认的评估指标是Pascal VOC。这里直接贴一段原文吧:To use the COCO object detection metrics add metrics_set: “coco_detection_metrics” to the eval_config message in the config file. To use the COCO instance segmentation metrics add metrics_set: “coco_mask_metrics” to the eval_config message in the config file.

1git clone https://github.com/cocodataset/cocoapi.git 2cd cocoapi/PythonAPI 3make 4cp -r pycocotools <path_to_tensorflow>/models/research/ 5 6

Protobuf Compilation

1#进入到下载的 /models-master/research/ 目录下,运行: 2protoc object_detection/protos/*.proto --python_out=. 3 4

Add Libraries to PYTHONPATH

1# 还是在 /models-master/research/ 目录下 2export PYTHONPATH=$PYTHONPATH:`pwd`:`pwd`/slim 3 4

注意:这一步骤每次新开一个终端都要运行,如果嫌麻烦,可以将其添加到~/.bashrc中去,其中那个 ‘pwd’ 指的是 /models/research/ 所在目录,可以用绝对路径,例如:
export PYTHONPATH=$PYTHONPATH:/home/hadoop/tensorflow/models-master/research:/home/hadoop/tensorflow/models-master/research/slim

3.测试安装

1# 还是在 /models-master/research/ 目录下 2python object_detection/builders/model_builder_test.py 3 4

#二、准备数据
官网有详细的数据准备过程,提供了两个数据集PASCAL VOC和Oxford-IIIT Pet的下载和转换。
https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/preparing_inputs.md

说明:大体过程就是下载数据集后,然后将数据集转换成TFRecord格式的文件。

我这里也提供一个转换后的数据下载,包括PASCAL VOC和Oxford-IIIT Pet两种:
链接: https://pan.baidu.com/s/1DbYTQo4TFd6xSJV8RDI-Ow 密码: dun8

说明:其中.record文件是训练和验证数据,.pbtxt文件存的是各个类别对应的名字,.config文件则是我测试过的网络相关配置。下载完成后可以解压缩到 /models-master/文件夹下,这样可以和我的目录结构一样。

#二、准备预训练的模型
官网提供了各个检测方法的预训练模型,下载地址为:
https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/detection_model_zoo.md

我这里也提供一个预训练模型下载地址:
链接: https://pan.baidu.com/s/1ldDYseIpE4qt6ooUWJoWsw 密码: ruyx

说明:其中有faster_rcnn_resnet50_coco_2018_01_28,faster_rcnn_resnet101_coco_11_06_2017,ssd_inception_v2_coco_2017_11_17,ssd_mobilenet_v1_coco_2017_11_17这四个我测试过的预训练模型。同上,下载完成后可以解压缩到 /models-master/文件夹下,这样可以和我的目录结构一样。
#三、开始单机训练
官网有单机版的训练教程:
https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/running_locally.md

1# 还是在 /models-master/research/ 目录下 2python object_detection/train.py \ 3 --logtostderr \ 4 --pipeline_config_path=${PATH_TO_YOUR_PIPELINE_CONFIG} \ 5 --train_dir=${PATH_TO_TRAIN_DIR} 6 7

说明:pipeline_config_path指定是所使用网络的配置文件,train_dir指定模型训练后的存储位置。网络的配置文件在 models-master/research/object_detection/samples/configs/ 文件夹下可以找到。如果直接从我之前百度云的压缩包下载的数据,data文件夹下已经存了几个模型的配置。

接下来进行所使用的网络配置文件的修改。这里以这个网络配置为例,主要修改的部分都加了中文注释:
models-master/research/object_detection/samples/configs/ssd_mobilenet_v1_pets.config

1train_config: { 2 batch_size: 24 ############################用来修改batchsize 3 optimizer { 4 rms_prop_optimizer: { 5 learning_rate: { 6 exponential_decay_learning_rate { 7 initial_learning_rate: 0.004 8 decay_steps: 800720 9 decay_factor: 0.95 10 } 11 } 12 momentum_optimizer_value: 0.9 13 decay: 0.9 14 epsilon: 1.0 15 } 16 } 17 fine_tune_checkpoint: "PATH_TO_BE_CONFIGURED/model.ckpt" 18 #####指向预训练的模型路径,如果从 19 #我的百度云下的模型,则是model_dir文件下的各个模型 20 #例如:fine_tune_checkpoint: "/home/hadoop/tensorflow/models-master/model_dir/ssd_mobilenet_v1_coco_2017_11_17/model.ckpt" 21 # 22 from_detection_checkpoint: true 23 # Note: The below line limits the training process to 200K steps, which we 24 # empirically found to be sufficient enough to train the pets dataset. This 25 # effectively bypasses the learning rate schedule (the learning rate will 26 # never decay). Remove the below line to train indefinitely. 27 num_steps: 200000 ############################用来修改训练次数 28 data_augmentation_options { 29 random_horizontal_flip { 30 } 31 } 32 data_augmentation_options { 33 ssd_random_crop { 34 } 35 } 36} 37 38train_input_reader: { 39 tf_record_input_reader { 40 input_path: "PATH_TO_BE_CONFIGURED/pet_train.record"####指向训练数据路径, 41 #例如:input_path: "/home/hadoop/tensorflow/models-master/data/pet_train_with_masks.record" 42 } 43 label_map_path: "PATH_TO_BE_CONFIGURED/pet_label_map.pbtxt"####指向数据的标签 44 #例如:label_map_path: "/home/hadoop/tensorflow/models-master/data/pet_label_map.pbtxt" 45} 46 47eval_config: { 48 num_examples: 2000 49 # Note: The below line limits the evaluation process to 10 evaluations. 50 # Remove the below line to evaluate indefinitely. 51 max_evals: 10 52} 53 54eval_input_reader: { 55 tf_record_input_reader { 56 input_path: "PATH_TO_BE_CONFIGURED/pet_val.record"####指向验证数据路径 57 #例如:input_path: "/home/hadoop/tensorflow/models-master/data/pet_val_with_masks.record" 58 } 59 label_map_path: "PATH_TO_BE_CONFIGURED/pet_label_map.pbtxt"###指向数据的标签 60 #例如:label_map_path: "/home/hadoop/tensorflow/models-master/data/pet_label_map.pbtxt" 61 shuffle: false 62 num_readers: 1 63} 64 65

这里是我的单机版运行ssd_mobilenet_v1_pets的完整代码:

1python object_detection/train.py --logtostderr --pipeline_config_path=/home/hadoop/tensorflow/models-master/data/ssd_mobilenet_v1_pets.config --train_dir=/home/hadoop/tensorflow/models-master/train_dir_tmp 2 3

#三、开始分布式训练
官网对分布式训练介绍的不多,这里说明如何进行分布式训练。
准备工作:将三台机器的配置都按前述弄好,其中作为ps的机器中可以没有训练和测试的数据集,即之前的.record文件。

说明:分布式运行通过TF_CONFIG来指定集群,train.py和trainer.py代码中会自动读取系统中的TF_CONFIG这一变量,用于构建集群。
作为ps的机器启动1个ps进程,作为worker0和worker1的机器分别启动两个进程,一个为master,一个为worker。
另外,这个分布式的原理我也不是很懂,master和worker的关系希望有人可以不吝赐教。还有,这个分布式运行的模式应该是between-graph+Synchronization,如果不对也请告知我。

另外说明一下,我的woker0和worker1是台式机,这两台机器搭建了hadoop,然后我的笔记本当作ps,也安装了hadoop,作为hadoop的客户端在使用。所以我在/etc/hosts中配置了相关的ip和名字的对应:
下文中的运行命令中的"master:2000",“slave1:2222”,"slave2:2224"这中间的master,slave1和slave2分别对应我三台电脑的ip。
master--------------worker0的ip
slave1--------------worker1的ip
slave2--------------ps的ip

说明:接下来是各个机器的运行命令,注意命令中”index“和”type"的区别

ps机器中运行ps:

1# 还是在 /models-master/research/ 目录下 2TF_CONFIG='{"cluster": {"master": ["master:2220","slave1:2222"], "ps": ["slave2:2224"], "worker": ["master:3001","slave1:3003"]}, "task": {"index": 0, "type": "ps"}}' python object_detection/train.py --logtostderr --pipeline_config_path=/home/hadoop/tensorflow/models-master/data/ssd_mobilenet_v1_pets.config --train_dir=/home/hadoop/tensorflow/models-master/train_dir_tmp 3 4

worker0机器中运行master:

1# 还是在 /models-master/research/ 目录下 2TF_CONFIG='{"cluster": {"master": ["master:2220","slave1:2222"], "ps": ["slave2:2224"], "worker": ["master:3001","slave1:3003"]}, "task": {"index": 0, "type": "master"}}' python object_detection/train.py --logtostderr --pipeline_config_path=/home/hadoop/tensorflow/models-master/data/ssd_mobilenet_v1_pets.config --train_dir=/home/hadoop/tensorflow/models-master/train_dir_tmp 3 4

worker0机器中运行worker:

1# 还是在 /models-master/research/ 目录下 2TF_CONFIG='{"cluster": {"master": ["master:2220","slave1:2222"], "ps": ["slave2:2224"], "worker": ["master:3001","slave1:3003"]}, "task": {"index": 0, "type": "worker"}}' python object_detection/train.py --logtostderr --pipeline_config_path=/home/hadoop/tensorflow/models-master/data/ssd_mobilenet_v1_pets.config --train_dir=/home/hadoop/tensorflow/models-master/train_dir_tmp 3 4

worker1机器中运行master:

1# 还是在 /models-master/research/ 目录下 2TF_CONFIG='{"cluster": {"master": ["master:2220","slave1:2222"], "ps": ["slave2:2224"], "worker": ["master:3001","slave1:3003"]}, "task": {"index": 1, "type": "master"}}' python object_detection/train.py --logtostderr --pipeline_config_path=/home/hadoop/tensorflow/models-master/data/ssd_mobilenet_v1_pets.config --train_dir=/home/hadoop/tensorflow/models-master/train_dir_tmp 3 4

worker1机器中运行worker:

1# 还是在 /models-master/research/ 目录下 2TF_CONFIG='{"cluster": {"master": ["master:2220","slave1:2222"], "ps": ["slave2:2224"], "worker": ["master:3001","slave1:3003"]}, "task": {"index": 1, "type": "worker"}}' python object_detection/train.py --logtostderr --pipeline_config_path=/home/hadoop/tensorflow/models-master/data/ssd_mobilenet_v1_pets.config --train_dir=/home/hadoop/tensorflow/models-master/train_dir_tmp 3 4

至此,应该就可以顺利开始训练了,可以利用命令:

1tensorboard --logdir=/home/hadoop/tensorflow/models-master/train_dir_tmp 2 3

来监测训练情况,最后训练的模型应该会保存在worker0这台机器对应的文件夹上。

#四、可以加入HDFS

说明:还可以将训练数据,预训练模型甚至训练后保存的模型存储到HDFS中,在配置成功hadoop的集群里,只要对配置文件、文件路径以及运行命令稍做修改即可。

这里贴出ps上的运行命令:

1CLASSPATH=$($HADOOP_HDFS_HOME/bin/hadoop classpath --glob) TF_CONFIG='{"cluster": {"master": ["master:2220","slave1:2222"], "ps": ["slave2:2224"], "worker": ["master:3001","slave1:3003"]}, "task": {"index": 0, "type": "ps"}}' python object_detection/train.py --logtostderr --pipeline_config_path=hdfs://master:9000/home/hadoop/tensorflow/models-master/data/ssd_mobilenet_v1_pets_hdfs.config --train_dir=hdfs://master:9000/home/hadoop/tensorflow/models-master/train_dir_tmp 2 3

注意:数据需要事先传到HDFS中,相关配置文件ssd_mobilenet_v1_pets_hdfs.config也可以传到HDFS上,只是要将里面训练数据的对应路径修改成HDFS中的。
#五、一些问题
说明
ps是笔记本,两台台式是worker。
台式配置:1070,16g内存。
局域网:100M的以太网
####1.使用tensorflow时,开启进程就会把所有显存占满,worker机器中要启动master和worker两个进程,如果先启动worker进程,则master进程可分配的显存很小,程序会跑不起来,有时候会输出特别长的字各种路径。若先启动master进程,再启动worker进程,则程序可以跑,但过一段时间worker进程会显存错误。
解决方法:给tensorflow程序开启显存自增长,而不是启动就占满。
在models-master/research/object_detection/train.py文件中,大约143行开始,修改成如下样子,修改的部分在注释 #maqy add下

1 2 if worker_replicas >= 1 and ps_tasks > 0: 3 # Set up distributed training. 4 5 #maqy add gpu 6 config = tf.ConfigProto() 7 config.gpu_options.allow_growth = True 8 server = tf.train.Server(tf.train.ClusterSpec(cluster), protocol='grpc', 9 job_name=task_info.type, 10 task_index=task_info.index, 11 config=config) 12 if task_info.type == 'ps': 13 server.join() 14 return 15 16

在models-master/research/object_detection/trainer.py文件中,大约307行开始,修改成如下样子:

1 # Merge all summaries together. 2 summary_op = tf.summary.merge(list(summaries), name='summary_op') 3 4 # Soft placement allows placing on CPU ops without GPU implementation. 5 session_config = tf.ConfigProto(allow_soft_placement=True, 6 log_device_placement=False) 7 #maqy add 8 session_config.gpu_options.allow_growth = True 9 10 # Save checkpoints regularly. 11 keep_checkpoint_every_n_hours = train_config.keep_checkpoint_every_n_hours 12 saver = tf.train.Saver( 13 keep_checkpoint_every_n_hours=keep_checkpoint_every_n_hours) 14 15 16

####2.承接上一问题,当修改完毕后,使用ssd_mobilenet_v1_coco_2017_11_17这一小网络,并把训练batchsize调为12,则master进程所使用显存大约为2.5g,之后运行一段时间,worker进程也开始进行计算输出global_step,并且显存使用从100m也达到2.5g,不知道master进程和worker进程到底存在着什么关系。另外可以观察一下当worker进程也开始计算后,单步速度有没有变慢。

####3.为什么模型最终会保存在worker0机器中,这个可以指定么?

####4.分布式运行速度明显下降了很多,使用ssd_mobilenet_v1_coco_2017_11_17,batchsize为12时,单机版每步速度大约0.25s,分布式每步大约4.8s,并且经过测试,不同的网络结构速度会差很多,比如faster_rcnn_resnet101大约每步要30-50s。
初步考虑原因是参数传递的过程耗费时间,通过系统监视器可以看到100M的以太网,各个机器的传输与接收速度基本在12M/s左右,可能是影响速度的主要原因,如果有人试了更大带宽的局域网,希望可以留言一下计算速度。

####5.faster-rcnn的所有配置文件的batch_size都是1,这个是什么原因呢?另外,不论是resnet50还是resnet101,我使用的时候显存仍然会被占满(8g),这个正常么?


代码交流 2021