重磅百度开源分布式深度学习平台,挑战TensorFlow (教程)
Posted 新智元
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了重磅百度开源分布式深度学习平台,挑战TensorFlow (教程)相关的知识,希望对你有一定的参考价值。
1 新智元编译1
来源:Github,Hacker News,paddlepaddle.org
译者:胡祥杰
【新智元导读】今天百度开源深度学习平台Paddle。业内人士纷纷点赞:Paddle代码简洁、设计干净,没有太多的abstraction,速度比Tensorflow、Theano快,显存占用小,可多机多卡并行,支持CPU和GPU、文档比较全……Hacker News有评论,在不支持TensorFlow的中国,百度的Paddle或有机会获胜。百度一直说自己深耕深度学习,其技术水平如何,本次开源或可提供一些线索。
百度深度学习 PaddlePaddle (Parallel Distributed Deep Learning)是一个云端托管的分布式深度学习平台,对于序列输入、稀疏输入和大规模数据的模型训练有着良好的支持,支持GPU运算,支持数据并行和模型并行,仅需少量代码就能训练深度学习模型,大大降低了用户使用深度学习技术的成本。
根据百度官方网站的介绍,Paddle 有以下优势:
Github 上介绍,PaddlePaddle有以下特点:
灵活
PaddlePaddle支持大量的神经网络架构和优化算法。很容易安装复杂的模型,比如拥有注意力(attention)机制或者复杂记忆连接的神经机器翻译模型。
高效
为了利用异构计算资源的能力,PaddlePaddle中的每一级都会进行优化,其中包括计算、内存、架构和通信。以下 是几个例子:
通过SSE/AVX 内联函数、BLAS数据库(例如MKL,ATLAS,cuBLAS)或者定制化的CPU/GPU 核优化数字。
高度优化的递归网络,在没有padding 的情况下,也能处理不同长度的序列。
对拥有高维稀疏数据的模型进行局部优化和分布式训练。
可扩展
有了PaddlePaddle,使用多个CPU和GPU以及机器来加速训练可以变得很轻松。 PaddlePaddle 能通过优化通信,获得高吞吐量和性能。
与产品的连接
PaddlePaddle的部署也很简单。在百度,PaddlePaddle 已经被用于产品和服务中,拥有大量用户。应用场景包括广告点击率(CTR)预测、大规模图像分类、光学字符识别、搜索排名、计算机病毒检测、推荐等等。PaddlePaddle 在百度有着巨大的影响。
Facebook 深度学习研究员贾扬清在知乎上评价说:今天刚看到的,简单说一些第一印象(以目前的github repo为准)。整体的设计感觉和Caffe心有灵犀,同时解决了Caffe早期设计当中的一些问题(比如说default stream)。
总的来说, Paadle是百度使用了多年的深度学习平台,并且已经做出了一些实际的产品,较为成熟。在性能和各项指标上,比如:代码简洁、设计很干净,没有太多的abstraction、 速度比tensorflow,theano快,显存占用小、可多机多卡并行,支持cpu和gpu、文档比较全等等,Paddle也获得了较高的肯定,是一个不错的深度学习工具,在国内有较大的应用潜力。
附:PaddlePaddle快速入门教程 http://www.paddlepaddle.org/doc_cn/
我们以文本分类问题作为背景,介绍PaddlePaddle使用流程和常用的网络基础单元的配置方法。
安装(Install)
首先请参考安装教程安装PaddlePaddle。
使用概述(Overview)
文本分类问题:对于给定的一条文本, 我们从提前给定的类别集合中选择其所属类 别。比如通过用户对电子商务网站评论,评估产品的质量:
这个显示器很棒! (好评)
用了两个月之后这个显示器屏幕碎了。(差评)
每一个任务流程都可以分为如下5个基础部分。
数据格式准备
每行保存一条样本,类别Id 和文本信息用Tab间隔, 文本中的单词用空格分隔(如果不切词,则字与字之间用空格分隔),例如:
类别Id‘\t’ 这 个 显 示 器 很 棒 !
数据向模型传送
PaddlePaddle可以读取Python写的传输数据脚本,所有字符都将转换为连续整数表示的Id传给模型
网络结构(由易到难展示4种不同的网络配置)
逻辑回归模型
词向量模型
卷积模型
时序模型
优化算法
训练模型
预测
数据格式准备(Data Preparation)
在本问题中,我们使用Amazon电子产品评论数据, 将评论分为好评(正样本)和差评(负样本)两类。demo/quick_start
里提供了数据下载脚本 和预处理脚本。
cd demo/quick_start
./data/get_data.sh
pip install -r requirements.txt
./preprocess.sh
数据向模型传送(Transfer Data to Model)
Python数据加载脚本(Data Provider Script)
下面dataprovider_bow.py文件给出了完整例子,主要包括两部分:
initalizer: 定义文本信息、类别Id的数据类型。
process: yield文本信息和类别Id,和initalizer里定义顺序一致。
from paddle.trainer.PyDataProvider2 import *# id of the word not in dictionaryUNK_IDX = 0# initializer is called by the framework during initialization.# It allows the user to describe the data types and setup the# necessary data structure for later use.# `settings` is an object. initializer need to properly fill settings.input_types.# initializer can also store other data structures needed to be used at process().# In this example, dictionary is stored in settings.# `dictionay` and `kwargs` are arguments passed from trainer_config.lr.pydef initializer(settings, dictionary, **kwargs): # Put the word dictionary into settings
settings.word_dict = dictionary # setting.input_types specifies what the data types the data provider
# generates.
settings.input_types = [ # The first input is a sparse_binary_vector,
# which means each dimension of the vector is either 0 or 1. It is the
# bag-of-words (BOW) representation of the texts.
sparse_binary_vector(len(dictionary)), # The second input is an integer. It represents the category id of the
# sample. 2 means there are two labels in the dataset.
# (1 for positive and 0 for negative)
integer_value(2)]# Delaring a data provider. It has an initializer 'data_initialzer'.# It will cache the generated data of the first pass in memory, so that# during later pass, no on-the-fly data generation will be needed.# `setting` is the same object used by initializer()# `file_name` is the name of a file listed train_list or test_list file given# to define_py_data_sources2(). See trainer_config.lr.py.@provider(init_hook=initializer, cache=CacheType.CACHE_PASS_IN_MEM)def process(settings, file_name): # Open the input data file.
with open(file_name, 'r') as f: # Read each line.
for line in f: # Each line contains the label and text of the comment, separated by \t.
label, comment = line.strip().split('\t') # Split the words into a list.
words = comment.split() # convert the words into a list of ids by looking them up in word_dict.
word_vector = [settings.word_dict.get(w, UNK_IDX) for w in words] # Return the features for the current comment. The first is a list
# of ids representing a 0-1 binary sparse vector of the text,
# the second is the integer id of the label.
yield word_vector, int(label)
配置中的数据加载定义(Data Provider in Configure)
在模型配置中利用define_py_data_sources2
加载数据:
from paddle.trainer_config_helpers import *file = "data/dict.txt"word_dict = dict()with open(dict_file, 'r') as f: for i, line in enumerate(f):
w = line.strip().split()[0]
word_dict[w] = i# define the data sources for the model.# We need to use different process for training and prediction.# For training, the input data includes both word IDs and labels.# For prediction, the input data only includs word Ids.define_py_data_sources2(train_list='data/train.list',
test_list='data/test.list',
module="dataprovider_bow",
obj="process",
args={"dictionary": word_dict})
data/train.list,data/test.list: 指定训练、测试数据
module=”dataprovider”: 数据处理Python文件名
obj=”process”: 指定生成数据的函数
args={“dictionary”: word_dict}: 额外的参数,这里指定词典
更详细用例请参考文档Python Use Case, 数据格式和详细文档请参考 PyDataProviderWrapper。
网络结构(Network Architecture)
本节我们将专注于网络结构的介绍。
我们将以基本的逻辑回归网络作为起点,并逐渐展示更加深入的功能。更详细的网络配置 连接请参考Layer文档。 所有配置在demo/quick_start
目录,首先列举逻辑回归网络。
逻辑回归模型(Logistic Regression)
流程如下:
获取利用one-hot vector表示的每个单词,维度是词典大小
word = data_layer(name="word", size=word_dim)
获取该条样本类别Id,维度是类别个数。
label = data_layer(name="label", size=label_dim)
利用逻辑回归模型对该向量进行分类,同时会计算分类准确率
# Define a fully connected layer with logistic activation (also called softmax activation).output = fc_layer(input=word,
size=label_dim,
act_type=SoftmaxActivation())# Define cross-entropy classification loss and error.classification_cost(input=output, label=label)
input: 除过data层,每个层都有一个或多个input,多个input以list方式输入
size: 该层神经元个数
act_type: 激活函数类型
效果总结:我们将在后面介绍训练和预测的流程的脚本。在此为方便对比不同网络结构, 我们随时总结了各个网络的复杂度和效果。
网络名称 | 参数数量 | 错误率 |
---|---|---|
逻辑回归 | 252 KB | 8.652% |
词向量模型(Word Vector)
embeding模型需要稍微改变数据提供的脚本,即dataprovider_emb.py
,词向量模型、 卷积模型、时序模型均使用该脚
文本输入类型定义为整数类型integer_value
设置文本输入类型seq_type为SequenceType.SEQUENCE
def initializer(settings, dictionary, **kwargs):
settings.word_dict = dictionary
settings.input_types = [ # Define the type of the first input as sequence of integer.
integer_value(len(dictionary), seq_type=SequenceType.SEQUENCE), # Define the second input for label id
integer_value(2)]@provider(init_hook=initializer)def process(settings, file_name): ...
# omitted, it is same as the data provider for LR model
该模型依然是使用逻辑回归分类网络的框架, 只是将句子利用连续向量表示替换稀疏 向量表示, 即对第3步进行替换。句子表示的计算更新为2步:
利用单词Id查找对应的该单词的连续表示向量(维度为word_dim), 输入N个单词,输出为N个word_dim维度向量
emb = embedding_layer(input=word, size=word_dim)
将该句话包含的所有单词向量求平均得到句子的表示
avg = pooling_layer(input=emb, pooling_type=AvgPooling())
其它部分和逻辑回归网络结构一致。 效果总结:
网络名称 | 参数数量 | 错误率 |
---|---|---|
词向量模型 | 15 MB | 8.484% |
卷积模型(Convolution)
卷积网络是一种特殊的从词向量表示到句子表示的方法, 也就是将词向量模型额步 骤3-2进行进一步演化, 变为3个新的子步骤。
文本卷积分为三个步骤:
获取每个单词左右各k个近邻, 拼接成一个新的向量表示;
对该表示进行非线性变换 (例如Sigmoid变换), 成为维度为hidden_dim的新的向量;
在每个维度上取出在该句话新的向量集合上该维度的最大值作为最后的句子表示向量。 这3个子步骤可配置为:
text_conv = sequence_conv_pool(input=emb,
context_start=k,
context_len=2 * k + 1)
效果总结:
网络名称 | 参数数量 | 错误率 |
---|---|---|
卷积模型 | 16 MB | 5.628% |
时序模型(Time Sequence)
时序模型即为RNN模型, 包括简单的RNN模型、GRU模型、LSTM模型等。
GRU模型配置:
gru = simple_gru(input=emb, size=gru_size)
LSTM模型配置:
lstm = simple_lstm(input=emb, size=lstm_size)
针对本问题,我们采用单层LSTM模型,并使用了Dropout,效果总结:
网络名称 | 参数数量 | 错误率 |
---|---|---|
时序模型 | 16 MB | 4.812% |
优化算法(Optimization Algorithm)
优化算法包括 Momentum, RMSProp,AdaDelta,AdaGrad,ADAM,Adamax等,这里采用Adam优化方法,加了L2正则和梯度截断。
settings(batch_size=128,
learning_rate=2e-3,
learning_method=AdamOptimizer(),
regularization=L2Regularization(8e-4),
gradient_clipping_threshold=25)
训练模型(Training Model)
在完成了数据和网络结构搭建之后, 我们进入到训练部分。
训练脚本:我们将训练的命令行保存在了 train.sh
文件中。训练时所需设置的主要参数如下:
paddle train \--config=trainer_config.py \--log_period=20 \--save_dir=./output \--num_passes=15 \--use_gpu=false
这里没有介绍多机分布式训练,可以参考分布式训练的demo学习如何进行多机训练。
预测(Prediction)
可以使用训练好的模型评估带有label的验证集,也可以预测没有label的测试集。
测试脚本如下,将会测试配置文件中test.list指定的数据。
paddle train \--use_gpu=false \--job=test \--init_model_path=./output/pass-0000x
可以参考Python API预测 教程,或其他demo的Python预测过程。也可以通过如下方式预测。
预测脚本(predict.sh
):
model="output/pass-00003"paddle train \
--config=trainer_config.lstm.py \
--use_gpu=false \
--job=test \
--init_model_path=$model \
--config_args=is_predict=1 \
--predict_output_dir=. \mv rank-00000 result.txt
与训练网络配置不同的是:无需label相关的层,指定outputs输出概率层(softmax输出), 指定batch_size=1,数据传输无需label数据,预测数据指定test_list的位置。
is_predict = get_config_arg('is_predict', bool, False)trn = 'data/train.list' if not is_predict else Nonetst = 'data/test.list' if not is_predict else 'data/pred.list'obj = 'process' if not is_predict else 'process_pre'batch_size = 128 if not is_predict else 1if is_predict:
maxid = maxid_layer(output)
outputs([maxid,output])else:
label = data_layer(name="label", size=2)
cls = classification_cost(input=output, label=label)
outputs(cls)
总体效果总结(Summary)
这些流程中的数据下载、网络配置、训练脚本在/demo/quick_start
目录,我们在此总 结上述网络结构在Amazon-Elec测试集(25k)上的效果:
网络名称 | 参数数量 | 错误率 | 配置文件 |
---|---|---|---|
逻辑回归模型 | 252KB | 8.652% | trainer_config.lr.py |
词向量模型 | 15MB | 8.484% | trainer_config.emb.py |
卷积模型 | 16MB | 5.628% | trainer_config.cnn.py |
时序模型 | 16MB | 4.812% | trainer_config.lstm.py |
附录(Appendix)
命令行参数(Command Line Argument)
–config:网络配置
–save_dir:模型存储路径
–log_period:每隔多少batch打印一次日志
–num_passes:训练轮次,一个pass表示过一遍所有训练样本
–config_args:命令指定的参数会传入网络配置中。
–init_model_path:指定初始化模型路径,可用在测试或训练时指定初始化模型。
默认一个pass保存一次模型,也可以通过saving_period_by_batches设置每隔多少batch保存一次模型。 可以通过show_parameter_stats_period设置打印参数信息等。 其他参数请参考令行参数文档。
输出日志(Log)
TrainerInternal.cpp:160] Batch=20 samples=2560 AvgCost=0.628761 CurrentCost=0.628761 Eval: classification_error_evaluator=0.304297 CurrentEval: classification_error_evaluator=0.304297
模型训练会看到这样的日志,详细的参数解释如下面表格:
名称 | 解释 |
---|---|
Batch=20 | 表示过了20个batch |
samples=2560 | 表示过了2560个样本 |
AvgCost | 每个pass的第0个batch到当前batch所有样本的平均cost |
CurrentCost | 当前log_period个batch所有样本的平均cost |
Eval: classification_error_evaluator | 每个pass的第0个batch到当前batch所有样本的平均分类错误率 |
CurrentEval: classification_error_evaluator | 当前log_period个batch所有样本的平均分类错误率 |
【号外】由中国自动化学会和新智元联合主办的AI全球年度盛典『AI WORLD 2016世界人工智能大会』即将盛大开幕。大会官网:http://aiworld2016.com/
更多详情,点击“阅读原文”,查看大会官网
以上是关于重磅百度开源分布式深度学习平台,挑战TensorFlow (教程)的主要内容,如果未能解决你的问题,请参考以下文章
重磅 | PaddlePaddle之后,百度开源深度学习硬件基准DeepBench
重磅Facebook 开源产业级深度学习框架 Caffe2,带来跨平台机器学习工具