百度飞桨(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
深度学习可以分为以下几个步骤:
数据集定义与加载
模型组网
模型训练与评估
模型推理
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类的类,自定义数据集
需要重写以下三个方法:
我现在有一个数据,是北京市房价的数据,如下:
数据共有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组网时,只需要按顺序叠加网络层即可:
layers = paddle.nn.Sequential(
paddle.nn.Linear(3, 30), # 全连接层
paddle.nn.ReLU(),
paddle.nn.Linear(30, 1)
)
这定义了一个三层的神经网络。第一层有3个神经元,第二层有30个神经元,第三层有1个神经元。第二、三层之间有激活函数ReLU连接
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)
一个神经网络有许多的层,每个层都有许多神经元:
前面提到的全连接层,就是这样的:
paddle.nn.Linear(3, 30)
其中,3表示输入3个神经元,30表示输出30个神经元
为了让结果非线性,我们需要使用激活函数。最常见的激活函数是ReLU函数:
paddle.nn.ReLU()
这个函数的定义如下:
即如果输入为正数,则返回这个数,否则返回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)
模型训练需要执行以下步骤:
封装模型需要使用paddle.Model进行封装;准备工作需要分别定义优化器、损失函数和评价指标;启动训练需指定训练集、训练轮数和一次读取的数据量等信息,verbose设置日志的打印方式,0表示不打印,1表示以进度条的形式打印,2表示一条一条地打印。
model.fit的参数如下:
以房价预测为例,我们需要使用均方误差损失函数:
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深度学习平台