百度飞浆学习(二)

本文参考链接:https://www.paddlepaddle.org.cn/documentation/docs/zh/beginners_guide/programming_guide/programming_guide.html

1.数据的表示和定义:paddle以Tensor来表示数据,Tensor是神经网络中传递的一种数据格式,简单理解就是多维数组

../../../_images/tensor.jpg

2. 使用paddle来创建数据(两种方式):

方式一:

fluid.data(name, shape, dtype='float32', lod_level=0)

方式二:

fluid.layers.fill_constant.fill_constant(shape, dtype, value, force_cpu=False, out=None)

使用方式二创建一个维度为[3, 4], 数据类型为int64的Tensor,其中所有元素均为16的代码如下

import paddle.fluid as fluid

data = fluid.layers.fill_constant(shape=[3, 4], value=16, dtype='int64')
print(data)

打印结果为

name: "fill_constant_0.tmp_0"
type {
  type: LOD_TENSOR
  lod_tensor {
    tensor {
      data_type: INT64
      dims: 3
      dims: 4
    }
  }
}
persistable: false

在网络运行过程中如果要查看Tensor中的数值有两种方式

方式一:利用 paddle.fluid.layers.Print 创建一个打印操作, 打印正在访问的Tensor

例如:

import paddle.fluid as fluid

data = fluid.layers.fill_constant(shape=[3, 4], value=16, dtype='int64')
data = fluid.layers.Print(data, message="Print data:")

place = fluid.CPUPlace()
exe = fluid.Executor(place)
exe.run(fluid.default_startup_program())

ret = exe.run()

打印结果为:

1577945741	Print data:	The place is:CPUPlace
Tensor[fill_constant_0.tmp_0]
	shape: [3,4,]
	dtype: __int64
	data: 16,16,16,16,16,16,16,16,16,16,16,16,

方式二为直接将变量添加到fetch_list中,后面再示例

3.组建网络

目标是实现一个加法运算,而在paddle中,关于计算类的API函数大多在paddle.fluid.layers 模块中

下面通过paddle.fluid.layers.elementwise_add()来实现用户输入数据的加法计算

例如:

import paddle.fluid as fluid

# 定义变量
a = fluid.data(name="a", shape=[None, 1], dtype='int64')
b = fluid.data(name="b", shape=[None, 1], dtype='int64')

# 组建网络(此处网络仅由一个操作构成,即elementwise_add)
result = fluid.layers.elementwise_add(a,b)

# 准备运行网络
cpu = fluid.CPUPlace() # 定义运算设备,这里选择在CPU下训练
exe = fluid.Executor(cpu) # 创建执行器
exe.run(fluid.default_startup_program()) # 网络参数初始化

# 读取输入数据
import numpy
data_1 = int(input("Please enter an integer: a="))
data_2 = int(input("Please enter an integer: b="))
x = numpy.array([[data_1]])
y = numpy.array([[data_2]])

# 运行网络
outs = exe.run(
    feed={'a':x, 'b':y}, # 将输入数据x, y分别赋值给变量a,b
    fetch_list=[result] # 通过fetch_list参数指定需要获取的变量结果
    )

# 输出计算结果
print("%d+%d=%d" % (data_1,data_2,outs[0][0]))

出错了,看了下错误信息

我将a,b的变量类型都改为了int32,再次运行

有结果了,不过有警告,看不懂,先不管

这时如果想要获取在网络运行中a,b的值,可以将a,b一并加入到fetch_list中

例如:

# 运行网络
outs = exe.run(
    feed={'a':x, 'b':y}, # 将输入数据x, y分别赋值给变量a,b
    fetch_list=[a,b,result] # 通过fetch_list参数指定需要获取的变量结果
    )

print(outs)
# 输出计算结果

结果为:

[array([[6]], dtype=int32), array([[7]], dtype=int32), array([[13]], dtype=int32)]

4.组建更复杂的网络

Paddle提供顺序、分支和循环三种执行逻辑,用户可以通过组合描述任意复杂的模型

顺序执行:
 

##定义一个数据类型为float32的二维数据组变量x,第一维的维度是未知的,第二维维度是13,所以x的形状可以表示为[None, 13]
x = fluid.data(name='x', shape=[None, 13], dtype='float32')
#预测的y值
y_predict = fluid.layers.fc(input=x, size=1, act=None)
##定义一个数据类型为float32的二维数据组变量y,第一维的维度是未知的,第二维维度是1,所以x的形状可以表示为[None, 1]
#喂入神经网络的y
y = fluid.data(name='y', shape=[None, 1], dtype='float32')
# 计算cost
cost = fluid.layers.square_error_cost(input=y_predict, label=y)

条件分支:
Paddle提供了 fluid.layers.Switch 和 fluid.layers.IfElse 两个API来实现条件分支的操作

ifelse

class paddle.fluid.layers.IfElse(cond, name=None)

这个类用于实现paddle的条件分支,每个IFElse包含两个block,true_block和false_block,cond为条件,条件符合则执行true_block中的语句块,不符合则执行false_block中的语句块,cond是一个shape为[N,1],数据类型为bool的二维数组

例如:

# 以下代码完成的功能:对x中大于0的数据减去10,对x中小于0的数据加上10,并将所有的数据求和
import numpy as np
import paddle.fluid as fluid

x = fluid.layers.data(name='x', shape=[4,1], append_batch_size=False, dtype='float32')
y = fluid.layers.data(name='y', shape=[4,1], append_batch_size=False, dtype='float32')

x_d = np.array([[3], [1], [-2], [-3]]).astype(np.float32)
y_d = np.zeros((4, 1)).astype(np.float32)

# 比较x, y对元素的大小,输出cond, cond是shape为[4, 1],数据类型为bool的2-D tensor。
# 根据输入数据x_d, y_d,可以推断出cond中的数据为[[true], [true], [false], [false]]
cond = fluid.layers.greater_than(x, y)

# 同其他常见OP不同的是,该OP返回的ie是一个IfElse OP的对象
ie = fluid.layers.IfElse(cond)

with ie.true_block():
    # 在这个block中,根据cond条件,获取x中对应条件为true维度的数据,并减去10
    out_1 = ie.input(x)
    out_1 = out_1 - 10
    ie.output(out_1)

with ie.false_block():
    # 在这个block中,根据cond条件,获取x中对应条件为false维度的数据,并加上10
    out_1 = ie.input(x)
    out_1 = out_1 + 10
    ie.output(out_1)
# 根据cond条件将两个block中处理后的数据进行合并,此处的output为输出,类型为List,List中的元素类型为Variable。
output = ie() #  [array([[-7.], [-9.], [ 8.], [ 7.]], dtype=float32)]

# 将输出List中的第一个Variable获取出来,并计算所有元素和
out = fluid.layers.reduce_sum(output[0])
exe = fluid.Executor(fluid.CPUPlace())
exe.run(fluid.default_startup_program())

res = exe.run(fluid.default_main_program(), feed={"x":x_d, "y":y_d}, fetch_list=[out])
print(res)
# [array([-1.], dtype=float32)]

内部函数:

通过调用对象中的 with ie.true_block() 函数构建block,将条件为true下的计算逻辑放入此block中。如果没有构建相应的block,则对应条件维度下的输入数据不做改变。
通过调用对象中的 with ie.false_block() 函数构建block,将条件为false下的计算逻辑放入此block中。如果没有构建相应的block,则对应条件维度下的输入数据不做改变。
out = ie.input(x) 会将x中对应条件维度的数据获取出来放入到out中,支持block内部处理多个输入。
ie.output(out) 会将结果写入对应条件的输出中。
对象内部有 __call__() 函数,即通过对 output = ie() 的调用,将条件分别为True,False的block内部所有的输出进行融合作为整体的输出,输出的类型为列表,列表中每个元素的类型为Variable。

循环

while:

class paddle.fluid.layers.While(cond, is_test=False, name=None)

该类用于实现while循环控制功能,只要循环条件cond为True,就循环执行while循环体中的语句,直到cond为False为止。

参数:
cond (Variable) – 用于判断循环继续进行的条件,为数据类型bool型的Tensor,其shape必须为[1]。
is_test (bool,可选) – 用于表明是否在测试阶段执行,默认值为False。
name (str,可选) - 具体用法请参见 Name ,一般无需设置,默认值为None。

例如:
 

# 该示例代码展示整数循环+1,循环10次,输出计数结果
import paddle.fluid as fluid
import numpy as np

i = fluid.layers.fill_constant(shape=[1], dtype='int64', value=0)           # 循环计数器

loop_len = fluid.layers.fill_constant(shape=[1],dtype='int64', value=10)    # 循环次数

cond = fluid.layers.less_than(x=i, y=loop_len)              # 循环条件 比较i和loop_len
while_op = fluid.layers.While(cond=cond)
with while_op.block():  # 循环体
    i = fluid.layers.increment(x=i, value=1, in_place=True) #往上计数加1
    fluid.layers.less_than(x=i, y=loop_len, cond=cond)      # 更新循环条件

exe = fluid.Executor(fluid.CPUPlace())
exe.run(fluid.default_startup_program())

res = exe.run(fluid.default_main_program(), feed={}, fetch_list=[i])
print(res) # [array([10])]

5.一个完整的网络示例

一个典型的模型通常包括4个部分:输入数据定义,搭建网络(模型前向计算逻辑),定义损失函数,选择优化算法

下面通过一个简单的数据预测网络(线性回归),来完整的展示如何使用Paddle静态图方式完成一个深度学习模型的组建和训练

问题描述:给定一组数据<X,Y>,求解出函数f, 使得y = f(x),其中X,Y均为一维张量, 最终网络可以依据输入x,准确预测出y(predict),

例如:

import paddle.fluid as fluid
import numpy

# 1.定义输入变量
# 假设输入数据X=[1 2 3 4],Y=[2 4 6 8],在网络中定义:
train_data = numpy.array([[1.0], [2.0], [3.0], [4.0]]).astype('float32')
y_true = numpy.array([[2.0], [4.0], [6.0], [8.0]]).astype('float32')

# 2.搭建网络(定义前向计算逻辑)
#
# 接下来需要定义预测值与输入的关系,本次使用一个简单的线性回归函数进行预测:
x = fluid.data(name='x', shape=[None, 1], dtype='float32')
y = fluid.data(name='y', shape=[None, 1], dtype='float32')

y_predict = fluid.layers.fc(input=x, size=1, act=None)

# 3.添加损失函数
# 完成模型搭建后,如何评估预测结果的好坏呢?我们通常在设计的网络中添加损失函数,以计算真实值与预测值的差。
# 在本例中,损失函数采用均方差函数:
#定义损失函数
cost = fluid.layers.square_error_cost(input=y_predict, label=y)
avg_cost = fluid.layers.mean(cost)


# 4.网络优化 
# 确定损失函数后,可以通过前向计算得到损失值,并根据损失值对网络参数进行更新,
# 最简单的算法是随机梯度下降法:w=w−η⋅g,由 fluid.optimizer.SGD 实现:
#选择优化方法
sgd_optimizer = fluid.optimizer.SGD(learning_rate=0.01)
sgd_optimizer.minimize(avg_cost)

#网络参数初始化
cpu = fluid.CPUPlace()
exe = fluid.Executor(cpu)
exe.run(fluid.default_startup_program())

#开始训练,迭代100次
for i in range(100):
    outs = exe.run(
        feed={'x':train_data, 'y':y_true},
        fetch_list=[y_predict, avg_cost])

print(outs)#输出如下:
'''
[array([[2.2844574],
       [4.137839 ],
       [5.9912205],
       [7.8446016]], dtype=float32), array([0.03103533], dtype=float32)]
'''

可以看到迭代100次后,预测值y(predict)与真实值y_true已经差别不大
 

发布了17 篇原创文章 · 获赞 8 · 访问量 2649

猜你喜欢

转载自blog.csdn.net/qq_39295354/article/details/103803254