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,里面有相关说明,这里简单介绍一下,详细说明可以去看官网的。

使用如下命令安装依赖:

sudo apt-get install protobuf-compiler python-pil python-lxml python-tk
sudo pip install jupyter
sudo pip install matplotlib

或者使用:

sudo pip install pillow
sudo pip install lxml
sudo pip install jupyter
sudo pip install matplotlib

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

sudo pip install Cython

如果想使用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.

git clone https://github.com/cocodataset/cocoapi.git
cd cocoapi/PythonAPI
make
cp -r pycocotools <path_to_tensorflow>/models/research/

Protobuf Compilation

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

Add Libraries to PYTHONPATH

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

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

3.测试安装

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

二、准备数据

官网有详细的数据准备过程,提供了两个数据集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

# 还是在 /models-master/research/ 目录下
python object_detection/train.py \
    --logtostderr \
    --pipeline_config_path=${PATH_TO_YOUR_PIPELINE_CONFIG} \
    --train_dir=${PATH_TO_TRAIN_DIR}

说明: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

train_config: {
  batch_size: 24  ############################用来修改batchsize
  optimizer {
    rms_prop_optimizer: {
      learning_rate: {
        exponential_decay_learning_rate {
          initial_learning_rate: 0.004
          decay_steps: 800720
          decay_factor: 0.95
        }
      }
      momentum_optimizer_value: 0.9
      decay: 0.9
      epsilon: 1.0
    }
  }
  fine_tune_checkpoint: "PATH_TO_BE_CONFIGURED/model.ckpt"
  #####指向预训练的模型路径,如果从
  #我的百度云下的模型,则是model_dir文件下的各个模型
  #例如:fine_tune_checkpoint: "/home/hadoop/tensorflow/models-master/model_dir/ssd_mobilenet_v1_coco_2017_11_17/model.ckpt"
                                     #
  from_detection_checkpoint: true
  # Note: The below line limits the training process to 200K steps, which we
  # empirically found to be sufficient enough to train the pets dataset. This
  # effectively bypasses the learning rate schedule (the learning rate will
  # never decay). Remove the below line to train indefinitely.
  num_steps: 200000   ############################用来修改训练次数
  data_augmentation_options {
    random_horizontal_flip {
    }
  }
  data_augmentation_options {
    ssd_random_crop {
    }
  }
}

train_input_reader: {
  tf_record_input_reader {
    input_path: "PATH_TO_BE_CONFIGURED/pet_train.record"####指向训练数据路径,
  #例如:input_path: "/home/hadoop/tensorflow/models-master/data/pet_train_with_masks.record"
  }
  label_map_path: "PATH_TO_BE_CONFIGURED/pet_label_map.pbtxt"####指向数据的标签
  #例如:label_map_path: "/home/hadoop/tensorflow/models-master/data/pet_label_map.pbtxt"
}

eval_config: {
  num_examples: 2000
  # Note: The below line limits the evaluation process to 10 evaluations.
  # Remove the below line to evaluate indefinitely.
  max_evals: 10
}

eval_input_reader: {
  tf_record_input_reader {
    input_path: "PATH_TO_BE_CONFIGURED/pet_val.record"####指向验证数据路径
    #例如:input_path: "/home/hadoop/tensorflow/models-master/data/pet_val_with_masks.record"
  }
  label_map_path: "PATH_TO_BE_CONFIGURED/pet_label_map.pbtxt"###指向数据的标签
  #例如:label_map_path: "/home/hadoop/tensorflow/models-master/data/pet_label_map.pbtxt"
  shuffle: false
  num_readers: 1
}

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

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

三、开始分布式训练

官网对分布式训练介绍的不多,这里说明如何进行分布式训练。
准备工作:将三台机器的配置都按前述弄好,其中作为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:

# 还是在 /models-master/research/ 目录下
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=/home/hadoop/tensorflow/models-master/data/ssd_mobilenet_v1_pets.config  --train_dir=/home/hadoop/tensorflow/models-master/train_dir_tmp

worker0机器中运行master:

# 还是在 /models-master/research/ 目录下
TF_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

worker0机器中运行worker:

# 还是在 /models-master/research/ 目录下
TF_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

worker1机器中运行master:

# 还是在 /models-master/research/ 目录下
TF_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

worker1机器中运行worker:

# 还是在 /models-master/research/ 目录下
TF_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

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

tensorboard --logdir=/home/hadoop/tensorflow/models-master/train_dir_tmp

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

四、可以加入HDFS

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

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

CLASSPATH=$($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

注意:数据需要事先传到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下


  if worker_replicas >= 1 and ps_tasks > 0:
    # Set up distributed training.

    #maqy add gpu
    config = tf.ConfigProto()
    config.gpu_options.allow_growth = True
    server = tf.train.Server(tf.train.ClusterSpec(cluster), protocol='grpc',
                             job_name=task_info.type,
                             task_index=task_info.index,
                             config=config)
    if task_info.type == 'ps':
      server.join()
      return

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

    # Merge all summaries together.
    summary_op = tf.summary.merge(list(summaries), name='summary_op')

    # Soft placement allows placing on CPU ops without GPU implementation.
    session_config = tf.ConfigProto(allow_soft_placement=True,
                                    log_device_placement=False)
    #maqy add
    session_config.gpu_options.allow_growth = True    

    # Save checkpoints regularly.
    keep_checkpoint_every_n_hours = train_config.keep_checkpoint_every_n_hours
    saver = tf.train.Saver(
        keep_checkpoint_every_n_hours=keep_checkpoint_every_n_hours)

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),这个正常么?


猜你喜欢

转载自blog.csdn.net/u013036495/article/details/79484432