PaddlePaddle快速入门

类似于pytorch或者tensorflow,pp是百度开源的深度学习框架。

计算常量加法

# 计算常量加法
import paddle.fluid as fluid
# 定义形状为[2,2]的张量 赋值为1,铺满整个张量,类型为int64
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,并用它进行计算
place = fluid.CPUPlace()
exe = fluid.executor.Executor(place)
# 进行参数初始化 program默认有两个 一个是default_startup_program另外一个是default_main_program
exe.run(fluid.default_startup_program())
# 进行运算,并把y的结果输出 这里program是主程序,fetch_list是解析器在run之后要输出的值,最后得到的也是一个张量
result = exe.run(program=fluid.default_main_program(),fetch_list=[y1])
print(result)
# 如果有时出现了 Error: Need to Create DeviceContextPool first! 报错 可以重启执行器
[array([[2, 2],
       [2, 2]], dtype=int64)]

计算变量加法

# 计算变量加法
'''
    常量的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解析器 以及参数初始化
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')

# 进行运算 feed参数对张量进行赋值的,使用键值对格式,key是定义张量变量时指定名称,value是要传递的值
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)
[3 2] + [1 1] = [4 3]

线性网络

# 线性回归
import paddle.fluid as fluid
import paddle
import numpy as np 

# 定义一个简单的线性网络 输入-隐层-输出
# 这里的data类似create_tensor() 形状为13是因为波士顿房价数据集的每条数据有13个属性
# x表示输入
x = fluid.layers.data(name='x',shape=[13],dtype='float32')
# 隐层
hidden = fluid.layers.fc(input=x,size=100,act='relu')
# 输出 
net = fluid.layers.fc(input=hidden,size=1,act=None)

# 定义神经网络的损失函数 因为是线性回归 所以使用的是平方差损失函数
# y这里还是使用了data这个接口,可以理解为数据对应的结果
y = fluid.layers.data(name='y',shape=[1],dtype='float32')
# 求一个batch的损失值
cost = fluid.layers.square_error_cost(input=net,label=y)
# 求出平均值
avg_cost = fluid.layers.mean(cost)

# 复制一个主程序,方便之后使用
'''
    在主程序中克隆一个程序作为预测程序,用于训练完之后使用预测程序进行预测数据
    定义的顺序不能错,因为网络结构、损失函数等都是按照顺序记录到paddlepaddle主程序中的
    主程序定义了神经网络模型,前后向计算,以及优化算法对网络中可学习参数的更新。
'''
test_program = fluid.default_main_program().clone(for_test=True)

# 定义训练使用的优化方法,随机梯度下降优化 SGD
# 定义优化的方法
optimizer = fluid.optimizer.SGDOptimizer(learning_rate=0.01)
opts = optimizer.minimize(avg_cost)

# 创建解析器,同样使用CPU进行训练
place = fluid.CPUPlace()
exe = fluid.Executor(place)
exe.run(fluid.default_startup_program())

# 定义训练数据和测试数据
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')

# 开始训练
for pass_id in range(10):
    train_cost = exe.run(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]))
pass:0, cost:55.73622
pass:1, cost:26.38364
pass:2, cost:17.24310
pass:3, cost:15.46374
pass:4, cost:15.23521
pass:5, cost:15.08984
pass:6, cost:14.95126
pass:7, cost:14.81588
pass:8, cost:14.68303
pass:9, cost:14.55298
# 开始预测
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为%.5f" % result[0][0][0])
当x为6.0时,y为10.96196

paddlepaddle做房价预测

准备数据

1、uci-housing数据集
506行,每行14列,前13列用来描述房屋的各种信息,最后一列是房价中位数
训练集接口 paddle.dataset.uci_housing.train()
测试集接口 paddle.dataset.uci_housing.test()

2、train_reader和test_reader
paddle.reader.shuffle()表示每次缓存BUF_SIZE个数据项,并进行打乱
paddle.batch()表示每BATCH_SIZE组成一个batch

# 导入基本库
import paddle.fluid as fluid
import numpy as np 
import paddle
import os

BUF_SIZE=500
BATCH_SIZE=20

# 用于训练的数据提供器 每次从缓存中随机读取批次大小的数据
train_reader = paddle.batch(paddle.reader.shuffle(paddle.dataset.uci_housing.train(),buf_size=BUF_SIZE),
                            batch_size=BATCH_SIZE)
# 用于测试的数据提供器
test_reader = paddle.batch(paddle.reader.shuffle(paddle.dataset.uci_housing.test(),buf_size=BUF_SIZE),
                           batch_size=BATCH_SIZE)

# 查看uci_housing数据
train_data = paddle.dataset.uci_housing.train()
# 没有解释next函数 个人认为next应该是python的内置函数 含义返回迭代器的下一个项目
sampledata = next(train_data())
print(sampledata)
(array([-0.0405441 ,  0.06636364, -0.32356227, -0.06916996, -0.03435197,
        0.05563625, -0.03475696,  0.02682186, -0.37171335, -0.21419304,
       -0.33569506,  0.10143217, -0.21172912]), array([24.]))

网络配置

对于线性回归来讲,它就是一个从输入到输出的简单的全连接层
对于波士顿房价来说,假设属性和房价之间的关系可以被属性间的线性组合描述

# 定义输入
x = fluid.layers.data(name='x',shape=[13],dtype='float32')
# 定义输出 
y = fluid.layers.data(name='y',shape=[1],dtype='float32')

# 定义一个简单的线性网络 连接从输入到输出的全连接层 size表示该层输出单元的数目 act表示激活函数
y_predict = fluid.layers.fc(input=x,size=1,act=None)

# 定义损失函数 依旧使用均方误差损失函数
# square_error_cost接收预测值与真实目标值 一个batch的损失值
cost = fluid.layers.square_error_cost(input=y_predict,label=y)
# 对损失求均值
avg_cost = fluid.layers.mean(cost)

# 定义优化函数 随机梯度下降
optimizer = fluid.optimizer.SGDOptimizer(learning_rate=0.001)
opts = optimizer.minimize(avg_cost)
test_program = fluid.default_main_program().clone(for_test=True)
'''
    这里总结一下过程:实际数据获取(有格式规范) 定义输入和输出数据 定义网络模型 定义损失函数 定义优化函数 开始训练 开始预测
    这里为什么顺序大致是这样,因为最开始需要有模型 但是模型前向计算时的权重等都是自己初始化的 没有什么意义的
    根据自己的模型可以对输入的数据进行结果的预测 根据损失函数来规定是否预测准确 如果预测不准确 那么可能是网络的参数不合理
    或者网络设置不合理 如果参数不合理需要调参 使用优化函数(有梯度下降,梯度上升等算法)反向计算权重进行网络优化 优化的目标就是
    尽可能地减小损失。
'''
'''
    上述模型配置完成之后,得到两个fluid.Program:一个是startup另外一个是main
    startup:参数初始化写入
    main:主程序 用于训练和测试模型
    fluid.layers中的所有layer函数可以向main添加算子和变量
'''

模型训练&&模型评估

# 创建Executor 选择CPU还是GPU
# executor接收传入的program 通过run的方式运行program
use_cuda = False
place = fluid.CUDAPlace(0) if use_cuda else fluid.CPUPlace()
# 创建一个Executor的实例exe
exe = fluid.Executor(place)
# run方法先执行startup program 进行参数初始化
exe.run(fluid.default_startup_program())
# 定义输入数据
# DataFeeder负责将数据提供器(train_reader,test_reader)返回的数据转换成一种特殊的数据结构,使其可以输入到Executor中
# feed_list:向模型输入的变量
feeder = fluid.DataFeeder(place=place,feed_list=[x,y])
# 训练时损失值变化趋势图示 draw_train_process
# 引入画图第三方库
import matplotlib.pyplot as plt
# iter表示到当前batch为止的数据量
iter=0
iters=[]
train_costs=[]
def draw_train_process(iters,train_costs):
    title="traing cost"
    plt.title(title,fontsize=24)
    plt.xlabel('iter',fontsize=14)
    plt.ylabel('cost',fontsize=14)
    plt.plot(iters, train_costs,color='red',label='training cost') 
    plt.grid()
    plt.show()
%matplotlib inline
# 训练并保存模型
# 表示训练轮数
EPOCH_NUM=50
model_save_dir = "/home/aistudio/work/fit_a_line.inference.model"

for pass_id in range(EPOCH_NUM):
    # 开始训练并输出最后一个batch的损失值
    train_cost = 0
    for batch_id, data in enumerate(train_reader()):
        train_cost = exe.run(program=fluid.default_main_program(),
                             feed=feeder.feed(data),
                             fetch_list=[avg_cost])
        # 打印最后一个batch的损失值
        if batch_id % 40 == 0:
            print("pass:%d, Cost:%0.5f" % (pass_id, train_cost[0][0])) 
        
        # 这里是为了绘制时事损失值的变量记录 iter就是到当前batch为止的数据量 所有的iter都记录到iters当中 每个iter对应的cost记录到train_costs中
        iter = iter+BATCH_SIZE
        iters.append(iter)
        train_costs.append(train_cost[0][0])

    # 开始测试并输出最后一个batch的损失值
    test_cost = 0
    for batch_id, data in enumerate(test_reader()):
        test_cost = exe.run(program=fluid.default_main_program(),
                            feed=feeder.feed(data),
                            fetch_list=[avg_cost])
    # 打印最后一个batch的损失
    print('Test:%d, Cost:%0.5f' % (pass_id,test_cost[0][0]))

# 保存模型
# 如果保存路径不在就创建
if not os.path.exists(model_save_dir):
    os.makedirs(model_save_dir)
print("save models to %s" % model_save_dir)

# 保存训练参数到指定路径中去,构建一个专门用于预测的program
fluid.io.save_inference_model(model_save_dir, # 保存推理model的路径
                              ['x'], #推理(inference)需要 feed 的数据
                              [y_predict], #保存推理(inference)结果的 Variables
                              exe) #exe 保存 inference model
draw_train_process(iters,train_costs)
pass:0, Cost:554.59772
Test:0, Cost:167.82324
pass:1, Cost:419.52271
Test:1, Cost:118.58235
pass:2, Cost:786.26758
Test:2, Cost:206.14641
pass:3, Cost:522.15173
Test:3, Cost:124.77617
pass:4, Cost:506.57925
Test:4, Cost:329.67911
pass:5, Cost:589.67590
Test:5, Cost:144.04843
pass:6, Cost:497.10205
Test:6, Cost:119.91728
...
pass:48, Cost:128.59196
Test:48, Cost:4.06591
pass:49, Cost:37.72329
Test:49, Cost:7.94485
save models to /home/aistudio/work/fit_a_line.inference.model

模型预测

%matplotlib inline
# 创建预测用的Executor
infer_exe = fluid.Executor(place)
# Scope指定作用域
inference_scope = fluid.core.Scope()

# 可视化真实值与预测值方法定义
infer_results = []
groud_truths = []

def draw_infer_result(groud_truths,infer_results):
    title='Boston'
    plt.title(title, fontsize=24)
    x = np.arange(1,20) 
    y = x
    plt.plot(x, y)
    plt.xlabel('ground truth', fontsize=14)
    plt.ylabel('infer result', fontsize=14)
    plt.scatter(groud_truths, infer_results,color='green',label='training cost') 
    plt.grid()
    plt.show()

# 开始预测 
# with语句修改全局/默认作用域(scope),运行时的所有变量都将分配给新的scope
with fluid.scope_guard(inference_scope):
    # 从指定目录中加载 推理模型
    [inference_program,                             #推理的program
     feed_target_names,                             #需要在推理program中提供数据的变量名称
     fetch_targets] = fluid.io.load_inference_model(#fetch_targets: 推断结果
                                    model_save_dir, #model_save_dir:模型训练路径 
                                    infer_exe)      #infer_exe: 预测用executor

    # 获取预测数据
    infer_reader = paddle.batch(paddle.dataset.uci_housing.test(),batch_size=200)
    #从test_reader中分割x 
    # 这里使用了next 迭代取得infer_reader中的下一个数据 但是它里面的数据是按照批次划分
    # 一个批次有200条数据
    test_data = next(infer_reader())
    test_x = np.array([data[0] for data in test_data]).astype("float32")
    test_y= np.array([data[1] for data in test_data]).astype("float32")

    results = infer_exe.run(inference_program,                              #预测模型
                            feed={feed_target_names[0]: np.array(test_x)},  #喂入要预测的x值
                            fetch_list=fetch_targets)                       #得到推测结果 
    
    # 输出当前批次中的推断值
    print("infer results: (House Price)")
    for idx, val in enumerate(results[0]):
        print("%d: %.2f" % (idx, val))
        infer_results.append(val)
    # 输出当前批次中的真实值
    print("ground truth:")
    for idx, val in enumerate(test_y):
        print("%d: %.2f" % (idx, val))
        groud_truths.append(val)
    
    draw_infer_result(groud_truths,infer_results)
infer results: (House Price)
0: 15.53
1: 15.90
2: 15.45
3: 16.59
4: 15.83
5: 16.14
6: 15.69
7: 15.40
8: 13.75
9: 15.65
...
99: 21.84
100: 21.73
101: 21.50
ground truth:
0: 8.50
1: 5.00
2: 11.90
3: 27.90
4: 17.20
5: 27.50
6: 15.00
7: 17.20
8: 17.90
9: 16.30
...
99: 23.90
100: 22.00
101: 11.90

ps:存在matplotlib.pyplot在jupyter notebook中不显示图像问题
原因:在命令行知道需要使用ipython –pylab进入ipython环境后才能做出图像
解决方法:在绘制图形之前添加%matplotlib inline,然后使用plt.show()就可以绘制图像了