【深度學(xué)習(xí)系列】關(guān)于PaddlePaddle的一些避“坑”技巧
最近除了工作以外,業(yè)余在參加Paddle的AI比賽,在用Paddle訓(xùn)練的過程中遇到了一些問題,并找到了解決方法,跟大家分享一下:
PaddlePaddle的Anaconda的兼容問題
之前我是在服務(wù)器上安裝的PaddlePaddle的gpu版本,我想把BROAD數(shù)據(jù)拷貝到服務(wù)器上面,結(jié)果發(fā)現(xiàn)我們服務(wù)器的22端口沒開,不能用scp傳上去,非常郁悶,只能在本地訓(xùn)練。本機(jī)mac的顯卡是A卡,所以只能裝cpu版本的,安裝完以后,我發(fā)現(xiàn)運(yùn)行一下程序的時(shí)候報(bào)錯(cuò)了:
1 import paddle.v2 as paddle 2 paddle.init(use_gpu=False,trainer_count=1)
報(bào)錯(cuò):
1 Fatal Python error: PyThreadState_Get: no current thread 2 Abort trap: 6
這讓我非常郁悶,因?yàn)橹拔抑苯釉诜?wù)器上裝沒有問題,但是我的數(shù)據(jù)不能傳上去,所以只能在本機(jī)裝一個(gè),直接pip install paddlepaddle,初始化報(bào)錯(cuò)。后來(lái)我發(fā)現(xiàn)我本機(jī)裝了anaconda,用anaconda的python運(yùn)行paddle會(huì)有一些小問題,不過可以使用otool 和 install_name_tool對(duì)_swig_paddle.so進(jìn)行修改就可以:
1.運(yùn)行otool,可以看到pip安裝之后的_swig_paddle.so依賴/usr/local/opt/python/Frameworks/Python.framework/Versions/2.7/Python,但實(shí)際系統(tǒng)中不存在該路徑
1 otool -L /anaconda/lib/python2.7/site-packages/py_paddle/_swig_paddle.so 2 /anaconda/lib/python2.7/site-packages/py_paddle/_swig_paddle.so: 3 /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1445.12.0) 4 /System/Library/Frameworks/Security.framework/Versions/A/Security (compatibility version 1.0.0, current version 58286.20.16) 5 /usr/local/opt/python/Frameworks/Python.framework/Versions/2.7/Python (compatibility version 2.7.0, current version 2.7.0) 6 /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.0) 7 /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.0.0)
2.利用install_name_tool來(lái)替換依賴
1 install_name_tool -change /usr/local/opt/python/Frameworks/Python.framework/Versions/2.7/Python ~/anaconda/lib/libpython2.7.dylib ~/anaconda/lib/python2.7/site-packages/py_paddle/_swig_paddle.so
3.替換成功后,可以看到第五條已經(jīng)成功的換成anaconda下的路徑了
1 otool -L /anaconda/lib/python2.7/site-packages/py_paddle/_swig_paddle.so 2 /anaconda/lib/python2.7/site-packages/py_paddle/_swig_paddle.so: 3 /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1445.12.0) 4 /System/Library/Frameworks/Security.framework/Versions/A/Security (compatibility version 1.0.0, current version 58286.20.16) 5 /anaconda/lib/libpython2.7.dylib (compatibility version 2.7.0, current version 2.7.0) 6 /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.0) 7 /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.0.0)
現(xiàn)在再運(yùn)行paddle.init就不會(huì)有問題了
不過要注意一點(diǎn)的是:在第二步中,anaconda的路徑要寫絕對(duì)路徑。不能直接進(jìn)去到anacona的上層目錄后直接寫/anaconda/lib...,如果這樣做,那么你換一個(gè)路徑再執(zhí)行paddle.init還是會(huì)有問題,因?yàn)檎也坏侥愕腶naconda的路徑。
PaddlePaddle數(shù)據(jù)類型與數(shù)據(jù)讀取
我在這篇文章“【深度學(xué)習(xí)系列】PaddlePaddle之?dāng)?shù)據(jù)預(yù)處理”中寫過PaddlePaddle的基本數(shù)據(jù)類型與如何用自己的數(shù)據(jù)集進(jìn)行訓(xùn)練,但是還有很多同學(xué)給我發(fā)郵件問我這方面的問題,說(shuō)在處理自己數(shù)據(jù)集的時(shí)候遇到了很多問題。下面我總結(jié)一下幾個(gè)被問到的問題:
1.不明白什么時(shí)候用sequence數(shù)據(jù)
我們知道paddle有四種數(shù)據(jù)類型:dense_vector、sparse_binary_vector、sparse_float_vector和integer,但是還有三種序列格式,對(duì)于dense_vector的話,它的序列格式是dense_vector_sequence,但是什么時(shí)候用dense_vector_sequence呢?
如果你的數(shù)據(jù)是x = [1.0,2.0,3.0,4.0]這樣的,那么就應(yīng)該用dense_vector,維度即為輸入數(shù)據(jù)的維度(這里我們假設(shè)是4),那么應(yīng)該設(shè)置為:
x = paddle.layer.data(name='x', type=paddle.data_type.dense_vector(4))
如果你的數(shù)據(jù)是x = [ [1.0,2.0], [2.0,3.0], [3.0,4.0]],那么我們可以看到這個(gè)數(shù)據(jù)有三個(gè)時(shí)間步長(zhǎng),每個(gè)時(shí)間步的向量維度是2,應(yīng)該設(shè)置為:
x = paddle.layer.data(name='x', type=paddle.data_type.dense_vector_sequence(2))
同理,interger_value和interger_value_sequence也是同樣的處理方法,只不過向量里的元素由dense_vector中的float換成了int。
2.不知道如何創(chuàng)建reader
在數(shù)據(jù)預(yù)處理那篇文章中舉了兩個(gè)例子來(lái)說(shuō)明如何創(chuàng)建自己的數(shù)據(jù)集,包括三種方式:reader、reader_creator和reader_decorator,針對(duì)于這個(gè)比賽,我們將數(shù)據(jù)解析后,轉(zhuǎn)換成data和label的形式,那么我們應(yīng)該如何創(chuàng)建reader呢?其實(shí)有很多種方式,寫一個(gè)最簡(jiǎn)單的方式。我們來(lái)創(chuàng)建一個(gè)reader creator:
1 def reader_creator(data,label): 2 def reader(): 3 for i in xrange(len(data)): 4 yield data[i,:],int(label[i]) 5 return reader
在這里可以看到,使用了yield生成器來(lái)生成數(shù)據(jù),分別生成同一個(gè)sample的data和label,返回的是一個(gè)reader函數(shù),方便我們后面train的時(shí)候灌入數(shù)據(jù)。
當(dāng)然也有其他的方式可以創(chuàng)建,大家可以自行發(fā)揮。
3.不知道怎么用創(chuàng)建好的reader訓(xùn)練
大家可能會(huì)覺得很奇怪,為什么我們創(chuàng)建了reader creator后要返回一個(gè)reader函數(shù)呢,其實(shí)我們是為了方便在訓(xùn)練的時(shí)候調(diào)用,下面創(chuàng)建一個(gè)train_reader
train_reader = paddle.batch(paddle.reader.shuffle( reader_creator(data,label),buf_size=200), batch_size=16)
我們上一步創(chuàng)建好的reader返回的數(shù)據(jù)放到paddle.reader.shuffle里進(jìn)行數(shù)據(jù)混洗,就是把數(shù)據(jù)打散,buf_size表示我一次性把多少條數(shù)據(jù)放進(jìn)來(lái)進(jìn)行shuffle,可以自行設(shè)置,混洗好的數(shù)據(jù)放到paddle.batch里進(jìn)行,以batch_size的量級(jí)批量灌倒模型里去訓(xùn)練,注意如果使用sgd的話,batch_size不能設(shè)置的太大,會(huì)崩潰,親測(cè) = =!
同理,我們也可以創(chuàng)建val_reader,test_reader。
創(chuàng)建完后,就可以放到trainer里訓(xùn)練了
trainer.train(reader=train_reader,num_passes=20,event_handler=event_handler)
還有一些關(guān)于模型訓(xùn)練的參數(shù)設(shè)置技巧大家可以多嘗試,如果有很多相同的問題話,我會(huì)再總結(jié)了發(fā)出來(lái)。