走近深度学习,认识MoXing:基于TensorFlow运行参数教程

举报
云上AI 发表于 2018/08/17 11:54:42 2018/08/17
【摘要】 本文为MoXing系列文章第二篇,主要介绍用户在定义运行参数时遇到的常见报错及解决办法。

MoXing没有对运行参数定义特殊API,用户可根据自己的习惯定义运行参数。建议使用TensorFlowflags组件来定义。


1、使用tf.flags定义运行参数(TensorFlow-1.4

flags是由TensorFlow-1.4提供的一种定义运行参数组件。从TensorFlow-1.5开始,TensorFlow将flags替换成了absl


如果代码中出现如下错误信息,很有可能是在使用MoXing-TensorFlow-1.4的情况下,TensorFlow的版本不是1.4。

AttributeError: 'module' object has no attribute '_FlagValues'

通过以下命令查看TensorFlow版本:

pip list | grep tensorflow

或者在python中输入:

import tensorflow as tf

tf.__version__


使用tf.flags定义一个运行参数如下:

tf.flags.DEFINE_string(name='data_url', default='./', help='Data directory.')

flags = tf.flags.FLAGS

print(flags.data_url)

flag_name: 运行参数名,例如外部命令行运行时添加参数--data_url=xxx

default_value: 当外部命令行参数不传入该参数时使用的缺省值

docstring: 命令行帮助文档信息


在TensorFlow-1.4中,tf.flags提供了以下4种数据类型:

tf.flags.DEFINE_string

tf.flags.DEFINE_integer

tf.flags.DEFINE_float

tf.flags.DEFINE_boolean


如果本来的脚本中定义的运行参数中有list,但是tf.flags不支持list怎么办?

用string表达list,然后在代码中解析出来,比如:

tf.flags.DEFINE_string(name='int_list', default='0,1,2', help=None)

flags = tf.flags.FLAGS

int_list = [int(int_item) for int_item in flags.int_list.split(',')]


2、MoXing定义的默认运行参数

MoXing本身会定义一些默认的运行参数,这些参数不需要在用户脚本中额外定义,当用户使用如下导入代码时即生效,直接可以在外部命令行或DLS服务的运行参数中传入。

import moxing.tensorflow as mox

 

以下列举几个重要的参数:

--num_gpus: 使用GPU的数量,如果使用的是CPU,这项参数不要填写,或者给1,缺省值为1。


以下四个参数是TensorFlow推荐的分布式运行参数,具体可参考TensorFlow官方文档

--job_name: ps或worker

--task_index: ps或worker进程的序号,一般情况下task_index为0的worker为chief worker (也可以认为是master节点,master节点在物理上并不存在,是一个逻辑节点)

--ps_hosts: ps的ip和端口,多个节点以“,”分割。

--worker_hosts: worker的ip和端口,多个节点以“,”分割。


例如,启动一个2个节点的训练作业,每个节点使用4个GPU,参数配置如下:

# 节点0启动ps进程参数(对应IP地址为192.168.1.100

--job_name=ps

--task_index=0

--ps_hosts=192.168.1.100:2222,192.168.1.101:2222

--worker_hosts=192.168.1.100:2223,192.168.1.101:2223

# 节点0启动worker进程参数(对应IP地址为192.168.1.100

--job_name=worker

--task_index=0

--ps_hosts=192.168.1.100:2222,192.168.1.101:2222

--worker_hosts=192.168.1.100:2223,192.168.1.101:2223

--num_gpus=4

 # 节点1启动ps进程参数(对应IP地址为192.168.1.101

--job_name=ps

--task_index=1

--ps_hosts=192.168.1.100:2222,192.168.1.101:2222

--worker_hosts=192.168.1.100:2223,192.168.1.101:2223

 # 节点1启动ps进程参数(对应IP地址为192.168.1.101

--job_name=worker

--task_index=1

--ps_hosts=192.168.1.100:2222,192.168.1.101:2222

--worker_hosts=192.168.1.100:2223,192.168.1.101:2223

--num_gpus=4

MoXing内部定义运行参数的相关APImox.get_flag,mox.set_flag


所有分布式进程都启动后,worker进程不断在打印如下信息,没有开始训练。

2018-04-13 14:01:47.653259: I tensorflow/core/distributed_runtime/master.cc:221] CreateSession still waiting for response from worker: /job:ps/replica:0/task:0

2018-04-13 14:01:47.653308: I tensorflow/core/distributed_runtime/master.cc:221] CreateSession still waiting for response from worker: /job:ps/replica:0/task:1

2018-04-13 14:01:47.653315: I tensorflow/core/distributed_runtime/master.cc:221] CreateSession still waiting for response from worker: /job:worker/replica:0/task:1

解决办法:

首先保证job_name,task_index,ps_hosts,worker_hosts这四个参数都是正确的,考虑以下这种情况是不正确的:

在一个IP为192.168.1.100的机器上启动ps或worker进程:

--job_name=worker

--task_index=1

--ps_hosts=192.168.1.100:2222,192.168.1.101:2222

--worker_hosts=192.168.1.100:2223,192.168.1.101:2223

因为该进程启动位置是192.168.1.100,但是运行参数中指定的task_index为1,对应的IP地址是ps_hosts或worker_hosts的第二项(第一项的task_index为0),也就是192.168.1.101,和进程本身所在机器的IP不一致。

另外一种情况也会导致该问题的发生,从TensorFlow-1.4开始,分布式会自动使用环境变量中的代理去连接,如果运行的节点之间不需要代理互连,那么将代理的环境变量移除即可,在脚本的开始位置添加代码:

# 注意这段代码必须写在import tensorflow as tf或者import moxing.tensorflow as mox之前

import os

os.enrivon.pop('http_proxy')

os.enrivon.pop('https_proxy')


3、DLS服务中训练作业的运行参数

image.png

DLS服务-创建训练作业的界面


DLS服务中,用户不需要考虑代理问题。如用户使用原生TensorFlow-API脚本进行训练,用户需要定义DLS服务规定的几项参数,说明如下:

⊙ 训练数据集中填写的内容会以运行参数--data_url的形式传入到启动文件指定的脚本中.

⊙ 在选择计算节点规格和计算节点个数时会产生多GPU和分布式相关的5项参数。如,计算节点规格为4*P100,即使用4个P100的GPU,所以--num_gpus=4,计算节点个数为2,则表示分布式运行并使用2个节点,则会使用启动文件指定的脚本启动4个进程,每个进程都会按规范填入job_name,task_index,ps_hosts,worker_hosts,其中的IP地址和端口是由DLS预先分配指定好的,用户直接在脚本中使用即可。

⊙ 如果用户使用基于MoXing的脚本进行训练,则不需要定义多GPU和分布式的参数,也不需要编写多GPU和分布式相关的代码。但用户仍然需要定义--data_url这个运行参数。



用户在训练脚本中想读取一些文件或者写入一些日志文件,发现找不到文件或路径。

如果你想读取OBS上桶名为dls-test中的文件a.txt,而且使用了如下代码:

f=open('/dls-test/a.txt', 'r')

则会出现如下错误:

IOError: [Errno 2] No such file or directory: '/dls-test/a.txt'

在DLS服务中,作业在容器中启动,一般来说对文件的读写都是基于OBS或其他数据服务的,比如打开一个OBS上,桶名为dls-test中的文件a.txt,那么要使用OBS的路径s3://dls-test/a.txt,但是当你发现把代码修改为:

f=open('s3://dls-test/a.txt', 'r')

依然会出现同样找不到文件的错误,那是因为大多数文件读写的API都不支持s3路径,用户如果涉及文件读写的操作,都必须使用支持s3的文件接口,如obs-sdk,obscmd,s3cmd,tf.gfile,mox.file

以下代码利用tf.gfile操作文件:

import tensorflow as tf

f=tf.gfile.Open('s3://dls-test/a.txt', 'r')


在DLS中,用户不需要配置OBS的ak, sk等信息,因为都已经默认配置好了。

建议用户将输入数据集、代码、输出日志这三者的路径提前规划好,不要放在相同的目录下,由于代码目录有10MB的容量大小限制,所以如果输入数据集或者输出日志存放在代码目录中可能会导致不能提交作业。


假设用户将代码结构如下:

project_dir

|- main.py

|- module_dir

|- module_file.py

用户在main.py中有代码:

from module_dir import module_file

发生如下错误:

Traceback (most recent call last):

File "project_dir/main.py", line 1, in <module>

from module_dir import module_file

ImportError: No module named module_dir

这份代码如果在本地运行,需要将project_dir加入到PYTHONPATH或者将整个project_dir安装到site-package中才能运行,但是在DLS中没有办法进行这些操作,所以可以将project_dir加入到sys.path中解决该问题,步骤如下:

首先保证被import的module中有__init__.py存在,创建module_dir的__init__.py,代码结构如下:

project_dir

|- main.py

|- module_dir

|- __init__.py

|- module_file.py

在main.py中将project_dir添加到sys.path中,由于用户不知道project_dir在容器中的位置,所以利用相对路径:

import os

import sys

# __file__为获取当前执行脚本main.py的绝对路径

# os.path.dirname(__file__)获取main.py的父目录,即project_dir的绝对路径

current_path = os.path.dirname(__file__)

sys.path.append(current_path)

# sys.path.append执行完毕之后再导入其他模块

from module_dir import module_file

再次提交作业运行即可。

如果在DLS服务中训练数据集的值没有填写,脚本依然会收到--data_url的参数,参数值为空。


在用户脚本中定义了运行参数如下:

tf.flags.DEFINE_string('data_url', default='s3://xxx', help=None)

在DLS中训练数据集项不填写,这种情况下用户可能会认为脚本会取运行参数data_url的默认值default_value,即's3://xxx',但实际情况是,即使训练数据集项不填写,脚本依然会收到--data_url的参数,只是参数的值为空,即:python xxx.py --data_url='',所以默认值无法起作用。

如果是用户自定义的运行参数,考虑以下3种情况:

① 用户添加了一个运行参数: my_flag = xxx,则脚本会收到--my_flag=xxx

② 用户添加了一个运行参数: my_flag,但是没有填入任何的值,则脚本会收到--my_flag=''

③ 用户没有添加运行参数: my_flag,则脚本不会收到--my_flag这个运行参数

所以训练数据集类似这里的第②种情况。




MoXing系列文章下期预告:数据输入教程。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。