百度飞桨教程(一)

百度飞桨(paddle),是一个开源的深度学习平台 

百度飞桨的安装

pip install paddlepaddle -i https://mirror.baidu.com/pypi/simple

手写数字识别案例

我们来通过一个案例,大概了解paddle的使用 

import paddle
import numpy as np
from paddle.vision.transforms import Normalize

transform = Normalize(mean=[127.5], std=[127.5], data_format='CHW')
# 下载数据集并初始化 DataSet
train_dataset = paddle.vision.datasets.MNIST(mode='train', transform=transform)
test_dataset = paddle.vision.datasets.MNIST(mode='test', transform=transform)

# 模型组网并初始化网络
lenet = paddle.vision.models.LeNet(num_classes=10)
model = paddle.Model(lenet)

# 模型训练的配置准备,准备损失函数,优化器和评价指标
model.prepare(paddle.optimizer.Adam(parameters=model.parameters()),
              paddle.nn.CrossEntropyLoss(),
              paddle.metric.Accuracy())

# 模型训练
model.fit(train_dataset, epochs=5, batch_size=64, verbose=1)
# 模型评估
model.evaluate(test_dataset, batch_size=64, verbose=1)

# 从测试集中取出一张图片
img, label = test_dataset[0]
# 将图片shape从1*28*28变为1*1*28*28,增加一个batch维度,以匹配模型输入格式要求
img_batch = np.expand_dims(img.astype('float32'), axis=0)

# 执行推理并打印结果,此处predict_batch返回的是一个list,取出其中数据获得预测结果
out = model.predict_batch(img_batch)[0]
pred_label = out.argmax()
print('true label: {}, pred label: {}'.format(label[0], pred_label))

 输出:

The loss value printed in the log is the current step, and the metric is the average value of previous steps.
Epoch 1/5
step 938/938 [==============================] - loss: 0.0422 - acc: 0.9367 - 11ms/step          
Epoch 2/5
step 938/938 [==============================] - loss: 0.0174 - acc: 0.9756 - 11ms/step          
Epoch 3/5
step 938/938 [==============================] - loss: 0.0117 - acc: 0.9800 - 10ms/step          
Epoch 4/5
step 938/938 [==============================] - loss: 0.0091 - acc: 0.9832 - 11ms/step          
Epoch 5/5
step 938/938 [==============================] - loss: 0.0259 - acc: 0.9857 - 11ms/step          
Eval begin...
step 157/157 [==============================] - loss: 0.0030 - acc: 0.9820 - 4ms/step          
Eval samples: 10000
true label: 7, pred label: 7

Process finished with exit code 0

深度学习步骤

深度学习可以分为以下几个步骤:

  1. 数据集定义与加载

  2. 模型组网

  3. 模型训练与评估

  4. 模型推理

数据集定义与加载

import paddle
from paddle.vision.transforms import Normalize

transform = Normalize(mean=[127.5], std=[127.5], data_format='CHW')
# 下载数据集并初始化 DataSet
train_dataset = paddle.vision.datasets.MNIST(mode='train', transform=transform)
test_dataset = paddle.vision.datasets.MNIST(mode='test', transform=transform)

# 打印数据集里图片数量
print('{} images in train_dataset, {} images in test_dataset'.format(len(train_dataset), len(test_dataset)))

这段代码展示了如何加载数据集

paddle.vision.datasets.MNIST是一个手写数字数据集,mode指定训练集或测试集。train代表训练集,test代表测试集

另外,paddle.vision.transforms定义了一些图象变换操作,Normalize将图象归一化

数据集定义

可以创建一个继承自paddle.io.Dataset类的类,自定义数据集

需要重写以下三个方法:

  1. __init__ 初始化数据集
  2. __getitem__ 返回对应索引的一条数据
  3. __len__ 样本总数

我现在有一个数据,是北京市房价的数据,如下:

百度飞桨教程(一)_第1张图片

数据共有3000行

我们可以使用以下代码创建这样的数据类:

import paddle
import pandas as pd


class MyHouseData(paddle.io.Dataset):

    def __init__(self):
        super().__init__()
        self.data = pd.read_csv('home_data.csv')

    def __getitem__(self, idx):
        features = np.array([self.data['m2'][idx], self.data['shi'][idx], self.data['ting'][idx]], dtype=np.float32)
        label = self.data['money'][idx]
        return features, label

    def __len__(self):
        return len(self.data)


dataset = MyHouseData()
print(len(dataset))

模型组网

import paddle
import numpy as np
from paddle.vision.transforms import Normalize

transform = Normalize(mean=[127.5], std=[127.5], data_format='CHW')
# 下载数据集并初始化 DataSet
train_dataset = paddle.vision.datasets.MNIST(mode='train', transform=transform)
test_dataset = paddle.vision.datasets.MNIST(mode='test', transform=transform)

# 模型组网并初始化网络
lenet = paddle.vision.models.LeNet(num_classes=10)

# 可视化模型组网结构和参数
paddle.summary(lenet,(1, 1, 28, 28))

这段代码展示了如何进行模型组网,其输出如下:

---------------------------------------------------------------------------
 Layer (type)       Input Shape          Output Shape         Param #    
===========================================================================
   Conv2D-1       [[1, 1, 28, 28]]      [1, 6, 28, 28]          60       
    ReLU-1        [[1, 6, 28, 28]]      [1, 6, 28, 28]           0       
  MaxPool2D-1     [[1, 6, 28, 28]]      [1, 6, 14, 14]           0       
   Conv2D-2       [[1, 6, 14, 14]]     [1, 16, 10, 10]         2,416     
    ReLU-2       [[1, 16, 10, 10]]     [1, 16, 10, 10]           0       
  MaxPool2D-2    [[1, 16, 10, 10]]      [1, 16, 5, 5]            0       
   Linear-1          [[1, 400]]            [1, 120]           48,120     
   Linear-2          [[1, 120]]            [1, 84]            10,164     
   Linear-3          [[1, 84]]             [1, 10]              850      
===========================================================================
Total params: 61,610
Trainable params: 61,610
Non-trainable params: 0
---------------------------------------------------------------------------
Input size (MB): 0.00
Forward/backward pass size (MB): 0.11
Params size (MB): 0.24
Estimated Total Size (MB): 0.35
---------------------------------------------------------------------------

自定义模型组网

我们可以使用paddle.nn.Sequential或paddle.nn.Layer组网

paddle.nn.Sequential组网

在使用paddle.nn.Sequential组网时,只需要按顺序叠加网络层即可:

layers = paddle.nn.Sequential(
    paddle.nn.Linear(3, 30),  # 全连接层
    paddle.nn.ReLU(), 
    paddle.nn.Linear(30, 1)
)

这定义了一个三层的神经网络。第一层有3个神经元,第二层有30个神经元,第三层有1个神经元。第二、三层之间有激活函数ReLU连接

paddle.nn.Layer组网

paddle.nn.Layer组网的特点是可以自定义前向传播函数,因此可以建立子网。这里以官方的例子为例

# 使用 Subclass 方式构建 LeNet 模型
class LeNet(nn.Layer):
    def __init__(self, num_classes=10):
        super().__init__()
        self.num_classes = num_classes
        # 构建 features 子网,用于对输入图像进行特征提取
        self.features = nn.Sequential(
            nn.Conv2D(
                1, 6, 3, stride=1, padding=1),
            nn.ReLU(),
            nn.MaxPool2D(2, 2),
            nn.Conv2D(
                6, 16, 5, stride=1, padding=0),
            nn.ReLU(),
            nn.MaxPool2D(2, 2))
        # 构建 linear 子网,用于分类
        if num_classes > 0:
            self.linear = nn.Sequential(
                nn.Linear(400, 120),
                nn.Linear(120, 84), 
                nn.Linear(84, num_classes)
            )
    # 执行前向计算
    def forward(self, inputs):
        x = self.features(inputs)

        if self.num_classes > 0:
            x = paddle.flatten(x, 1)
            x = self.linear(x)
        return x
lenet_SubClass = LeNet()

# 可视化模型组网结构和参数
params_info = paddle.summary(lenet_SubClass,(1, 1, 28, 28))
print(params_info)

一个神经网络有许多的,每个层都有许多神经元

百度飞桨教程(一)_第2张图片 

前面提到的全连接层,就是这样的:

paddle.nn.Linear(3, 30)

其中,3表示输入3个神经元,30表示输出30个神经元

激活函数

为了让结果非线性,我们需要使用激活函数。最常见的激活函数是ReLU函数:

paddle.nn.ReLU()

这个函数的定义如下:

ReLU(x)=max(0, x)

即如果输入为正数,则返回这个数,否则返回0. 

为什么要让结果非线性呢?因为有些数据不是线性的,比如y=x^2,这时就需要非线性拟合

模型训练与评估

import paddle
import numpy as np
from paddle.vision.transforms import Normalize

transform = Normalize(mean=[127.5], std=[127.5], data_format='CHW')
# 下载数据集并初始化 DataSet
train_dataset = paddle.vision.datasets.MNIST(mode='train', transform=transform)
test_dataset = paddle.vision.datasets.MNIST(mode='test', transform=transform)

# 模型组网并初始化网络
lenet = paddle.vision.models.LeNet(num_classes=10)

# 封装模型,便于进行后续的训练、评估和推理
model = paddle.Model(lenet)

# 模型训练的配置准备,准备损失函数,优化器和评价指标
model.prepare(paddle.optimizer.Adam(parameters=model.parameters()),
              paddle.nn.CrossEntropyLoss(),
              paddle.metric.Accuracy())

# 开始训练
model.fit(train_dataset, epochs=5, batch_size=64, verbose=1)

模型训练需要执行以下步骤:

  1. 封装模型
  2. 完成准备工作
  3. 配置循环参数并启动训练

封装模型需要使用paddle.Model进行封装;准备工作需要分别定义优化器、损失函数和评价指标;启动训练需指定训练集、训练轮数和一次读取的数据量等信息,verbose设置日志的打印方式,0表示不打印,1表示以进度条的形式打印,2表示一条一条地打印。

model.fit的参数如下:

百度飞桨教程(一)_第3张图片

以房价预测为例,我们需要使用均方误差损失函数:

model = paddle.Model(layers)
model.prepare(paddle.optimizer.Adam(parameters=model.parameters()), paddle.nn.MSELoss())
model.fit(dataset, epochs=50, batch_size=32, verbose=1)

评估模型需要使用model.evaluate方法:

model.evaluate(test_dataset, batch_size=64, verbose=1)

模型推理

可以使用model.predict_batch方法进行推理:

# 从测试集中取出一张图片
img, label = test_dataset[0]
# 将图片shape从1*28*28变为1*1*28*28,增加一个batch维度,以匹配模型输入格式要求
img_batch = np.expand_dims(img.astype('float32'), axis=0)

# 执行推理并打印结果,此处predict_batch返回的是一个list,取出其中数据获得预测结果
out = model.predict_batch(img_batch)[0]
pred_label = out.argmax()
print('true label: {}, pred label: {}'.format(label[0], pred_label))

房价预测

有了之前的基础,很容易写出房价预测的代码: 

import paddle
import pandas as pd
import numpy as np


class MyHouseData(paddle.io.Dataset):

    def __init__(self):
        super().__init__()
        self.data = pd.read_csv('home_data.csv', dtype=np.float32)

    def __getitem__(self, idx):
        features = np.array([self.data['m2'][idx], self.data['shi'][idx], self.data['ting'][idx]], dtype=np.float32)
        label = self.data['money'][idx]
        return features, label

    def __len__(self):
        return len(self.data)


dataset = MyHouseData()

layers = paddle.nn.Sequential(
    paddle.nn.Linear(3, 30),  # 全连接层
    paddle.nn.ReLU(),
    paddle.nn.Linear(30, 1)
)

model = paddle.Model(layers)
model.prepare(paddle.optimizer.Adam(parameters=model.parameters()), paddle.nn.MSELoss())
model.fit(dataset, epochs=20, batch_size=32, verbose=1)

predict = model.predict_batch(np.array([67.06, 3, 1], dtype=np.float32))

print(predict[0])

输出:

Epoch 1/20
step 94/94 [==============================] - loss: 167383.2344 - 943us/step          
Epoch 2/20
step 94/94 [==============================] - loss: 294456.1250 - 894us/step          
Epoch 3/20
step 94/94 [==============================] - loss: 245707.1094 - 862us/step          
Epoch 4/20
step 94/94 [==============================] - loss: 135117.5469 - 904us/step          
Epoch 5/20
step 94/94 [==============================] - loss: 232710.1875 - 926us/step          
Epoch 6/20
step 94/94 [==============================] - loss: 60725.4570 - 872us/step           
Epoch 7/20
step 94/94 [==============================] - loss: 79890.5625 - 862us/step           
Epoch 8/20
step 94/94 [==============================] - loss: 108326.3047 - 974us/step          
Epoch 9/20
step 94/94 [==============================] - loss: 117477.0547 - 862us/step          
Epoch 10/20
step 94/94 [==============================] - loss: 171364.5000 - 872us/step          
Epoch 11/20
step 94/94 [==============================] - loss: 189489.7031 - 894us/step          
Epoch 12/20
step 94/94 [==============================] - loss: 66547.1641 - 915us/step           
Epoch 13/20
step 94/94 [==============================] - loss: 221477.0469 - 938us/step         
Epoch 14/20
step 94/94 [==============================] - loss: 90312.0156 - 851us/step          
Epoch 15/20
step 94/94 [==============================] - loss: 61580.3281 - 957us/step           
Epoch 16/20
step 94/94 [==============================] - loss: 171379.0312 - 915us/step          
Epoch 17/20
step 94/94 [==============================] - loss: 175056.0312 - 862us/step          
Epoch 18/20
step 94/94 [==============================] - loss: 217609.6094 - 883us/step          
Epoch 19/20
step 94/94 [==============================] - loss: 130867.4297 - 883us/step          
Epoch 20/20
step 94/94 [==============================] - loss: 130538.9844 - 926us/step          
[392.48697]

Process finished with exit code 0

 可以发现,根据模型,一个67.06平米的3室1厅房子需要392.48697万元

参考

10分钟快速上手飞桨-使用文档-PaddlePaddle深度学习平台

数据集定义与加载-使用文档-PaddlePaddle深度学习平台

使用 pandas 处理 CSV 文件_pandas csv-CSDN博客 

模型组网-使用文档-PaddlePaddle深度学习平台 

Model-API文档-PaddlePaddle深度学习平台 

你可能感兴趣的:(百度,paddlepaddle,人工智能)