導語python
在使用指南的最後一部分,咱們彙總了使用PaddlePaddle過程當中的常見問題,本部分推文目錄以下:
算法
2.22:【FAQ】模型配置相關問題彙總express
2.23:【FAQ】參數設置相關問題彙總apache
2.24:【FAQ】本地訓練與預測相關問題彙總api
2.25:【FAQ】集羣訓練與預測相關問題彙總緩存
2.26:如何貢獻代碼網絡
2.27:如何貢獻文檔多線程
本地訓練與預測相關問題彙總app
|1. 如何減小內存佔用less
神經網絡的訓練自己是一個很是消耗內存和顯存的工做,常常會消耗數10GB的內存和數GB的顯存。 PaddlePaddle的內存佔用主要分爲以下幾個方面:
DataProvider緩衝池內存(只針對內存)
神經元激活內存(針對內存和顯存)
參數內存 (針對內存和顯存)
其餘內存雜項
其中,其餘內存雜項是指PaddlePaddle自己所用的一些內存,包括字符串分配,臨時變量等等,暫不考慮在內。
A.減小DataProvider緩衝池內存
PyDataProvider使用的是異步加載,同時在內存裏直接隨即選取數據來作Shuffle。即:
因此,減少這個內存池便可減少內存佔用,同時也能夠加速開始訓練前數據載入的過程。可是,這 個內存池實際上決定了shuffle的粒度。因此,若是將這個內存池減少,又要保證數據是隨機的, 那麼最好將數據文件在每次讀取以前作一次shuffle。可能的代碼爲:
# Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
@provider(min_pool_size=0, ...)
def process(settings, filename):
os.system('shuf %s > %s.shuf' % (filename, filename)) # shuffle before.
with open('%s.shuf' % filename, 'r') as f:
for line in f:
yield get_sample_from_line(line)
這樣作能夠極大的減小內存佔用,而且可能會加速訓練過程,詳細文檔參考 api_pydataprovider2 。
B.神經元激活內存
神經網絡在訓練的時候,會對每個激活暫存一些數據,如神經元激活值等。 在反向傳遞的時候,這些數據會被用來更新參數。這些數據使用的內存主要和兩個參數有關係, 一是batch size,另外一個是每條序列(Sequence)長度。因此,其實也是和每一個mini-batch中包含 的時間步信息成正比。
因此作法能夠有兩種:
減少batch size。 即在網絡配置中 settings(batch_size=1000) 設置成一個小一些的值。可是batch size自己是神經網絡的超參數,減少batch size可能會對訓練結果產生影響。
減少序列的長度,或者直接扔掉很是長的序列。好比,一個數據集大部分序列長度是100-200, 可是忽然有一個10000長的序列,就很容易致使內存超限,特別是在LSTM等RNN中。
C.參數內存
PaddlePaddle支持很是多的優化算法(Optimizer),不一樣的優化算法須要使用不一樣大小的內存。 例如使用 adadelta 算法,則須要使用等於權重參數規模大約5倍的內存。舉例,若是參數保存下來的模型目錄 文件爲 100M, 那麼該優化算法至少須要 500M 的內存。
能夠考慮使用一些優化算法,例如 momentum。
|2.如何加速訓練速度
加速PaddlePaddle訓練能夠考慮從如下幾個方面:
減小數據載入的耗時
加速訓練速度
利用分佈式訓練駕馭更多的計算資源
A.減小數據載入的耗時
使用pydataprovider時,能夠減小緩存池的大小,同時設置內存緩存功能,便可以極大的加速數據載入流程。 DataProvider 緩存池的減少,和以前減少經過減少緩存池來減少內存佔用的原理一致。
# Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
@provider(min_pool_size=0, ...)
def process(settings, filename):
os.system('shuf %s > %s.shuf' % (filename, filename)) # shuffle before.
with open('%s.shuf' % filename, 'r') as f:
for line in f:
yield get_sample_from_line(line)
同時 @provider 接口有一個 cache 參數來控制緩存方法,將其設置成 CacheType.CACHE_PASS_IN_MEM 的話,會將第一個 pass (過完全部訓練數據即爲一個pass)生成的數據緩存在內存裏,在以後的 pass 中,不會再從 python 端讀取數據,而是直接從內存的緩存裏讀取數據。這也會極大減小數據讀入的耗時。
B.加速訓練速度
PaddlePaddle支持Sparse的訓練,sparse訓練須要訓練特徵是 sparse_binary_vector 、 sparse_vector 、或者 integer_value 的任一一種。同時,與這個訓練數據交互的Layer,須要將其Parameter設置成 sparse 更新模式,即設置 sparse_update=True
這裏使用簡單的 word2vec 訓練語言模型距離,具體使用方法爲:使用一個詞前兩個詞和後兩個詞,來預測這個中間的詞。這個任務的DataProvider爲:
# Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
DICT_DIM = 3000
@provider(input_types=[integer_sequence(DICT_DIM), integer_value(DICT_DIM)])
def process(settings, filename):
with open(filename) as f:
# yield word ids to predict inner word id
# such as [28, 29, 10, 4], 4
# It means the sentance is 28, 29, 4, 10, 4.
yield read_next_from_file(f)
這個任務的配置爲:
# Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
... # the settings and define data provider is omitted.
DICT_DIM = 3000 # dictionary dimension.
word_ids = data_layer('word_ids', size=DICT_DIM)
emb = embedding_layer(
input=word_ids, size=256, param_attr=ParamAttr(sparse_update=True))
emb_sum = pooling_layer(input=emb, pooling_type=SumPooling())
predict = fc_layer(input=emb_sum, size=DICT_DIM, act=Softmax())
outputs(
classification_cost(
input=predict, label=data_layer(
'label', size=DICT_DIM)))
C.利用更多的計算資源
利用更多的計算資源能夠分爲如下幾個方式來進行:
單機CPU訓練
使用多線程訓練。設置命令行參數 trainer_count。
單機GPU訓練
使用顯卡訓練。設置命令行參數 use_gpu。
使用多塊顯卡訓練。設置命令行參數 use_gpu 和 trainer_count 。
多機訓練
請參考 cluster_train。
|3. 如何指定GPU設備
例如機器上有4塊GPU,編號從0開始,指定使用二、3號GPU:
方式1:經過 CUDA_VISIBLE_DEVICES(連接:http://www.acceleware.com/blog/cudavisibledevices-masking-gpus) 環境變量來指定特定的GPU。
env CUDA_VISIBLE_DEVICES=2,3 paddle train --use_gpu=true --trainer_count=2
方式2:經過命令行參數 --gpu_id 指定。
paddle train --use_gpu=true --trainer_count=2 --gpu_id=2
|4.如何調用 infer 接口輸出多個layer的預測結果
將須要輸出的層做爲 paddle.inference.Inference() 接口的 output_layer 參數輸入,代碼以下:
inferer = paddle.inference.Inference(output_layer=[layer1, layer2], parameters=parameters)
指定要輸出的字段進行輸出。以輸出 value 字段爲例,代碼以下:
out = inferer.infer(input=data_batch, field=["value"])
須要注意的是:
若是指定了2個layer做爲輸出層,實際上須要的輸出結果是兩個矩陣;
假設第一個layer的輸出A是一個 N1 * M1 的矩陣,第二個 Layer 的輸出B是一個 N2 * M2 的矩陣;
paddle.v2 默認會將A和B 橫向拼接,當N1 和 N2 大小不同時,會報以下的錯誤:
ValueError: all the input array dimensions except for the concatenation axis must match exactly
多個層的輸出矩陣的高度不一致致使拼接失敗,這種狀況經常發生在:
同時輸出序列層和非序列層;
多個輸出層處理多個不一樣長度的序列;
此時能夠在調用infer接口時經過設置 flatten_result=False , 跳過「拼接」步驟,來解決上面的問題。這時,infer接口的返回值是一個python list:
list 中元素的個數等於網絡中輸出層的個數;
list 中每一個元素是一個layer的輸出結果矩陣,類型是numpy的ndarray;
每個layer輸出矩陣的高度,在非序列輸入時:等於樣本數;序列輸入時等於:輸入序列中元素的總數;寬度等於配置中layer的size;
|5. 如何在訓練過程當中得到某一個layer的output
能夠在event_handler中,經過 event.gm.getLayerOutputs("layer_name") 得到在模型配置中某一層的name layer_name 在當前 mini-batch forward的output的值。得到的值類型均爲 numpy.ndarray ,能夠經過這個輸出來完成自定義的評估指標計算等功能。例以下面代碼:
def score_diff(right_score, left_score):
return np.average(np.abs(right_score - left_score))
def event_handler(event):
if isinstance(event, paddle.event.EndIteration):
if event.batch_id % 25 == 0:
diff = score_diff(
event.gm.getLayerOutputs("right_score")["right_score"][
"value"],
event.gm.getLayerOutputs("left_score")["left_score"][
"value"])
logger.info(("Pass %d Batch %d : Cost %.6f, "
"average absolute diff scores: %.6f") %
(event.pass_id, event.batch_id, event.cost, diff))
注意:此方法不能獲取 paddle.layer.recurrent_group 裏step的內容,但能夠獲取 paddle.layer.recurrent_group 的輸出。
|6. 如何在訓練過程當中得到參數的權重和梯度
在某些狀況下,得到當前mini-batch的權重(或稱做weights, parameters)有助於在訓練時觀察具體數值,方便排查以及快速定位問題。 能夠經過在 event_handler 中打印其值(注意,須要使用 paddle.event.EndForwardBackward 保證使用GPU訓練時也能夠得到), 示例代碼以下:
...
parameters = paddle.parameters.create(cost)
...
def event_handler(event):
if isinstance(event, paddle.event.EndForwardBackward):
if event.batch_id % 25 == 0:
for p in parameters.keys():
logger.info("Param %s, Grad %s",
parameters.get(p), parameters.get_grad(p))
注意:「在訓練過程當中得到某一個layer的output」和「在訓練過程當中得到參數的權重和梯度」都會形成訓練中的數據從C++拷貝到numpy,會對訓練性能形成影響。不要在注重性能的訓練場景下使用。
end
*原創貼,版權全部,未經許可,禁止轉載
*值班小Paddle:wangp
*歡迎在留言區分享您的觀點
本文分享 CSDN - 飛槳PaddlePaddle。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。