百度PaddlePaddle >>> 4. 快速入门

在这里插入图片描述
本文基于百度PaddlePaddle教程:https://aistudio.baidu.com/aistudio/projectdetail/350646

一、PaddlePaddle基础命令

在PaddlePaddle中,计算的对象是张量。
在这里插入图片描述

1. 计算常量的加法:1+1

使用PaddlePaddle来计算一个[[1, 1], [1, 1]] * [[1, 1], [1, 1]]

定义两个张量的常量x1和x2,并指定它们的形状是[2, 2],并赋值为1铺满整个张量,类型为int64:

import paddle.fluid as fluid

# 定义两个张量
x1 = fluid.layers.fill_constant(shape=[2, 2], value=1, dtype='int64')
x2 = fluid.layers.fill_constant(shape=[2, 2], value=1, dtype='int64')

接着定义一个操作,该计算是将上面两个张量进行加法计算,并返回一个求和的算子:

# 将两个张量求和
y1 = fluid.layers.sum(x=[x1, x2])

然后创建一个解释器,可以在这里指定计算使用CPU或GPU。当使用CPUPlace()时使用的是CPU,如果是CUDAPlace()使用的是GPU。
解析器是之后使用它来进行计算的,比如在执行计算之前我们要先执行参数初始化的program也是要使用到解析器的,因为只有解析器才能执行program

# 创建一个使用CPU的解释器
place = fluid.CPUPlace()
exe = fluid.executor.Executor(place)
# 进行参数初始化
exe.run(fluid.default_startup_program())

最后执行计算,program的参数值是主程序,不是上一步使用的是初始化参数的程序,program默认一共有两个,分别是default_startup_program()default_main_program()
fetch_list参数的值是在解析器在run之后要输出的值,我们要输出计算加法之后输出结果值。最后计算得到的也是一个张量。

# 进行运算,并把y的结果输出
result = exe.run(program=fluid.default_main_program(),
                    fetch_list=[y1])

print(result)

结果:
在这里插入图片描述
在这里插入图片描述

2. 计算变量的加法:1+1

和计算常量不同的是:计算变量是先定义好方程式,等到要计算的时候再把数据输入。

上面计算的是张量常量的1+1,并不能随意修改常量的值,所以下面我们要编写一个使用张量变量作为乘数的程序,类似是一个占位符,等到将要计算时,再把要计算的值添加到占位符中进行计算。

定义两个张量,并不指定该张量的形状和值,它们是之后动态赋值的。这里只是指定它们的类型和名字,这个名字是我们之后赋值的关键:

import paddle.fluid as fluid
import numpy as np

# 定义两个张量
a = fluid.layers.create_tensor(dtype='int64', name='a')
b = fluid.layers.create_tensor(dtype='int64', name='b')

同样定义这两个张量的加法操作:

# 将这两个张量求和
y = fluid.layers.sum(x=[a, b])

然后创建使用CPU 的解释器,并进行参数初始化:

# 创建一个使用CPU 的解释器
place = fluid.CPUPlace()
exe = fluid.executor.Executor(place)
# 进行参数初始化
exe.run(fluid.default_startup_program())

再使用numpy创建两个张量值,之后要计算的就是这两个值:

# 定义两个要计算的变量
a1 = np.array([3, 2]).astype('int64')
b1 = np.array([1, 1]).astype('int64')

这次exe.run()的参数有点不一样了,多了一个feed参数,这个就是要对张量变量进行赋值的。
赋值的方式是使用了键值对的格式,key是定义张量变量是指定的名称,value就是要传递的值。
在fetch_list参数中,笔者希望把a, b, y的值都输出来,所以要使用3个变量来接受返回值。

# 进行运算,并把y的结果输出
out_a, out_b, result = exe.run(program=fluid.default_main_program(),
                                feed={'a':a1, 'b':b1},
                                fetch_list=[a, b, y])
print(out_a, "+", out_b, "=", result)

结果:
在这里插入图片描述
在这里插入图片描述

二、使用PaddlePaddle做线性回归

先导入PaddlePaddle库和一些工具类库:

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

定义一个简单的线性网络,共有3层(输入层不计入)。具体的就是两个大小为100,激活函数是ReLU的全连接层和一个输出大小为1的全连接层。

这里使用输入fluid.layers.data()定义的输入层类似fluid.layers.create_tensor(),也是有name属性,之后也是根据这个属性来填充数据的。这里定义输入层的形状为13,这是因为后续需要用到的波士顿房价数据集的每条数据有13个属性,我们之后自定义的数据集也是为了符合这一个维度。

# 定义一个简单的线性网络
x = fluid.layers.data(name='x', shape=[13], dtype='float32')
hidden1 = fluid.layers.fc(input=x, size=100, act='relu')
hidden2 = fluid.layers.fc(input=hidden1, size=100, act='relu')
net = fluid.layers.fc(input=hidden2, size=1, act=None)

接着定义神经网络的损失函数,这里同样使用了fluid.layers.data()这个接口,这个可以理解为数据对应的结果,上面name为x的fluid.layers.data()为属性数据。这里使用了平方差损失函数(square_error_cost):

因为fluid.layers.square_error_cost()求的是一个Batch的损失值,所以我们还要对他求一个平均值。

# 定义损失函数
y = fluid.layers.data(name='y', shape=[1], dtype='float32')
cost = fluid.layers.square_error_cost(input=net, label=y)
avg_cost = fluid.layers.mean(cost)

定义损失函数之后,可以在主程序(fluid.default_main_program)中克隆一个程序作为预测程序,用于训练完成之后使用这个预测程序进行预测数据。
这个定义的顺序不能错,因为我们定义的网络结构,损失函数等等都是更加顺序记录到PaddlePaddle的主程序中的。主程序定义了神经网络模型,前向反向计算,以及优化算法对网络中可学习参数的更新,是我们整个程序的核心,这个是PaddlePaddle已经帮我们实现的了,我们只需注重网络的构建和训练即可。

# 复制一个主程序,方便以后使用
test_program = fluid.default_main_program().clone(for_test=True)

接着是定义训练使用的优化方法,这里使用的是随机梯度下降优化方法:

# 定义优化方法
optimizer = fluid.optimizer.SGDOptimizer(learning_rate=0.01)
opts = optimizer.minimize(avg_cost)

然后是创建一个解析器,我们同样是使用CPU来进行训练。创建解析器之后,使用解析器来执行fluid.default_startup_program()初始化参数:

# 创建一个使用CPU 的解释器
place = fluid.CPUPlace()
exe = fluid.Executor(place)
# 进行参数初始化
exe.run(fluid.default_startup_program())

我们使用numpy定义一组数据,这组数据的每一条数据有13个,这是因为我们在定义网络的输入层时,shape是13,但是每条数据的后面12个数据是没意义的,都是使用0来填充,纯粹是为了符合数据的格式而已。

这组数据是符合y = 2 * x + 1,但是程序是不知道的,我们之后使用这组数据进行训练,看看神经网络是否能够训练出一个拟合这个函数的模型。

最后定义了一个预测数据,是在训练完成,使用这个数据作为x输入,看是否能够预测于正确值相近结果。

# 定义训练和测试数据
x_data = np.array([[1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], 
                   [2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], 
                   [3.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], 
                   [4.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], 
                   [5.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]]).astype('float32')
y_data = np.array([[3.0], [5.0], [7.0], [9.0], [11.0]]).astype('float32')
test_data = np.array([[6.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]]).astype('float32')

定义数据之后,我们就可以使用数据进行训练了。
经过多次测试,当训练次数达到250时,损失函数基本就降到最低了。

同样我们使用的时profram是fluid.default_main_program(),feed中是在训练时把数据传入fluid.layers.data()定义的变量中,及那个键值对的key对用的就是fluid.layers.data()中的name的值。我们让训练过程中输出avg_cost的值。

在训练过程中,我们可以看到输出的损失值在不断减小,证明我们的模型在不断收敛:

# 开始训练250个pass
for pass_id in range(250):
    train_cost = exe.run(program=fluid.default_main_program(),
                            feed={'x':x_data, 'y':y_data},
                            fetch_list=[avg_cost])
    print("Pass:%d, Cost:%0.5f" % (pass_id, train_cost[0]))

在这里插入图片描述
训练完成之后,我们使用上面克隆主程序得到的预测程序了预测我们刚才定义的预测数据。预测数据同样作为x在feed输入,在预测时,理论上是不用输入y的,但是要符合输入格式,我们模拟一个y的数据值,这个值并不会影响我们的预测结果。

fetch_list的值,也就是我们执行预测之后要输出的结果,这是网络的最后一层,而不是平均损失函数(avg_cost),因为我们是想要预测程序输出预测结果。根据我们上面定义数据时,满足规律y = 2 * x + 1,所以当x为6时,y应该时13,最后输出的结果也是应该接近13的。

# 开始预测
result = exe.run(program=test_program,
                    feed={'x':test_data, 'y':np.array([[0.0]]).astype('float32')},
                    fetch_list=[net])
print("当x为6.0时,y=%0.5f" % result[0][0][0])

结果(训练结果还是可以的):
在这里插入图片描述
可以简单概括一下程序步骤:

  1. 构造神经网络
    毫无疑问,这当然是最重要的,没有神经网络也就没有强化学习了;

  2. 定义损失函数
    有了神经网络当然就会有输出结果了,如何描述输出值与真实值的关系呢?这就靠损失函数了;

  3. 定义优化方法
    有了输出值与真实值的关系,当然就要针对这一关系进行优化啦,这就需要某种优化方法了;

  4. 创建解释器
    万事俱备,只欠东风。创建一个解释器,开始训练吧;

  5. 开始训练

  6. 预测

发布了307 篇原创文章 · 获赞 127 · 访问量 15万+

猜你喜欢

转载自blog.csdn.net/weixin_40973138/article/details/105186771