PaddlePaddle Reader、Program、Scope使用

为了防止在应该Python文件中执行多个PaddlePaddle程序时出现问题,这里将会简单介绍Program和Scope的使用。
本篇以线性回归任务为例,py_reader(异步读取数据)、xmap(多线程预处理方案)、name_scope(局部命名空间)等操作将在接下来的文章中介绍。
点击回顾上节线性回归任务

构建标准的数据读取器--Reader

如果是像上节那样,先准备好所有的数据,然后对这些已经加载到内存的数据进行处理。这些操作在其它任务中(图像分类、
目标检测等)将会占用大量计算机资源。
除此之外,一般在进行读取数据时候可能还需要打乱数据等操作,便捷的调节Batch_size也将会让你在调试时可以更加轻松。

1、定义数据读取

构建Reader还是非常简单的,下面提供一个模版来举例。

def reader():
    def req_one_data():
            # 数据的读取、预处理部分(如果想多进程预处理可以考虑使用xmap,但大多数场景不需要这样做)
            # 单条数据返回部分 yield XXX,XXX,XXX    
    return req_one_data     # 返回这个函数的变量名

以上节的线性回归任务为例,因为我们要构造一个y = 10x +3的数据集,喂给神经网络x让它吐出y。

def reader():
    def req_one_data():
        for i in range(10):
            data_X = [i]        
            data_Y = [i * 10 + 3]
            data_X = np.array(data_X).reshape(1, 1).astype("float32")    
            data_Y = np.array(data_Y).reshape(1, 1).astype("float32")
            yield data_X, data_Y    # 使用yield来返回单条数据

    return req_one_data    # 返回 req_one_data 这个变量名!可不是req_one_data()

这里我们构造出单挑数据data_X、data_Y之后,因为需要使用yield返回的是numpy的array对象,所以提前使用np.array使单条数据变成array对象。
为什么要对array对象使用.reshape(1, 1)呢?不是一维数组吗?怎么要设定两个维度?
因为我们在定义张量的时候默认会在shape的第一维加入-1来表示Batch_size的大小
定义时是x = fluid.layers.data(name="x", shape=[1], dtype="float32")
实际上是x = fluid.layers.data(name="x", shape=[-1,1], dtype="float32")
但我们在使用yield返回array对象时,并不会默认增加应该维度表示Batch_size,所以我们需要手动添加这个维度,因此我们需要np.array(XXX).reshape(1, 1)

2、定义数据传输格式

在我们定义好Reader的读取后,我们还可以对Batch进行一些操作,比方说设置Batch_size、动态打乱数据集。

train_reader = paddle.batch(reader=reader(), batch_size=10)

注意 reader=reader(),这个reader()是刚刚定义的那个数据读取函数,而且是带()的,可不是变量名!

如果想对数据集进行动态打乱,只需要将train_reader变成下面的样子就可以了。

train_reader = paddle.batch(reader=paddle.reader.shuffle(reader(), buf_size), batch_size=10)

这里的buf_size则是打乱的缓冲器大小。
例如设置为10,则对每10个数据进行打乱一次。

3、定义数据输入格式

还记得上节的info = exe.run(feed={"x": x_, "y": y_}...吗?使用字典来传参是不是不太美观?
试试这个!

train_feeder = fluid.DataFeeder(feed_list=[x, y], place=place, program=hi_ai_program)

feed_list里就是我们所定义张量的变量名,顺序是yield返回数据的顺序。
place是最开始定义的训练环境。
program是作用的项目名称,如果你不了解这个,可以不写。

4、修改训练部分的代码

# 开始训练
for epoch in range(100):
    for data in train_reader():
        info = exe.run(feed=train_feeder.feed(data),
                       fetch_list=[loss])

(是不是感觉有点迷?贴上完整代码!)

import paddle.fluid as fluid
import paddle
import numpy as np


# 重写Reader
def reader():
    def req_one_data():
        for i in range(10):
            data_X = [i]
            data_Y = [i * 10 + 3]
            data_X = np.array(data_X).reshape(1, 1).astype("float32")
            data_Y = np.array(data_Y).reshape(1, 1).astype("float32")
            yield data_X, data_Y

    return req_one_data


# 初始化项目环境
hi_ai_program = fluid.Program()  # 空白程序
start_program = fluid.Program()  # 用于初始化框架的空白程序

with fluid.program_guard(main_program=hi_ai_program, startup_program=start_program):
    # 定义张量格式
    x = fluid.layers.data(name="x", shape=[1], dtype="float32")
    y = fluid.layers.data(name="y", shape=[1], dtype="float32")

    # 定义神经网络
    out = fluid.layers.fc(input=x, size=1)

    # 定义损失函数
    loss = fluid.layers.square_error_cost(input=out, label=y)
    avg_loss = fluid.layers.mean(loss)

    # 定义优化器
    opt = fluid.optimizer.SGD(learning_rate=0.01)
    opt.minimize(avg_loss)

# 初始化环境
place = fluid.CPUPlace()  # 初始化运算环境
exe = fluid.Executor(place)  # 初始化执行器
exe.run(start_program)

# 定义数据传输格式
train_reader = paddle.batch(reader=reader(), batch_size=10)
train_feeder = fluid.DataFeeder(feed_list=[x, y], place=place, program=hi_ai_program)

# 开始训练
for epoch in range(100):
    for data in train_reader():
        info = exe.run(program=hi_ai_program,
                       feed=train_feeder.feed(data),
                       fetch_list=[loss])

划分项目空间

有没有感觉上面代码有些陌生?
fluid.program_guard和fluid.Program()又是什么鬼?
为什么要划分项目空间?

PaddlePaddle默认空间示例

初次看这张图会比较懵逼,因为你还不了解划分这些框框能帮到你什么。
上节在数据集方面提到了训练集和交叉验证集,在训练过程中交叉验证集能评估当前训练的拟合情况,但它本身并不参与反向传播(学习)的过程。
如果你的项目中包含了反向传播,那么交叉验证集就没办法正在进行了。此时我们可以划分项目空间来确定不同数据集在哪种策略上进行。
图中的default_program就是默认的项目空间,因为是默认的,所以在你创建Python文件并导入paddle时它就已经存在了。如果不想使用这个项目空间,则要单独创建一个新空间则需要使用XXX = fluid.Program()来创建,然后使用with关键字来打开项目进行编辑

with fluid.program_guard(main_program=hi_ai_program, startup_program=start_program):
        #定义张量、loss、acc等操作

main_program是需要编辑的项目,startup_program是用做初始化参数的项目,先别急,下方会有介绍。
如果你要定义交叉验证集的程序,则只需要新建一个这样的训练项目空间,将训练时定义的优化器代码删去就不会进行反向传播了。
实际上PaddlePaddle提供了更简单的方法来创建交叉验证集项目,只需要eval = train_prog.clone(for_test = True)就会生成一个没有反向传播等操作的新项目空间,并取名为你所定义的那个变量名。

但需要注意的是,如果你习惯了使用default_program,而突然因为某某特殊情况来使用新项目空间,在执行exe.run、fluid.io.save_xxx等操作时可能会漏掉program参数,例如:

fluid.io.save_inference_model(dirname="infer.model",
                              feeded_var_names=["x"],
                              target_vars=[out],
                              executor=exe,
                              main_program=hi_ai_program)    # 如果是使用default_program则这一行可以忽略

那start_program又是干什么用的呢?它是用来初始化神经网络参数而准备的,它可以是一个空白的Program。
当然训练时候需要你去初始化参数,预测就不需要再初始化了,因为预测只需要你加载参数。

Scope

当你想要在一个Python中加载两个预测模型该怎么办?两个Program就可以了吗?
但实际上由于PaddlePaddle的设计,加载多个模型会替换Scope里面全局变量,可能会有冲突。
所以,为了避免冲突,可以使用Scope和with关键字来划分总体的空间,每个新Scope就像是一个新的Python文件,不必再将训练和预测分成两个Python文件来执行了~

至此,Reader、Program、Scope的简介也就大概这些内容了,如果对这些不了解也没问题,等你需要用到的时候知道有这样的用法就足够了。

当然,如果想一次性获取全部代码,可以点击下方GitHub链接,希望看到你的Star哟~
https://github.com/GT-ZhangAcer/DLExample/tree/master/easy02_Hi_AI

文章不定期更新,欢迎关注!
点击进入简书PaddlePaddle入门专题页面,获取完整教程信息
点击进入往期PaddlePaddle文章、极简入门专题页面

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

推荐阅读更多精彩内容