-
首先需要导入相关库
# paddle/fluid:飞桨的主库,目前大部分的实用函数均在paddle.fluid包内。
# dygraph:动态图的类库。
import paddle.fluid as fluid
import paddle.fluid.dygraph as dygraph
from paddle.fluid.dygraph import Linear
import numpy as np
-
数据处理
注:
此次数据处理新增了:记录数据的归一化参数,在预测时对数据做归一化。其余部分与上一篇文章相同,详细说明可戳上方链接查看。
def load_data():
firstdata = np.fromfile('housing.data', sep=' ')
# 添加属性
feature_names = ['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT',
'MEDV']
# 列的长度
feature_num = len(feature_names)
# 构造506*14的二维数组
data = firstdata.reshape([firstdata.shape[0] // feature_num, feature_num])
# 训练集设置为总数据的80%
ratio = 0.8
offset = int(data.shape[0] * ratio)
training_data = data[:offset]
# 训练集每列的最大值、最小值、平均值
maximums, minimums, avgs = training_data.max(axis=0), training_data.min(axis=0), training_data.sum(axis=0) / \
training_data.shape[0]
# 记录数据的归一化参数,在预测时对数据做归一化
global max_values
global min_values
global avg_values
max_values = maximums
min_values = minimums
avg_values = avgs
# 对所有数据进行归一化处理
for i in range(feature_num):
data[:, i] = (data[:, i] - avgs[i]) / (maximums[i] - minimums[i])
# 覆盖上面的训练集
training_data = data[:offset]
# 剩下的20%为测试集
test_data = data[offset:]
return training_data, test_data
-
模型设计
注:
FC:神经网络的全连接层函数,即包含所有输入权重相加和激活函数的基本神经元结构。在房价预测任务中,使用只有一层的神经网络(全连接层)来实现线性回归模型。
class Regressor(fluid.dygraph.Layer):
def __init__(self):
super(Regressor, self).__init__()
# 定义一层全连接层
# 输入维度为13,输出维度为1,不适用激活函数
self.fc = Linear(input_dim=13, output_dim=1, act=None)
# 网络的前向计算函数,返回预测结果
def forward(self, inputs):
x = self.fc(inputs)
return x
-
训练配置
注:
模型实例有两种状态:训练状态 .train() 和预测状态 .eval() 。
训练时要执行正向计算和反向传播梯度两个过程,而预测时只需要执行正向计算。
# 定义飞桨动态图的工作环境
with fluid.dygraph.guard():
model = Regressor()
# 开启模型训练
model.train()
training_data, test_data = load_data()
# 定义优化算法,SGD为随机梯度下降法
# 学习率为0.01
opt = fluid.optimizer.SGD(learning_rate=0.01, parameter_list=model.parameters())
-
训练过程
步骤:
数据准备:将一个批次的数据转变成np.array和内置格式。
前向计算:将一个批次的样本数据灌入网络中,计算输出结果。
计算损失函数:以前向计算结果和真实房价作为输入,通过损失函数square_error_cost计算出损失函数值(Loss)。
反向传播:执行梯度反向传播backward函数,即从后到前逐层计算每一层的梯度,并根据设置的优化算法更新参数opt.minimize。
保存模型:将模型当前的参数数据model.state_dict()保存到文件中(通过参数指定保存的文件名 LR_model),以备预测或校验的程序调用。
with dygraph.guard(fluid.CPUPlace()):
EPOCH_NUM = 10
BATCH_SIZE = 10
# 外层循环
for epoch_id in range(EPOCH_NUM):
# 打乱训练数据顺序
np.random.shuffle(training_data)
# 拆分数据,每个mini_batches包含10条数据
mini_batches = [training_data[k:k + BATCH_SIZE] for k in range(0, len(training_data), BATCH_SIZE)]
# 内层循环
for iter_id, mini_batch in enumerate(mini_batches):
x = np.array(mini_batch[:, :-1]).astype('float32')
y = np.array(mini_batch[:, -1:]).astype('float32')
# 将numpy数据转化为飞桨动态图variable形式
house_features = dygraph.to_variable(x)
prices = dygraph.to_variable(y)
# 前向计算
predicts = model(house_features)
# 计算损失
loss = fluid.layers.square_error_cost(predicts, label=prices)
avg_loss = fluid.layers.mean(loss)
if iter_id % 20 == 0:
print("epoch: {}, iter: {}, loss is: {}".format(epoch_id, iter_id, avg_loss.numpy()))
# 反向传播
avg_loss.backward()
# 最小化loss,更新参数
opt.minimize(avg_loss)
# 清除数据
model.clear_gradients()
# 保存模型
fluid.save_dygraph(model.state_dict(), 'LR_model')
-
测试模型
def load_one_example(data_dir):
f = open(data_dir, 'r')
datas = f.readlines()
# 倒数第十条数据
tmp = datas[-10]
# 修改数据格式
tmp = tmp.strip().split()
# 修改数据类型
one_data = [float(v) for v in tmp]
# 归一化处理
for i in range(len(one_data) - 1):
one_data[i] = (one_data[i] - avg_values[i]) / (max_values[i] - min_values[i])
# 取one_data的前13个数据,修改矩阵为1行13列,再变化数组类型
# 【2】【3】
data = np.reshape(np.array(one_data[:-1]), [1, -1]).astype(np.float32)
# 取one_data的最后一个数据
label = one_data[-1]
return data, label
with dygraph.guard():
# 载入保存的模型
model_dict, _ = fluid.load_dygraph('LR_model.pdparams')
model.load_dict(model_dict)
# 调整模型状态
model.eval()
# 读取数据
test_data, label = load_one_example('housing.data')
# 将数据转化为飞桨动态图variable形式
test_data = dygraph.to_variable(test_data)
results = model(test_data)
# 对结果进行反归一化处理
results = results * (max_values[-1] - min_values[-1]) + avg_values[-1]
print("Inference result is {}, the corresponding label is {}".format(results.numpy(), label))
输出结果:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200527193557828.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L25hcnV0b2R6eA==,size_16,color_FFFFFF,t_70)
-
总结
飞桨很大程度的上降低了深度学习的学习成本,深度学习框架对入门者很友好,编写少量的代码即可实现需要的功能。