目录
Mnist学习
##导入相关库
import paddle
import numpy as np ##矩阵运算库
import matplotlib.pyplot as plt ##画图工具
paddle.__version__
import paddle.vision.transforms as T ##图像预处理库,一个高层APIvision.transforms
# 数据的加载和预处理
transform = T.Normalize(mean=[127.5], std=[127.5]) ##图像归一化,0-255的像素值变成小区间-1到1
##搜索一下参数的设置
# 训练数据集
train_dataset = paddle.vision.datasets.MNIST(mode='train', transform=transform)
# 评估数据集
eval_dataset = paddle.vision.datasets.MNIST(mode='test', transform=transform)
print('训练集样本量: {},验证集样本量: {}'.format(len(train_dataset), len(eval_dataset)))
# 数据集查看
print('图片:')
print(type(train_dataset[0][0]))##显示数据预处理后的类型,矩阵类型
print(train_dataset[0][0])##显示数据
print('标签:')
print(type(train_dataset[0][1]))
print(train_dataset[0][1])##显示标签
# 可视化展示,三种展示方法
#plt.figure()
plt.imshow(train_dataset[0][0].reshape([28,28]), cmap=plt.cm.binary)
##plt.show()
# 模型网络结构搭建
network = paddle.nn.Sequential(
paddle.nn.Flatten(), # 拉平,将 (28, 28) => (784)
paddle.nn.Linear(784, 512), # 隐层:线性变换层
paddle.nn.ReLU(), # 激活函数,便于反向传播函数
paddle.nn.Linear(512, 10) # 输出层
)
# 模型封装
model = paddle.Model(network) ##把网络变成模型
# 模型可视化,检测是否搭建成功
model.summary((1, 28, 28))
# 配置优化器、损失函数、评估指标,优化器,学习率
model.prepare(paddle.optimizer.Adam(learning_rate=0.001, parameters=network.parameters()),
paddle.nn.CrossEntropyLoss(),##要小,交叉熵已经集成softmax(概率统计)
paddle.metric.Accuracy())##评估集与结果的比较,看出模型过拟合(学过头了,训练太多了)或欠拟合
# 启动模型全流程训练
model.fit(train_dataset, # 训练数据集
eval_dataset, # 评估数据集
epochs=5, # 训练的总轮次
batch_size=64, # 训练使用的批大小
verbose=1) # 日志展示形式,1为进度条形式
# 模型评估,根据prepare接口配置的loss和metric进行返回
result = model.evaluate(eval_dataset, verbose=1)
print(result)
# 模型预测
# 进行批量预测操作
result = model.predict(eval_dataset)
# 定义画图方法
def show_img(img, predict):
plt.figure()
plt.title('predict: {}'.format(predict))
plt.imshow(img.reshape([28, 28]), cmap=plt.cm.binary)
plt.show()
# 抽样展示
indexs = [2, 15, 38, 211]
for idx in indexs:
show_img(eval_dataset[idx][0], np.argmax(result[0][idx]))
# 读取单张图片
image = eval_dataset[501][0]
# 单张图片预测
result = model.predict_batch([image])##最大值对应的索引的标签即为预测结果
# 可视化结果
show_img(image, np.argmax(result))
# 保存用于后续继续调优训练的模型
model.save('finetuning/mnist')
# 继续调优训练
from paddle.static import InputSpec
# 模型封装,为了后面保存预测模型,这里传入了inputs参数
model_2 = paddle.Model(network, inputs=[InputSpec(shape=[-1, 28, 28], dtype='float32', name='image')])
# 加载之前保存的阶段训练模型
model_2.load('finetuning/mnist')##文件目录加模型名
# 模型配置
model_2.prepare(paddle.optimizer.Adam(learning_rate=0.001, parameters=network.parameters()),
paddle.nn.CrossEntropyLoss(),##分类常用交叉熵
paddle.metric.Accuracy())
# 模型全流程训练
model_2.fit(train_dataset,
eval_dataset,
epochs=2,
batch_size=64,
verbose=1)
# 保存用于后续推理部署的模型
model_2.save('infer/mnist', training=False)
以上手写识别模型使用全连接矩阵网络结构,还可使用高层API模型,如下
network_2 = paddle.vision.models.LeNet(num_classes = 10)##10个结果
或者卷积网络模型
##卷积网络结构搭建
import paddle.nn as nn
network_3 = nn.Sequential(
nn.Conv2D(in_channels=1,out_channels=6,kernel_size=3,stride=1,padding=1),
nn.ReLU(),##激活函数
nn.MaxPool2D(kernel_size=2,stride=2),
nn.Conv2D(in_channels=6,out_channels=16,kernel_size=5,stride=1,padding=0),
nn.ReLU(),
nn.MaxPool2D(kernel_size=2,stride=2),
nn.Flatten(),
nn.Linear(in_features=400,out_features=120),
nn.Linear(in_features=120,out_features=84),
nn.Linear(in_features=84,out_features=10)
)
##模型可视化
paddle。summary(network_3,(1,1,28,28))
图像分类解决二分类,多分类,多标签。
LeNet是CNN卷积神经网络的鼻祖,定义了基本结构,卷积层,池化层,全连接层。
平均池化,适用于传递背景信息,
最大值池化,用于提取边缘或关键特征信息。
激活函数的选择
Tanh
Relu函数
Paddle学习流程
1.数据加载和预处理,可以远程下载
2.模型的网络设计与开发
sequential
subclass更复杂一点的卷积网络
内置网络
3.模型训练
4.模型评估和测试
5.模型保存和部署.save(model_path)继续调优
.save(model_path,training = False)用于预测部署
网络参数调整(更换或加深)
更换网络结构,添加几层来看效果。训练参数不变。
##更改前的代码
network = paddle.nn.Sequential(
paddle.nn.Flatten(), # 拉平,将 (28, 28) => (784)
paddle.nn.Linear(784, 512), # 隐层:线性变换层
paddle.nn.ReLU(), # 激活函数,便于反向传播函数
paddle.nn.Linear(512, 10) # 输出层
)
# 配置优化器、损失函数、评估指标,优化器,学习率
model.prepare(paddle.optimizer.Adam(learning_rate=0.001, parameters=network.parameters()),
paddle.nn.CrossEntropyLoss(),##要小,交叉熵已经集成softmax(概率统计)
paddle.metric.Accuracy())##评估集与结果的比较,看出模型过拟合(学过头了,训练太多了)或欠拟合
# 启动模型全流程训练
model.fit(train_dataset, # 训练数据集
eval_dataset, # 评估数据集
epochs=5, # 训练的总轮次
batch_size=64, # 训练使用的批大小
verbose=1) # 日志展示形式,1为进度条形式
结果为
{'loss': [0.0], 'acc': 0.9747}
# 将512更改为256
network = paddle.nn.Sequential(
paddle.nn.Flatten(), # 拉平,将 (28, 28) => (784)
paddle.nn.Linear(784, 256), # 隐层:线性变换层
paddle.nn.ReLU(), # 激活函数,便于反向传播函数
paddle.nn.Linear(256, 10) # 输出层
)
结果为
{'loss': [5.6028525e-06], 'acc': 0.9695},准确率下降
改为400,
{'loss': [0.0], 'acc': 0.9688},准确率又降了。
改为600,
{'loss': [2.503392e-06], 'acc': 0.9721},和512的准确率接近了
改为650,
{'loss': [2.3841855e-07], 'acc': 0.9724},准确率高了一点
改为700,
{'loss': [2.3841855e-07], 'acc': 0.9715}准确率低了。。
。。。确实玄学
# 网络多一层
network = paddle.nn.Sequential(
paddle.nn.Flatten(), # 拉平,将 (28, 28) => (784)
paddle.nn.Linear(784, 650), # 隐层:线性变换层
paddle.nn.ReLU(), # 激活函数,便于反向传播函数
paddle.nn.Linear(650, 512),
paddle.nn.ReLU(),
paddle.nn.Linear(512, 10)
)
隐层多添加一层,效果也不如例子好。
{'loss': [1.9073468e-06], 'acc': 0.9693}
# 网络多添加几层
network = paddle.nn.Sequential(
paddle.nn.Flatten(), # 拉平,将 (28, 28) => (784)
paddle.nn.Linear(784, 650), # 隐层:线性变换层
paddle.nn.ReLU(), # 激活函数,便于反向传播函数
paddle.nn.Linear(650, 512),
paddle.nn.ReLU(),
paddle.nn.Linear(512, 400),
paddle.nn.ReLU(),
paddle.nn.Linear(400, 300),
paddle.nn.ReLU(),
paddle.nn.Linear(300, 200),
paddle.nn.ReLU(),
paddle.nn.Linear(200, 10)
)
隐层多添几层,效果不如例子好,比多添加一层好。
{'loss': [0.0], 'acc': 0.9717}
调整训练的超参数(Epoch,Batch Size)
在网络模型使用最高准确率原例时,修改Epoch与Batch Size的值,观察结果。
# Epoch = 5 的结果
Epoch 5/5
step 938/938 [==============================] - loss: 0.1218 - acc: 0.9773 - 8ms/step
Eval begin...
step 157/157 [==============================] - loss: 0.0010 - acc: 0.9774 - 6ms/step
Eval samples: 10000
Eval begin...
step 10000/10000 [==============================] - loss: 3.5763e-07 - acc: 0.9774 - 2ms/step
Eval samples: 10000
{'loss': [3.576278e-07], 'acc': 0.9774}
在例子中,epoch=5,此时第五轮训练准确率达到最高0.9773,测试准确率有0.9774,最终准确率0.9774.
epoch = 3
将训练轮数降低,准确率降低。
{'loss': [4.9351427e-05], 'acc': 0.9693}
Epoch = 6
训练轮数增加,准确率没有5轮好,但比3轮好。
{'loss': [1.1920922e-06], 'acc': 0.9734}
Epoch = 8
训练轮数增加为8,准确率没有5轮好,但比3轮好。
值得一提的是第8轮的训练结果准确率为0.9840,是测试各轮数结果最高的准确率,可是在测试集准确率又下降了,此时最好的Epoch仍然是5轮。
Epoch 8/8
step 938/938 [==============================] - loss: 0.0037 - acc: 0.9840 - 7ms/step
Eval begin...
step 157/157 [==============================] - loss: 4.7354e-04 - acc: 0.9764 - 7ms/step
Eval samples: 10000
Eval begin...
step 10000/10000 [==============================] - loss: 0.0000e+00 - acc: 0.9764 - 2ms/step
Eval samples: 10000
{'loss': [0.0], 'acc': 0.9764}
最后尝试训练9次,结果也是测试的时候准确率降低了,无法解释。。。
Epoch 9/9
step 938/938 [==============================] - loss: 0.0043 - acc: 0.9856 - 8ms/step
Eval begin...
step 157/157 [==============================] - loss: 2.2484e-05 - acc: 0.9723 - 6ms/step
Eval samples: 10000
Eval begin...
step 10000/10000 [==============================] - loss: 0.0000e+00 - acc: 0.9723 - 2ms/step
Eval samples: 10000
{'loss': [0.0], 'acc': 0.9723}
Batch Size改了几次数值,结果也是原本的64准确率最高。
总结
对模型,训练和预测有了实例化的理解,至于参数的选择,可能更多的是靠加减大小调试出更好的结果吧,最优解是不存在的!