Python語言
越來越廣泛的應(yīng)用于機(jī)器學(xué)習(xí)/
深度學(xué)習(xí)領(lǐng)域,是目前最火的該領(lǐng)域編程語言,各大深度學(xué)習(xí)框架基本都支持
python
接口。
在TensorFlow
訓(xùn)練模型的過程中,一般數(shù)據(jù)加載分情景各有不同。
1.
當(dāng)數(shù)據(jù)量能直接全部載入內(nèi)存時(shí),當(dāng)然最是方便,直接全部載入內(nèi)存,然后訓(xùn)練即可。
2.
數(shù)據(jù)無法全部載入內(nèi)存時(shí),有多種方法。介紹其中
2
種用的多的,其一是邊訓(xùn)練邊讀?。梢杂枚嗑€程進(jìn)行優(yōu)化),其二是隨機(jī)打亂所有訓(xùn)練數(shù)據(jù)的索引然后隨機(jī)選擇部分?jǐn)?shù)據(jù)進(jìn)行訓(xùn)練測試。
第2
類情景中,有可能由于對(duì)
Python
的
GC
機(jī)制理解不深(
Me…
),出現(xiàn)內(nèi)存泄露。比如下面的第
12
行的列表就無法釋放,導(dǎo)致內(nèi)存泄露,而
11
行則不會(huì)出現(xiàn)內(nèi)存泄露。
import numpy
as np
import gc
import psutil
import os
def
get_memory_usage():
process = psutil.Process(os.getpid())
return process.memory_info().rss/(1024*1024)
print 'before load, memory: %d MB' % get_memory_usage()#dataset = [np.zeros((6000,6000),dtype=np.float32) for _ in range(30000)]
dataset = [(np.zeros((6000,6000),dtype=np.float32),np.zeros((200,200),dtype=np.int32))
for _
in range(10000)]
print 'after load, memory: %d MB' % get_memory_usage()
print 'before release, memory: %d MB' % get_memory_usage()
del dataset
dataset =
None
gc.collect()
print 'after release, memory: %d MB' % get_memory_usage()
第11
行內(nèi)存釋放結(jié)果:
before
load,
memory: 25 MB
after
load,
memory: 220 MB
before
release,
memory: 220 MB
after
release,
memory: 27 MB
第12
行內(nèi)存釋放結(jié)果:
before
load,
memory: 23 MB
after
load,
memory: 1406 MB
before
release,
memory: 1406 MB
after
release,
memory: 1170 MB
可以看到第12
行內(nèi)存泄露嚴(yán)重。出現(xiàn)這種內(nèi)存泄露時(shí),模型訓(xùn)練基本只能訓(xùn)練幾個(gè)
Epoch
就會(huì)出現(xiàn)
OOM
。
大力出奇跡
這種問題當(dāng)然最優(yōu)的是從根源解決,即研究清楚Python
的
GC
機(jī)制,解決內(nèi)存泄露。
在時(shí)間比較緊或者問題比較麻煩時(shí),有時(shí)粗暴快速的方法也不失為一種選擇。
訓(xùn)練模型的目標(biāo)是根據(jù)訓(xùn)練數(shù)據(jù)以及模型結(jié)構(gòu)優(yōu)化模型參數(shù),因此只要達(dá)成目的,過程不重要。
在這個(gè)例子中,可以直接每次只訓(xùn)練1
個(gè)
Epoch
,然后重啟
Python
進(jìn)程讀取模型進(jìn)行
fine-tune
。與直接訓(xùn)練若干個(gè)
Epoch
效果接近。
#
訓(xùn)練
50
個(gè)
epoch
seq 50|xargs -i python train.py --model-path=./model
來源:網(wǎng)絡(luò)
|