百度PaddlePaddle >>> 5. Boston房价预测

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

在这里插入图片描述

一、准备数据

  1. uci-housing 数据集介绍
    数据集共506行,每行14列。前13列用来描述房屋的各种信息,最后一列为该类房屋的价格中位数。

PaddlePaddle提供了读取uci-housing 训练集和测试集的接口,分别为paddle.dataset.uci_housing.train()paddle.dataset.uci_housing.test()

  1. train_readertest_reader
    paddle.reader.shuffle()表示每次缓存BUF_SIZE个数据项,并进行打乱。

paddle.batch()表示每BATCH_SIZE组成一个batch。

import paddle.fluid as fluid
import paddle
import numpy as np
import os
import matplotlib.pyplot as plt

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)

在这里插入图片描述

二、网络配置

1. 网络搭建

对于波士顿房价数据集,假设属性和房价之间的关系可以被属性间的线性组合描述。
在这里插入图片描述

# 定义张量变量x,表示13维的特征值
x = fluid.layers.data(name='x', shape=[13], dtype='float32')
# 定义张量y,表示目标值
y = fluid.layers.data(name='y', shape=[1], dtype='float32')
# 定义一个简单的线性网络,连接输入和输出的全连接层
# input: 输入tensor
# size: 该层输出单元的数目
# act: 激活函数
hidden1 = fluid.layers.fc(input=x, size=100, act="relu")
y_predict = fluid.layers.fc(input=hidden1, size=1, act=None)

2. 定义损失函数

这里使用均方差损失函数。

square_error_cost(input,lable) 接收输入预测值和目标值,并返回方差估计,即为**(y-y_predict)**的平方

# 定义损失函数
cost = fluid.layers.square_error_cost(input=y_predict, label=y)
avg_cost = fluid.layers.mean(cost)

3. 定义优化函数

这里使用随机梯度下降。

# 定义优化函数
optimizer = fluid.optimizer.SGDOptimizer(learning_rate=0.005)
opts = optimizer.minimize(avg_cost)
test_program = fluid.default_main_program().clone(for_test=True)

上述模型配置完毕后,得到两个fluid.Program

  1. fluid.default_startup_program()
    参数初始化操作会被写入该Program 中。

  2. fluid.default_main_program()
    此Program 用于获取默认或全局main program(主程序),该主程序用于训练和测试模型

fluid.layers 中所有layer函数可以向default_main_program 中添加算子和变量。
default_main_programfluid 的许多编程接口(API)的Program 参数的默认值(当用户program 没有传入的时候,Executor.run()会默认执行 default_main_program
在这里插入图片描述

三、模型训练 和 模型评估

1. 创建Executor

定义运算场所fluid.CPUPlace()fluid.CUDAPlace(0) 分别表示运算场所为CPU和GPU。

Executor:接收传入的program,通过run()方法运行program。

# 创建Executor
use_cuda = False
place = fluid.CUDAPlace(0) if use_cuda else fluid.CPUPlace()
exe = fluid.Executor(place)                 # 创建一个Executor实例exe
exe.run(fluid.default_startup_program())    # 参数初始化

2. 定义输入数据维度

DataFeeder负责将数据提供器(train_reader, test_reader)返回的数据转成一种特殊的数据结构,使其可以输入到Executor中。

# 定义输入数据维度
# feed_list: 向模型输入的变量表或变量表名
feeder = fluid.DataFeeder(place=place, feed_list=[x, y])

3. 定义绘制训练过程中的损失值变化趋势

由于我这由于某些未知原因,导致plt 图像不能显示,所以我只能将其保存在本地进行查看。

iter = 0
iters = []
train_costs = []
def draw_train_process(iters, train_costs):
    title = 'Training 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.savefig("C:/Users/waao_wuyou/Desktop/pic.jpg")

4. 训练并保存模型

Executor 接收传入的program, 并根据feed map(输入映射表)和fetch_list(结果获取表) 向program中添加feed operators(数据输入算子)和fetch operators(结果获取算子)。
feed map为该program提供输入数据。fetch_list提供program训练结束后用户预期的变量。

enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标

# 训练并保存模型
EPOCH_NUM = 100
model_save_dir = "C:/Users/waao_wuyou/Desktop/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_reader 迭代器
        train_cost = exe.run(program=fluid.default_main_program(),  # 运行主程序
                                feed=feeder.feed(data),             # 喂入一个batch 的训练数据,根据feed_list 和data 提供的信息,将输入数据转成一种特殊的数据结构
                                fetch_list=[avg_cost])
        if batch_id % 40 == 0:
            print("Pass:%d, Cost:%0.5f" % (pass_id, train_cost[0][0]))  # 打印最后一个batch 的损失值
        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_reader 迭代器
        test_cost = exe.run(program=test_program,
                            feed=feeder.feed(data),             # 喂入一个batch 的测试数据
                            fetch_list=[avg_cost])              # fetch 均方误差
    print('Test:%d, Cost:%0.5f' % (pass_id, test_cost[0][0]))   # 打印最后一个batch 的损失值

# 保存模型
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'],          # 推理需要feed 的数据
                                [y_predict],    # 保存推理结果的Variables
                                exe)            # exe 保存inference model
draw_train_process(iters, train_costs)

输出结果:

Pass:90, Cost:23.69488
Test:90, Cost:17.02254
Pass:91, Cost:6.22767
Test:91, Cost:12.09491
Pass:92, Cost:7.67705
Test:92, Cost:95.80173
Pass:93, Cost:5.76839
Test:93, Cost:7.67893
Pass:94, Cost:14.50994
Test:94, Cost:6.25279
Pass:95, Cost:34.86055
Test:95, Cost:29.38514
Pass:96, Cost:19.19988
Test:96, Cost:15.92449
Pass:97, Cost:27.39356
Test:97, Cost:4.28481
Pass:98, Cost:5.60616
Test:98, Cost:0.79274
Pass:99, Cost:9.20047
Test:99, Cost:15.64438

在这里插入图片描述
在这里插入图片描述

四、模型预测

1. 创建预测用的Executor

# 模型预测
infer_exe = fluid.Executor(place)       # 创建推测用的executor
inference_scope = fluid.core.Scope()    # Scope 指定作用域

2. 可视化真实值与预测值方法定义

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

# 绘制真实值和预测值对比图
def draw_infer_result(ground_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(ground_truths, infer_results, color='green', label='training cost')
    plt.grid()
    plt.savefig("C:/Users/waao_wuyou/Desktop/result.jpg")

3. 开始预测

通过fluid.io.load_inference_model,预测器会从params_dirname中读取已经训练好的模型,来对从未遇见过的数据进行预测。

# 开始预测
with fluid.scope_guard(inference_scope):    # 修改全局/默认作用域,运行时中的所有变量都将分配给新的scope
    # 从指定目录中加载 推理model(inference model)
    [inference_program,                                 # 推理的program
     feed_target_names,                                 # 需要在推理program中提供数据的变量名称
     fetch_targets] = fluid.io.load_inference_model(    # 推断结果
                                        model_save_dir, # 模型路径
                                        infer_exe)      # 预测用executor
    # 获取预测数据
    infer_reader = paddle.batch(paddle.dataset.uci_housing.test(),  # 获取uci_housing 的测试数据
                                batch_size=200)                     # 从测试数据中读取一个大小为200的batch 的数据

    # 从test_reader中分割x
    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: %0.2f" % (idx, val))
        infer_results.append(val)
    print("ground truth:")
    for idx, val in enumerate(test_y):
        print("%d: %.2f" % (idx, val))
        ground_truths.append(val)
    draw_infer_result(ground_truths, infer_results)

输出结果:

90: 24.50
91: 23.10
92: 19.70
93: 18.30
94: 21.20
95: 17.50
96: 16.80
97: 22.40
98: 20.60
99: 23.90
100: 22.00
101: 11.90

在这里插入图片描述
在这里插入图片描述

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

猜你喜欢

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