使用飞桨搭一个简单的神经网络

本文介绍使用飞桨(paddlepaddle)搭建神经网络的方法。详细阐述了处理数据、写出前向过程、选择优化器等思路,还说明了训练过程,包括打乱数据、转成tensor、前向计算等步骤,最后提及验证和使用模型的方法,并给出全部代码。

前言

应该是昨天吧,使用numpy搭了一个简单的神经网络(传送直通车——使用numpy搭一个简单的神经网络),那么今天就来一个使用飞桨(paddlepaddle)来搭一个吧。
毕竟国产的要支持一下,不然以后美国再一出手,不允许google对中国开源tensorflow,不允许facebook对中国开源pytorch,难不成我们又要回到解放前?还是老老实实学学国产的吧。

详细思路

不外乎还是那样,只是不需要你们手动去写梯度相关:

Created with Raphaël 2.2.0 开始 处理数据 写出前向计算 选择优化器 进行训练 结束

处理数据

跟上一篇一样,不详细说了。

def load_data():
    global minimums, maximums, averages
    file_path = './work/housing.data'
    data = np.fromfile(file_path, sep=' ')
    feature_size = 14
    data = data.reshape((data.shape[0]) // feature_size, feature_size)
    train_test_index = int(0.8 * data.shape[0])
    train_data = data[:train_test_index, :]
    test_data = data[train_test_index:, :]
    minimums, maximums, averages = train_data.min(axis=0), train_data.max(axis=0), train_data.mean(axis=0)
    for i in range(feature_size):
        data[:, i] = (data[:, i] - averages[i]) / (maximums[i] - minimums[i])
    train_data = data[:train_test_index, :]
    test_data = data[train_test_index:, :]
    return train_data, test_data

写出前向过程

在这里写出前向过程,是继承了fluid.dygraph.Layer,在初始化里定义你需要的模型,这里可以有多种层,说不定以后会用到的卷积层,全连接层。然后复写它的forward方法,在里面进行前向传播。

class Network(fluid.dygraph.Layer):
    def __init__(self):
        super(Network, self).__init__()
        self.fc = fluid.dygraph.Linear(input_dim=13, output_dim=1, act=None)
    def forward(self, x):
        z = self.fc(x)
        return z

选择优化器

飞桨提供了多种优化器,毕然老师说的,使用的优化器两只手都可以数出来,不够的话,再加上两只脚(后面的是我加的)。

opt = fluid.optimizer.SGD(0.01, parameter_list=model.parameters())

训练过程

对于训练过程,这里在讲一下:

Created with Raphaël 2.2.0 开始 打乱数据、小批量化 转成tensor 前向计算 计算损失并反向传播 使用优化器最小化损失 清理梯度??Dish还不太明白 每个batch次数迭代完? Epoch次数迭代完? 保存模型 结束 yes no yes no

打乱数据、小批量化

这一点本来不想说,不过还是提一句吧。

np.random.shuffle(train_data)
mini_batchs = [train_data[k:k+10] for k in range(0, n, 10)]

转成tensor

在之前的numpy神经网络里没有这一步,现在是使用fluid.dygraph.to_variable来转换。

x = np.array(mini_batch[:, :-1]).astype(np.float32) # np.float32才OK
y = np.array(mini_batch[:, -1:]).astype(np.float32) # np.float32才OK
house_features = fluid.dygraph.to_variable(x)
price = fluid.dygraph.to_variable(y)

前向计算

刚刚我们已经建立了网络,用这个网络来call一下。

# model = Network()
# model.train()    # 该神经网络设置为训练模式。
# 前面已经定义过了这里只是告诉你们读者,不要问这个model是哪里来的。
pred = model(house_features)

计算损失并反向传播

上一次的计算损失是要自己写 M S E MSE MSE的公式,现在只要使用fluid.layers.square_error_cost就可以了。

loss = fluid.layers.square_error_cost(pred, price)
avg_loss = fluid.layers.mean(loss)
avg_loss.backward()

使用优化器最小化损失

这里帮你更新找最小的损失时的权重和偏置。

opt.minimize(avg_loss)

清理梯度??Dish还不太明白

这一点我不知道如果解释,反正用不用这个都是一样的可以训练出来。知情的大神请赐教一下吧。

model.clear_gradients()  # 可有可无

保存模型

主要是保存model.state_dict()。那么你记住,取出的时候也是model.state_dict()

fluid.save_dygraph(model.state_dict(), 'Dish_LR')

验证、使用模型

Created with Raphaël 2.2.0 开始 使用相同网络结构 从文件中load模型 网络结构加载模型 转换为tensor并开始推理 结束

load模型

这里包括了“使用相同网络结构”,“从文件中load模型”,“网络结构加载模型”。fluid.load_dygraph返回值是两个值的,如果一不小心就会得到一个元组,下一步load_dict就会出错。注意这里将网络设置为推理模式。

model = Network() # 要相同的结构
model_dict, _ = fluid.load_dygraph('./Dish_LR')
model.load_dict(model_dict)
model.eval()    # 该神经网络设置为推理模式。

转换为tensor并开始推理

飞桨的预测,是直接用神经网络对象做为函数去调用,它里面是调用__call__方法

test_x = fluid.dygraph.to_variable(test_x)
test_ret = model(test_x)

全部代码

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


def load_data():
    global minimums, maximums, averages
    file_path = './work/housing.data'
    data = np.fromfile(file_path, sep=' ')
    feature_size = 14
    data = data.reshape((data.shape[0]) // feature_size, feature_size)
    train_test_index = int(0.8 * data.shape[0])
    train_data = data[:train_test_index, :]
    test_data = data[train_test_index:, :]
    minimums, maximums, averages = train_data.min(axis=0), train_data.max(axis=0), train_data.mean(axis=0)
    for i in range(feature_size):
        data[:, i] = (data[:, i] - averages[i]) / (maximums[i] - minimums[i])
    train_data = data[:train_test_index, :]
    test_data = data[train_test_index:, :]
    return train_data, test_data

class Network(fluid.dygraph.Layer):
    def __init__(self, ):
        super(Network, self).__init__()
        self.fc = fluid.dygraph.Linear(input_dim=13, output_dim=1, act=None)
    def forward(self, x):
        z = self.fc(x)
        return z
with fluid.dygraph.guard():
    model = Network()
    model.train()    # 该神经网络设置为训练模式。
    train_data, test_data = load_data()
    opt = fluid.optimizer.SGD(0.01, parameter_list=model.parameters())
    # print(model.parameters())
with fluid.dygraph.guard(fluid.CPUPlace()):
    n = train_data.shape[0]
    losses = []
    for epoch_i in range(500):
        np.random.shuffle(train_data)
        mini_batchs = [train_data[k:k+10] for k in range(0, n, 10)]
        for iten_i, mini_batch in enumerate(mini_batchs):
            # x = np.array(mini_batch[:, :-1]).astype(np.float32)
            # y = np.array(mini_batch[:, -1:]).astype(np.float32)
            x = np.array(mini_batch[:, :-1]).astype(np.float32) # np.float32才OK
            y = np.array(mini_batch[:, -1:]).astype(np.float32) # np.float32才OK
            house_features = fluid.dygraph.to_variable(x)
            price = fluid.dygraph.to_variable(y)
            pred = model(house_features)
            loss = fluid.layers.square_error_cost(pred, price)
            avg_loss = fluid.layers.mean(loss)
            avg_loss.backward()
            opt.minimize(avg_loss)
            model.clear_gradients()  # 可有可无
        losses.append(avg_loss.numpy()[0])
        if epoch_i % 100 == 0:
            print('epoch {}, loss {}'.format(epoch_i, avg_loss.numpy()))
    fluid.save_dygraph(model.state_dict(), 'Dish_LR')
plt.plot(losses)
plt.show()

with fluid.dygraph.guard():
    model = Network() # 要相同的结构
    model_dict, _ = fluid.load_dygraph('./Dish_LR')
    model.load_dict(model_dict)
    model.eval()    # 该神经网络设置为推理模式。
    test_data = np.array(test_data).astype(np.float32)
    test_x = test_data[:, :-1]
    test_y = test_data[:, -1:]

    test_x = fluid.dygraph.to_variable(test_x)
    test_ret = model(test_x)
    test_ret = test_ret * (maximums[-1] - minimums[-1]) + averages[-1]
    test_y = test_y * (maximums[-1] - minimums[-1]) + averages[-1]
    print('pred {}: true {}'.format(str(test_ret.numpy()), str(test_y)))
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值