場(chǎng)景描述:
- 構(gòu)建模型時(shí),會(huì)加載本地預(yù)訓(xùn)練的embedding向量到numpy array,數(shù)組大小為100w*128
- 再把numpy array賦值給模型的一個(gè)變量,后面參與訓(xùn)練
#代碼片段
#self.init_emb is a file path
emb_dict= np.loadtxt(self.init_emb, dtype=np.float32)
self.item_mat = tf.get_variable(name="item_mat", shape=[938280, 128],
dtype=tf.float32,
initializer=tf.constant(emb_dict))
- 定時(shí)保存checkpoint到HDFS路徑
出現(xiàn)問(wèn)題:
保存 checkpoint時(shí)報(bào)OOM;通過(guò)Xlearning上的log可以查看到;
跟進(jìn)排查:
- 調(diào)用tf.saver.save(session,path)保存checkpoint時(shí),默認(rèn)會(huì)生成4個(gè)文件:
checkpoint //存儲(chǔ)checkpoint的狀態(tài),路徑信息等
xxx.data //graph中變量的value
xxx.index //變量名和在data中的位置索引表
xxx.meta //graph的結(jié)構(gòu),包括 GraphDef, SaverDef等
- 發(fā)現(xiàn).meta文件很大,接近400M+;
- 把checkpoint保存到本地,正常。另外發(fā)現(xiàn)和HDFS上的文件大小不一樣;確認(rèn)是寫.meta文件到HDFS時(shí)寫掛了;
初步結(jié)論
- TensorFlow通過(guò)numpy等外部數(shù)據(jù)初始化的變量時(shí),這個(gè)外部數(shù)據(jù)會(huì)作為一個(gè)常量(Const)存儲(chǔ)在Graph中。導(dǎo)致寫checkpoint時(shí)meta文件很大,觸發(fā)寫HDFS時(shí)報(bào)OOM的問(wèn)題;
解決方式:
- 減少metagraph的大小,把變量通過(guò)feed_dict的方式進(jìn)行初始化,不過(guò)這樣寫變量初始化的邏輯要比較tricky。其他變量需要區(qū)分出來(lái)單獨(dú)進(jìn)行初始化,使用tf.global_variables_initializer()需要小心一點(diǎn)。
pl = tf.placeholder(np.float32, shape=[1000, 2000])
v3 = tf.get_variable("v3", initializer=pl)
with tf.Session() as sess:
matrix = np.random.rand(1000, 2000)
sess.run(v3.initializer, feed_dict={pl: matrix},run_metadata=meta)
- 保存checkpoint時(shí)不寫meta文件,可以暫時(shí)繞過(guò)。不過(guò)最后存儲(chǔ)模型時(shí)還是需要保存Graph結(jié)構(gòu)的。
#把write_meta_graph 設(shè)置成False
save_path = saver.save(sess, "/tmp/model/ckpt", write_meta_graph=False, global_step=xxx)
- 通過(guò)框架層面來(lái)解決checkpoint上傳到HDFS的問(wèn)題(tiny+目前支持把checkpoint上傳到指定HDFS路徑)
- 查證寫HDFS的原因,時(shí)間原因暫時(shí)沒(méi)去深入跟。
后續(xù)跟進(jìn)
1.TensorFlow的Graph 及模型保存
2.變量的初始化(通過(guò)tf op進(jìn)行初始化和np array初始化的流程細(xì)節(jié))
3.寫HDFS的這個(gè)bug
參考資料
1.tensorflow:A Tool Developer Guide To TFModelFIles
2.圖的核心數(shù)據(jù)結(jié)構(gòu)
3.files in save model
附件圖片
1.通過(guò)賦值np array的const

2.通過(guò)tf.constant構(gòu)造的const
