走近深度學習,認識MoXing:基于TensorFlow運行參數教程
MoXing沒有對運行參數定義特殊API,用戶可根據自己的習慣定義運行參數。建議使用TensorFlow的flags組件來定義。
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內部定義運行參數的相關API:mox.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服務中訓練作業的運行參數
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
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系列文章下期預告:數據輸入教程。
TensorFlow
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。