PaddlePaddle

前言

转载于https://blog.csdn.net/tangxiaoyin/article/details/80132220

这将是 PaddlePaddle 系列教程的开篇,属于非官方教程。既然是非官方,自然会从一个使用者的角度出发,来教大家怎么用,会有哪些坑,以及如何上手并用到实际项目中去。

我之前写过一些关于 tensorflow 的教程,在我的简书上可以找到,非常简单基础的一个教程,但是备受好评,因为国内实在是很难找到一个系列的关于这些深度学习框架的教程。因此在这里,我来给 PaddlePaddle 也写一个类似的教程,不复杂,三行代码入门。

三行代码 PaddlePaddle 从入门到精通

PaddlePaddle 是百度大力推出的一个框架,不得不说相比于 tensorflow,PaddlePaddle 会简单很多,接下来我会细说。同时百度在人工智能方面的功底还是非常深厚,我曾经在腾讯实习,类似于 AT 这样的公司,甚至没有一个非常成型的框架存在。

既然是三行代码精通 PaddlePaddle,那么得安装一下 PaddlePaddle。就目前来说,最好的办法是 build from source。步骤如下 (注意,这里是 CPU 版本,GPU 版本的源码编译过程后续补充,我们先用 CPU 来熟悉 API):

# clone 最新代码到 paddle
git clone https://github.com/PaddlePaddle/Paddle paddle
cd paddle
mkdir build
cd build
make all -j8
sudo make install

# 安装 python 接口,注意 paddlepaddle 目前貌似只支持 python2,因此在写脚本的时候一定要兼容一下 python3
# 这里是 mac 的情况下,如果是 ubuntu /usr/local/opt  应该直接是/opt/
sudo python -m pip install /usr/local/opt/paddle/share/wheels/*.whl
# 或者直接
sudo pip2 install /usr/local/opt/paddle/share/wheels/*.whl
20171013100600335.jpeg

好了,看上去应该算是安装完了。接下来我们用三行代码来测试一下?


20171013100727491.jpeg

PaddlePaddle 在 python API 上 0.10 有较大的变化,所以直接 import 一下 v2 版本的 API。如果可以说明 PaddlePaddle 安装没有问题。这里赞一下百度的技术功底和用户体验,这尼玛要是 caffe 或者 caffe2 编译出错概率 100%不说,python 安装了也不能 import,PaddlePaddle 一步到位,非常牛逼。

闲话不多说,直接三行代码来熟悉一下 PaddlePaddle 的 API。

三行代码来了

接下来要做的事情是,用 PaddlePaddle 搭建一个 3 层 MLP 网络,跑一个二维的 numpy 随机数据,来了解一下 PaddlePaddle 从数据喂入到训练的整个 pipeline 吧。

首先我们这个教程先给大家展示一个图片分类器,用到的数据集是 Stanford Dogs 数据集,下载链接,大概 800M, 同时下载一下 annotations, 大概 21M。下载好了我们用一个 paddle_test 的文件夹来做这个教程吧。

mkdir paddle_test
cd paddle_test
mkdir data

把所有的 images 和 annotations 扔到 data 里面去,解压一下:

paddle_test
└── data
    ├── annotation.tar
    └── images.tar

顺便说一下,这里的 annotations 是为后面用 paddlepaddle 做分割做准备,本次分类任务,只需要一个 images.tar 就可以了,所有图片被放在了该类别的文件夹下面,以后处理其他分类任务时,只需要把不同类别放在文件夹就 OK 了,甚至不用改代码,非常方便,这比 MXNet 要有道理很多,多数情况下我们根本不需要海量图片训练,也没有必要搞个什么 imrecord 的数据格式,MXNet 导入图片真心蛋疼,没有 Pytorch 方便,但是 Pytorch 得运行速度堪忧。

OK,将 images.tar 解压,会得到 120 个文件夹,也就是 120 个类别,每个类别里面都是一种狗狗图片。比如这张是一只 Beagle:


20171013100850064.jpeg

开始写三行代码

好了,开始写三行代码了。

def vgg_bn_drop(input_data):
def event_handler(event):
def train():

实际上 PaddlePaddle 的使用也就是三行代码的事情,首先是网络构建,这里我们构建一个 VGG 网络,其次是 event 的处理函数,这个机制是 PaddlePaddle 独有的,PaddlePaddle 把所有的训练过程都包装成了一个 trainer,然后调用这个 event_handler 来处理比如打印 loss 信息这样的事情。OK,我们一步一步来,先来看一下 train 的过程吧:

def train():
    data_dim = 3 * 32 * 32
    class_dim = 10
    image = paddle.layer.data(
        name="image", type=paddle.data_type.dense_vector(data_dim))
    net = vgg_bn_drop(image)
    out = paddle.layer.fc(input=net,
                          size=class_dim,
                          act=paddle.activation.Softmax())
    lbl = paddle.layer.data(
        name="label", type=paddle.data_type.integer_value(class_dim))
    cost = paddle.layer.classification_cost(input=out, label=lbl)
    parameters = paddle.parameters.create(cost)
    print(parameters.keys())
    momentum_optimizer = paddle.optimizer.Momentum(
        momentum=0.9,
        regularization=paddle.optimizer.L2Regularization(rate=0.0002 * 128),
        learning_rate=0.1 / 128.0,
        learning_rate_decay_a=0.1,
        learning_rate_decay_b=50000 * 100,
        learning_rate_schedule='discexp')
    # Create trainer
    trainer = paddle.trainer.SGD(cost=cost,
                                 parameters=parameters,
                                 update_equation=momentum_optimizer)
    reader = paddle.batch(
        paddle.reader.shuffle(
            paddle.dataset.cifar.train10(), buf_size=50000),
        batch_size=128)
    feeding = {'image': 0,
               'label': 1}
    trainer.train(
        reader=reader,
        num_passes=200,
        event_handler=event_handler,
        feeding=feeding)

PaddlePaddle 的网络训练流程分为几个步骤:

首先定义网络,这里的网络不包括最后一层的 softmax;
创建一个 cost,cost 当然就需要一个网络的输出和 lable 了;
通过这个 cost 来创建网络训练的参数,非常简单明了;
最后是优化器,这里定义反向传播的正则项,学习速率调整策略等;
通过上面这些创建一个 trainer;
最后这个 trainer 要训练起来,还需要持续的数据喂入,时间处理函数,和喂入的方式。
接着我们看一下网络定义和事件处理函数:

# define VGG network
def vgg_bn_drop(input_data):
    def convolution_block(ipt, num_filter, groups, dropouts, num_channels=None):
        return paddle.networks.img_conv_group(
            input=ipt,
            num_channels=num_channels,
            pool_size=2,
            pool_stride=2,
            conv_num_filter=[num_filter] * groups,
            conv_filter_size=3,
            conv_act=paddle.activation.Relu(),
            conv_with_batchnorm=True,
            conv_batchnorm_drop_rate=dropouts,
            pool_type=paddle.pooling.Max())
    convolution_1 = convolution_block(input_data, 64, 2, [0.3, 0], 3)
    convolution_2 = convolution_block(convolution_1, 128, 2, [0.4, 0])
    convolution_3 = convolution_block(convolution_2, 256, 3, [0.4, 0.4, 0])
    convolution_4 = convolution_block(convolution_3, 512, 3, [0.4, 0.4, 0])
    convolution_5 = convolution_block(convolution_4, 512, 3, [0.4, 0.4, 0])
    drop = paddle.layer.dropout(input=convolution_5, dropout_rate=0.5)
    fc1 = paddle.layer.fc(input=drop, size=512, act=paddle.activation.Linear())
    bn = paddle.layer.batch_norm(
        input=fc1,
        act=paddle.activation.Relu(),
        layer_attr=paddle.attr.Extra(drop_rate=0.5))
    fc2 = paddle.layer.fc(input=bn, size=512, act=paddle.activation.Linear())
    return fc2
def event_handler(event):
    if isinstance(event, paddle.event.EndIteration):
        if event.batch_id % 100 == 0:
            print("\nPass %d, Batch %d, Cost %f, %s" % (
                event.pass_id, event.batch_id, event.cost, event.metrics))
        else:
            sys.stdout.write('.')
            sys.stdout.flush()

这里我们先用 PaddlePaddle 内置的 cifar10 来测试一下能否训练起来,把上面的代码加上 import 之后:

from __future__ import print_function, division
import paddle.v2 as paddle
import sys
paddle.init(use_gpu=False, trainer_count=1)
if __name__ == '__main__':
    train()

在主函数里面运行 train()。见证奇迹的时刻到了。。

PaddlePaddle 开始下载数据,并打印出了网络结构!


20171013101152728.jpeg

20171013101309123.jpeg

接下来我们用这个代码来保存网络训练之后的权重:

try:
    trainer.train(
        reader=reader,
        num_passes=200,
        event_handler=event_handler,
        feeding=feeding)
except KeyboardInterrupt:
    with open('params_model.tar', 'w') as f:
        parameters.to_tar(f)

最后,模型 train 好之后,导入模型进行预测:

from __future__ import print_function
from PIL import Image
import numpy as np
import os
def load_image(file):
    im = Image.open(file)
    im = im.resize((32, 32), Image.ANTIALIAS)
    im = np.array(im).astype(np.float32)
    # PIL 打开图片存储顺序为 H(高度),W(宽度),C(通道)。
    # PaddlePaddle 要求数据顺序为 CHW,所以需要转换顺序。
    im = im.transpose((2, 0, 1)) # CHW
    # CIFAR 训练图片通道顺序为 B(蓝),G(绿),R(红),
    # 而 PIL 打开图片默认通道顺序为 RGB,因为需要交换通道。
    im = im[(2, 1, 0),:,:] # BGR
    im = im.flatten()
    im = im / 255.0
    return im
test_data = []
cur_dir = os.getcwd()
test_data.append((load_image(cur_dir + '/image/dog.png'),))
# with open('params_pass_50.tar', 'r') as f:
#    parameters = paddle.parameters.Parameters.from_tar(f)
probs = paddle.infer(
    output_layer=out, parameters=parameters, input=test_data)
lab = np.argsort(-probs) # probs and lab are the results of one batch data
print("Label of image/dog.png is: %d" % lab[0][0])

OK, 本次列车到此结束,对于 PaddlePaddle 如何训练一个图片分类器,应该有了一个清醒的认识.

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349

推荐阅读更多精彩内容