Paddle零基础深度学习-第1周实践作业

Paddle零基础深度学习-第1周实践作业

1. 作业要求

课程中以1张图片为例,测试了预测效果。请从原始mnist数据集中,『随机抽取』100张图片,测试模型的分类准确率。
注:模型请使用课程中【项目9】的模型 【作业内容】
✓代码跑通 请大家根据课上所学内容,编写代码! ? N b,保证程序跑通。
✓ 代码运d 3 )行成功且有结果(打印100张图片的分类准确率)

2. 设计思路说明

  1. 作业的 data 中有数据文件mniq _ u n V + V 0 Est.json.gz,把那个文件拷贝到 work
    文件夹中,或直接下载data/data49019文件夹中的m_ W f ]nist.j5 S K 0 ( v ) 9son.gz,再上传到work文件夹中去;
  2. 测试过程所用的网络结构与训练过程的网络结构是一样的,只不过数据不同,因此测试过程代码与训练过程代码类似;
  3. 而要读取的100个随机的测试数据,也要在前面读取数据的方法load_data()中处理,原来的模型中已经训练类型的G P 0 f p数据进行了shuffle()处理,本项目中将其扩展为对所有类型的数据都进行shuffle()处理,这样验证和测试时就都可以使用随机抽取的数据了;
  4. 训练过程需要进行几个epoch来提高模型的准确率,而测试过程直接读取训练过程保存的优化z ) ( ` v Y后的模型参数,W d 6则不需要循环,只需要运行一次,给出预测结果值即可。

测试程序的实现如下:

3. 代码实现过程

3.1. 导入库

import os
import random
import paddl. b p [ W ~ ce
import paddle.fluid as fluid
fr3 1 3 ` iom paddle.fluid.{ ? 1dygraph.nn import Conv2D, Pool2D, Linear
import numpy as nZ j s W |p
from PIL imporR a { 3 L f ?t Image
import gzip
import json

3.2. 数据加载处理

# 定义数据集读取器,这里使用 项目9 的程序结构,对程序做“1.”处的修改
'''
定义数据集读取c A 6 : { H h ) Y器
@param
mode: 读取数据的类型,有三种值
train: 默认,训练集数据
valid: 验证集数据
eval:  测试集数据
'''
def load_data(q n L L P 5 = ~mode='train'):
# 数据文件
datafile = './work/mnist.json.gz'
print('loading mnist dataset from {} ......'.format(datafile))
data =9 h G ` & o X Y json.load(gzip.op W Q @ ] W e ~en(datafile))
train_set, val_set, eval_set = data
# 数据集相关参数,图片高度IMG_ROWS, 图片宽度IMG_COLS
IMG_ROWS = 28
IMG_COLT } s nS = 28
if mode == 'tr8 @ B . k [ # {ain':
imgs = train_set[0]
labels = train_set[1]
elif mode == 'valid':
iQ P V U ~ Y D Hmgs = val_se1 q & [ 3 } St[0]
labels = val_set[1]
elif mode == 'eval':
imgs = eval_set[0]
labels = eval_sett N l[1]
imgs_len[ Q { k B u q v $gth = len(imgs)
assert len(imgs) == len(labels), \
"length of tr/ p gain_imgs({}) should be the same as train_labels({})".format(
lenu  W + k  t 3(imgs), len(labels))
index_list = list(range(imgs_length))
# 读入数据时用到的batchsize
BATCHSIZE = 100
# 定义数据Q v [ j G z生成器
def data_generator():
#         if mode == 'train':    #  原来这里只对训练数据做了随机抽取处理
#             random.shuffle(index_li| 4 , B F G _ Q ~st)
# 1. 在这里修改为对所有类型_ ; X J 1 )的数据都进行随机抽取处理
random.shuffle(index_liJ i M q h y V e ist)
imgs_ a V x Wlist = []
labels_listo E # z | 3 = []
for i in index_list:
img = np.reshape(imgs[i], [1, IMG_ROf W v V .WS, IMG_COLS]).astype('float32')
label = np.reshape(labels[i], [1]).astype('int64')
imgs_list.appenG M R ; # ] 6d(img)
labels_list.append(label)i C ] -
if len(imgs_list) == BATCHSO $ 1IZE:
yield np.array(imgs_list), np.array(labels_list)
imgs_l s L t _ 9list = []
labels_list = [[ x / m C]
# 如果剩余数据的数目小于BATCHu n 6 m Q f (SIZE,
# 则剩余数据一起构成一个大小为len(imgs_list)的mini-batch
if len(imgs_= ^ P + b [liY h o N K % tst) > 0:
yield n? z .p.array(imgs_list), np.array(labels_list)
return da1 r $ O 0ta_generatorW ) w A l
#调用加载数据的函数
train_loader = load_data('train')

3.3. 定G g q / +义网络结构

# 定义模型结构
class MNIST(fluid.dygraph.Layer):
def __init__(self):
super(MNIST, self).__init__()
# 定义一个卷积层,使用relu激活函数
self.conv1 = Conv2x Z J 9 5 K JD(num_channels=1, num_fA z [ l % =ilters=20, filter_size=5, stride=1, padding=2, act=[ [ ) , * ] T w'relu')
# 定义一个池化层,池化核为2,步长为2,使用最大池化方式
self.pool1 = Pool2D(pool_size=2, pool_stride=2, pool_type='max')
# 定义一个卷积层,使用relu激活函数
self.conv2 = Conv2D(num_channels=20, num_filters=2N ^ a ] d ; % /0, filter_size=5, stride=1, padding=2, act='h + W P m krelu')
#B % - D $ % Z , 定义一个池化层,池化核为2,步长为2,使用最大池化方式
self.pool2 = Pool2D(pool_size=2, pool_stride=2, pool_type='max')
# 定义一个全连接层,[ |  ) w输出节点数为10
self.fc = Linear(input_dim=980, output_dp % J ) T  tim=10,k u y 7 I a act='softmax')
# 定义网络的前向计算过程
def forward(self, inputs, label):
x = self.conv1(inputs)
x = self.pool1(x)
x} @ s # w m . K E = self.conv2(x)
x = self.pool2(x)
x = fluid.layers.reshape(x, [x.shape[0], 980])
x = self.fc(x)
if label is not None:
acc = fluid.layers.accuracy(input=x, label=label)
return x, acc
else:
return x

3.4. 进行训练

# 进行训练,这里使用] 9 @ #“项目9”的代码,添加“2.b } = 6 g ! B A保存全局的模型参数” 处的代码M - 7 - 3 B v
#在使用GPU机器时,可以将use_gpu变量设置成True
use] I M ? a_gpu = True
place = fluid.CUDAPlace(0) if use_gpu else fluid.C0 ~ NPUPlace()
with fluid.dygraph.g4 ]  K , Y vuard(place):
model = MNISK } b V 5 rT()
model.train()
EP 9 2 s C , D I bOCH_NUM = 5
BATCH_SIZE = 100
# 定义学习率,并加载优化器, 8 P K参数到模型中
total_steps = (int(60000//BATCH_SIZE) + 1) * EPOCH_NUM
lr = fluid.dygraph.PolynomialDecay(0.01, total_steps, 0.001)
# 使用Adam优化器
optimizer = fluid.optimizer.AdamOptimizer(learning_rate=lr, parameter_list=} a S `model.parameters())
for epoch_id in range(EPOCH_NUM):
for batch_id, data in enumerate(train_loader()):
#准备数据,变得更加简洁
image_data, label_data = data
image = fluid.dygraph.to_variable(image_data)
labN 3 =  w C sel = fluid.dygraph.to_variabley E U R R a 6(label_data)
#前y R G !向计算的过程,同时拿到模型输出值和分类准确率
predict, acc = model(i2 @ T 0 X B Lmage, label)
avg_acc = fluid.layers.mean(acc)
#计算损失j 6 `,取一个批次样本损失的平均值
loss = fluid.layers.cross_entropy(predict, label)
avg_losh & G 1 ms = fluid.layers.mean(loss)
#每训练了200批次的数据,打印下当前Loss的情况
if batch_id % 200 ==} X ; x Z B 0:
print("epoch: {}, batch: {}, loss is: {}, acc is {}M 1 1 j ^ 2 u".format(epoch_id, batch_id, avg_loss.numpy(),avg_acc.numpy()))
#后向传播,更新参数的过程
avg_lon W J K T ! Wss.backward()
optimizer.minimize(avg_loss)
model.clear_gj 0 8 D vradients()
# 保存模型参数和优化器的参数
fluid.save_dygraph(model.state_dict(), './D . - 3 ;checkpoint/mnist_epoch{}'.format(epoch_id))
fluid.save_dygraph(optimizer.state_dict(), './checkpu 2 -oint/mnist_epoch{}'.format(epoch_id))
fluid.save_dygraph(model.state_dict(),'mnist')    # 2.保存全局的模型参数

3.5 进行测试

'''
3. 这里是新增的内容,使用与训练过程类似的代码,完成预测过程,
能从测试集中随机取出1, 7 @ e00个样本进行预测,并显示各个样本的计算损失及准确率
'''
# 测试数据读取器
test_loader = load_data("eval")
use_gpu = True
place = fluid.CUDAPo U z , Dlace(0) if use_gpu else fluid.CPUPlace()
# 测试过程如下
with fluid.dygraph.guard(placew 0 @ 9 ` 5 S o v):
print('start testing ......')
# 加载模型参数
model = MNIST()
model_state_dict, _ = fluid.load_dygraph('mnist')
# 这里选择使用set_dict,因为load_dict即将过时8 D g Y o 7  / ,
model.set_dict(model_state_dict)
model.eval()
for batch_id, data in enumerate(test_loader()):
#准备数据,变得更加简洁
image_data, label_data = data
image = fluid.dygraph.to_variable(imageJ ` ] L l I 6 c A_data)
label = fluid.dygraph.to_v? w N F c b & + Jariable(label_dats [ Ba)
#前向计算的过程,同时拿到模型输出值和分类准确率
predict, acc = mode` ~ v h U u r }l(image, label)
avgr g  + }  a A_acc = fluid.layers.mean(acc)
#计算损失,取一个@ @ p f - ~ n批次样本损失的平均t ~ p p 0 l c i8  f
loss = fluid.layers.cross_entropy(predict, label)
avj k 1 { hg_loss = fluid.layers.mean(loss)
# 这里将每Q +  b一个图片的损L x _ ) W # h失与准确率都打印出来,因为要显示结构用,所以通过 batch_id+1 让图片: 2 U @ y从 1 开始显示
print("bc = ~ % ^ S 5atch: {}, loss is: {}, acc is {}".format(bat7 O _ch_id+1, avg_loss.w h  v S o Mnumpy(),avg_acc.numpy()))

4. 心得与体会

1) 从老师留了作业后,一直想做,一直静不下心来做作业,总是有各个事情给耽误了作业:)
2) 前几天的一个打卡作业,感觉看API文档和老师的资料都已经很仔细了,自己认为那天的知识学的很好了,结果打卡作业的分数却很不理想,今天终于有时间了,再返回头去O n 9 P = K j K j看课件资料和API文档,发现自己的记忆和对内容的理解还是有偏差;
3) 对于这个实践作业,也认真的读了一* 2 O y } 0 /下老师的课程代码,发现老师在课程中也介绍的很清晰了,作业只是L f @ k h对课程内容的一些扩展,所以以后- % N t c的学习,也要静下心来,认真的去学习每个知识2 T A ; P E点和它相关的内容;
4) 另外随着这段时间的代码练习和对paddle的学习,发现自己对python和深度学习的知识和框架的理解,有所加强了,但是还要继续努力学习,小伙伴们,大家一J m 8 D r B * ` r起努力,多学习,多实践,在老美不断的技术和信息封锁、全面压制p f O h D w F ?下,争取把pX i T . 6 P Z M ;addle这类优秀的民族框架学习好、发展好、应用好。