内容都是百度AIstudio的内容,我只是在这里做个笔记,不是原创。
#合并后代码
#数据处理部分之前的代码,保持不变
import os
import random
import paddle
import paddle.fluid as fluid
from paddle.fluid.dygraph.nn import Conv2D, Pool2D, FC
import numpy as np
import matplotlib.pyplot as plt
from PIL import Imageimport gzip
import json#数据处理部分的展开代码
# 定义数据集读取器
def load_data(mode='train'):# 数据文件datafile = './work/mnist.json.gz'print('loading mnist dataset from {} ......'.format(datafile))data = json.load(gzip.open(datafile))# 读取到的数据可以直接区分训练集,验证集,测试集train_set, val_set, eval_set = data# 数据集相关参数,图片高度IMG_ROWS, 图片宽度IMG_COLSIMG_ROWS = 28IMG_COLS = 28# 获得数据if mode == 'train':imgs = train_set[0]labels = train_set[1]elif mode == 'valid':imgs = val_set[0]labels = val_set[1]elif mode == 'eval':imgs = eval_set[0]labels = eval_set[1]else:raise Exception("mode can only be one of ['train', 'valid', 'eval']")imgs_length = len(imgs)assert len(imgs) == len(labels), \"length of train_imgs({}) should be the same as train_labels({})".format(len(imgs), len(labels))index_list = list(range(imgs_length))# 读入数据时用到的batchsizeBATCHSIZE = 100# 定义数据生成器def data_generator():if mode == 'train':# 训练模式下,将训练数据打乱random.shuffle(index_list)imgs_list = []labels_list = []for i in index_list:img = np.reshape(imgs[i], [1, IMG_ROWS, IMG_COLS]).astype('float32')label = np.reshape(labels[i], [1]).astype('float32')imgs_list.append(img) labels_list.append(label)if len(imgs_list) == BATCHSIZE:# 产生一个batch的数据并返回yield np.array(imgs_list), np.array(labels_list)# 清空数据读取列表imgs_list = []labels_list = []# 如果剩余数据的数目小于BATCHSIZE,# 则剩余数据一起构成一个大小为len(imgs_list)的mini-batchif len(imgs_list) > 0:yield np.array(imgs_list), np.array(labels_list)return data_generator#数据处理部分之后的代码,数据读取的部分调用Load_data函数
# 定义网络结构,同上一节所使用的网络结构
class MNIST(fluid.dygraph.Layer):def __init__(self, name_scope):super(MNIST, self).__init__(name_scope)name_scope = self.full_name()# 定义卷积层,输出特征通道num_filters设置为20,卷积核的大小filter_size为5,卷积步长stride=1,padding=2# 激活函数使用reluself.conv1 = Conv2D(name_scope, num_filters=20, filter_size=5, stride=1, padding=2, act='relu')# 定义池化层,池化核pool_size=2,池化步长为2,选择最大池化方式self.pool1 = Pool2D(name_scope, pool_size=2, pool_stride=2, pool_type='max')# 定义卷积层,输出特征通道num_filters设置为20,卷积核的大小filter_size为5,卷积步长stride=1,padding=2self.conv2 = Conv2D(name_scope, num_filters=20, filter_size=5, stride=1, padding=2, act='relu')# 定义池化层,池化核pool_size=2,池化步长为2,选择最大池化方式self.pool2 = Pool2D(name_scope, pool_size=2, pool_stride=2, pool_type='max')# 定义一层全连接层,输出维度是1,不使用激活函数self.fc = FC(name_scope, size=1, act=None)def forward(self, inputs):# outputs = self.fc(inputs)# return outputsx = self.conv1(inputs)x = self.pool1(x)x = self.conv2(x)x = self.pool2(x)x = self.fc(x)return x# 训练配置,并启动训练过程
with fluid.dygraph.guard():model = MNIST("mnist")model.train()#调用加载数据的函数train_loader = load_data('train')# 创建异步数据读取器place = fluid.CPUPlace()data_loader = fluid.io.DataLoader.from_generator(capacity=5, return_list=True)data_loader.set_batch_generator(train_loader, places=place)optimizer = fluid.optimizer.SGDOptimizer(learning_rate=0.001)EPOCH_NUM = 6for epoch_id in range(EPOCH_NUM):for batch_id, data in enumerate(data_loader):image_data, label_data = dataimage = fluid.dygraph.to_variable(image_data)label = fluid.dygraph.to_variable(label_data)predict = model(image)loss = fluid.layers.square_error_cost(predict, label)avg_loss = fluid.layers.mean(loss)if batch_id % 200 == 0:print("epoch: {}, batch: {}, loss is: {}".format(epoch_id, batch_id, avg_loss.numpy()))avg_loss.backward()optimizer.minimize(avg_loss)model.clear_gradients()fluid.save_dygraph(model.state_dict(), 'mnist')
with fluid.dygraph.guard():print('start evaluation .......')#加载模型参数model = MNIST("mnist")model_state_dict, _ = fluid.load_dygraph('mnist')model.load_dict(model_state_dict)model.eval()eval_loader = load_data('eval')acc_set = []avg_loss_set = []cnt=0sum=0for batch_id, data in enumerate(eval_loader()):x_data, y_data = dataimg = fluid.dygraph.to_variable(x_data)label = fluid.dygraph.to_variable(y_data)prediction= model(img)prediction=prediction.numpy().astype('int32')label=label.numpy().astype('int32')for i in range(len(label)):# print(prediction[i],label[i])if(prediction[i]==label[i]):cnt+=1sum+=100# print(len(prediction))# print("hello:",prediction.numpy().astype('int32'),label.numpy().astype('int32'))# loss = fluid.layers.square_error_cost(input=prediction, label=label)# avg_loss = fluid.layers.mean(loss)# acc_set.append(float(acc.numpy()))# avg_loss_set.append(float(avg_loss.numpy()))#计算多个batch的平均损失和准确率# acc_val_mean = np.array(acc_set).mean()# avg_loss_val_mean = np.array(avg_loss_set).mean()print("acc:",cnt/sum)# print('loss={}, acc={}'.format(avg_loss_val_mean, acc_val_mean))
单张图片测试
def load_image(img_path):# 从img_path中读取图像,并转为灰度图im = Image.open(img_path).convert('L')print(im)im = im.resize((28, 28), Image.ANTIALIAS)im = np.reshape(im,[1,1,28,28]).astype(np.float32)# [batchsize, channels, rows, cols]是这样的形式。1是因为mnist是灰度图只有一个通道,# 一般训练和预测的时候都是指定batchsize大小的,单张测试就取了batchsize=1# 图像归一化,保持和数据集的数据范围一致# print(im)im = 1- im / 127.5 # print(im)img=np.array(im).reshape(28,28).astype(np.float32)plt.imshow(img)return im# 定义预测过程
with fluid.dygraph.guard():model = MNIST("mnist")params_file_path = 'mnist'img_path = './work/example_8.png'# 加载模型参数model_dict, _ = fluid.load_dygraph("mnist")model.load_dict(model_dict)model.eval()tensor_img = load_image(img_path)result = model(fluid.dygraph.to_variable(tensor_img))# #预测输出取整,即为预测的数字print("本次预测的数字是", result.numpy().astype('int32'))