您的位置:首页 > 其它

paddle第一周学习心得

2020-08-17 11:44 95 查看

Paddle第一周学习心得

  • 完成代码
  • 总结:
  • 深度学习案例(一)

    这是我参加百度课程《百度架构师手把手带你零基础实践深度学习
    》的第二个案例。

    案例介绍

    本案例为构建一个简单的手写数字识别模型。即构建模型用于识别数据集mnist中的手写数字(0、1、2、3…9),并通过调节模型中的学习率、优化器、隐藏层数等来改变模型对手写数字识别的准确率。
    在本文案例中很多地方会让你觉得雨里雾里的,这是非常正常的,在参加这门课程时,我在学习中反反复复看了老师们提供的文案和视频教程,在结合百度搜索,反复练习课程中提供的案例,一点一点的吸收课程中的知识。
    案例中的数据集:链接: mnist数据集. 密码:lhf8

    环境配置

    python环境 python3任意版本,反正我是用最高版本的
    我使用的pycharm编写代码,代码中的第三方库在pycharm中均可安装,本次案例用到的第三方库有:numpy、matplotlib、paddle这三个,其它的在调试过程中根据需要进行安装,安装这一块网上有不少教程,这一部分就不进行过多的展开,通过搜素引擎检索知识是作为程序员的必备经验,大家加油吧。

    模型构建

    基本结构:导入模块——数据加载——训练配置——训练过程——保存模型

    导入模块

    import random   # python中的随机数模块
    import paddle	 # paddle深度学习框架包,可以不导入
    import paddle.fluid as fluid # paddle深度学习框架包中的一个模块
    from paddle.fluid.dygraph.nn import Conv2D,Pool2D,Linear # paddle框架中的卷积层、池化层、线性变化
    import numpy as np	# 强大的第三方运算库
    import matplotlib.pyplot as plt    # 绘图工具,可以不导入
    
    import gzip	# 解压工具
    import json  # 文件读取

    数据加载

    # 传入参数为train、valid、test,分别用于加载训练集、验证集和测试集
    def load_data(mode = 'train'):
    
    # 数据集路径,与.py文件放在同一文件夹下
    datafile = 'mnist.json.gz'
    # 解压数据集并加载数据
    data = json.load(gzip.open(datafile))
    # 数据集中含有70000张图片,训练集50000张、验证集10000张、测试集10000张
    train_data,val_data,test_data = data
    
    if mode == 'train':  # 当传入参数为“train”时,
    images_data,images_label = train_data[0],train_data[1]
    elif mode == 'valid': #  当传入参数为“valid”时
    images_data,images_label = val_data[0],val_data[1]
    elif mode == 'test': #  当传入参数为“test”时
    images_data,images_label = test_data[0],test_data[1]
    
    # 获取图片的数量,数据集信息可用np.array().shape获取
    image_len = len(images_data)
    
    # 图片由(-1,1)之间的数字组成,因此图片又被称为数字图像
    # 图片行数
    IMAGE_ROW = 28
    # 图片列数
    IMAGE_COL = 28
    
    # 模型每次读取数据集个数
    BATCH_NUM = 100
    
    # 图片编号,构建(0,1,2....image_len-1)相对于为每张图片进行编号,从0开始
    index_list = list(range(image_len))
    
    # 数据读取
    def data_generator():
    if mode == 'train':
    # 乱序,打乱图片顺序
    random.shuffle(index_list)
    # 建立一个用来存储图片的空list
    image_list = []
    # 建立一个用来存储标签的空list
    label_list = []
    
    # 遍历数据集
    for i in index_list:
    # 加载第i个数据集中的图片,并对其重新排列
    image = np.reshape(images_data[i],[1,IMAGE_ROW,IMAGE_COL]).astype('float32')
    # 加载第i个数据集中的标签,并对其重新排列
    label = np.reshape(images_label[i],[1]).astype('int64')
    # 将加载进来的图片存入list中
    image_list.append(image)
    # 将加载进来的标签存入list中
    label_list.append(label)
    
    # 当list中的个数为100个时,将数据集进行返回
    if len(image_list) == BATCH_NUM:
    # yield用于分批读取数据用于减少计算机负担
    yield np.array(image_list),np.array(label_list)
    # 清空图片list和标签list
    image_list = []
    label_list = []
    
    # 将剩余不足100个的数据集进行返回
    if len(image_list) > 0:
    yield np.array(image_list),np.array(label_list)
    
    return data_generator

    构建模型结构

    下面来构建模型的内部结构,该模型有输入层——隐藏层——输出层组成,其中隐藏层结构为卷积层(Conv2D)——池化层(Pool2D)——(Conv2D)——池化层(Pool2D)——全连接层(Linear)

    class MNIST(fluid.dygraph.Layer):
    def __init__(self):
    super(MNIST,self).__init__()
    # 第一层卷积神经网络,num_channel输入通道(深度)为1,num_filters输出通道(深度)为20,filter_size卷积核大小5*5,stride步长(卷积核每次移动格子数),padding边界补充2(图片周围补两圈0),激活函数relu
    self.conv1 = Conv2D(num_channels=1,num_filters=20,filter_size=5,stride=1,padding=2,act='relu')
    # 第一层池化层,pool_size池化核(类似于卷积核)大小2,pool_stride步长2,pool_type类型max,每次获取池化后最大数据
    self.pool1 = Pool2D(pool_size=2,pool_stride=2,pool_type='max')
    # 第二层卷积神经网络,num_channel输入通道(深度)为1,num_filters输出通道(深度)为20,filter_size卷积核大小5*5,stride步长(卷积核每次移动格子数),padding边界补充2(图片周围补两圈0),激活函数relu
    self.conv2 = Conv2D(num_channels=20,num_filters=20,filter_size=5,stride=1,padding=2,act='relu')
    # 第二层池化层,pool_size池化核(类似于卷积核)大小2,pool_stride步长2,
    self.pool2 = Pool2D(pool_size=2,pool_stride=2,pool_type='max')
    # 全连接层,input_dim输入维度980,输出维度10,激活函数softmax
    self.fc = Linear(input_dim=980,output_dim=10,act='softmax')
    
    def forward(self,data_image,data_label,check_data=False,check_content=False):
    # 输入数据data_image维度(100,1,28,28)
    # 输出conv1维度(100,20,28,28)
    conv1 = self.conv1(data_image)
    
    # 输入数据conv1维度(100,20,28,28)
    # 输出pool1维度(100,20,14,14)
    pool1 = self.pool1(conv1)
    
    # 输入数据pool1维度(100,20,14,14)
    # 输出conv2维度(100,20,14,14)
    conv2 = self.conv2(pool1)
    
    # 输入数据conv2维度(100,20,14,14)
    # 输出pool2维度(100,20,7,7)
    pool2 = self.pool2(conv2)
    
    # 重新排列pool
    # 输入数据pool2维度(100,20,7,7)
    # 输出_pool2维度(100,20*7*7)=(100,980)
    _pool2 = fluid.layers.reshape(pool2,[pool2.shape[0],-1])
    
    # 输入数据_pool2维度(100,980)
    # 输出output维度(100,10)
    output = self.fc(_pool2)
    
    # 对应识别数据和真实数据,计算识别数据的准确率
    if data_label is not None:
    acc = fluid.layers.accuracy(input=output,label=data_label)
    return output,acc
    else:
    return output

    训练配置

    # 获取训练集数据
    train_loader = load_data('train')
    use_gpu = False
    # 模型运行时使用cpu或gpu进行计算
    place = fluid.CUDAPlace(0) if use_gpu else fluid.CPUPlace()
    # paddle框架的起点
    with fluid.dygraph.guard(place):
    # 调用模型构建部分写的MNIST类
    model = MNIST()
    # 训练模型
    model.train()
    
    # 常见优化器,任选其一,通过使用不同的优化器,调整不同优化器的学习率,使得模型识别时有不同的效果。
    optimizer = fluid.optimizer.SGDOptimizer(learning_rate=0.01, parameter_list=model.parameters())
    #optimizer = fluid.optimizer.MomentumOptimizer(learning_rate=0.01, momentum=0.9, parameter_list=model.parameters())
    #optimizer = fluid.optimizer.AdagradOptimizer(learning_rate=0.01, parameter_list=model.parameters())
    #optimizer = fluid.optimizer.AdamOptimizer(learning_rate=0.01, parameter_list=model.parameters())

    训练过程

    EPOCH_NUM = 1
    for epoch_id in range(EPOCH_NUM):
    for batch_id, data in enumerate(train_loader()):
    # 获取数据集中图片和标签,
    images_data,labels_data = data
    # 将数据集中图片和标签类型转换成paddle框架中数据对应类型
    images = fluid.dygraph.to_variable(images_data)
    labels = fluid.dygraph.to_variable(labels_data)
    
    # 训练模型,并返回预测结果和预测准确率
    predict,acc = model(images,labels)
    # 计算交叉熵损失函数
    loss = fluid.layers.cross_entropy(predict,labels)
    # 损失函数求平均
    avg_loss = fluid.layers.mean(loss)
    
    if batch_id % 200 == 0:
    print("epoch: {}, batch: {}, loss is: {}, acc is {}".format(epoch_id, batch_id, avg_loss.numpy(),
    acc.numpy()))
    # 梯度下降(反向传递)
    avg_loss.backward()
    # 优化
    optimizer.minimize(avg_loss)
    # 梯度归零
    model.clear_gradients()

    保存模型

    fluid.save_dygraph(model.state_dict(),'mnist_acc')

    完成代码

    import random
    import paddle.fluid as fluid
    from paddle.fluid.dygraph.nn import Conv2D,Pool2D,Linear
    import numpy as np
    
    import gzip
    import json
    
    def load_data(mode = 'train'):
    datafile = 'mnist.json.gz'
    data = json.load(gzip.open(datafile))
    train_data,val_data,test_data = data
    
    if mode == 'train':
    images_data,images_label = train_data[0],train_data[1]
    elif mode == 'valid':
    images_data,images_label = val_data[0],val_data[1]
    elif mode == 'test':
    images_data,images_label = test_data[0],test_data[1]
    
    image_len = len(images_data)
    
    IMAGE_ROW = 28
    IMAGE_COL = 28
    BATCH_NUM = 100
    
    index_list = list(range(image_len))
    
    def data_generator():
    if mode == 'train':
    random.shuffle(index_list)
    image_list = []
    label_list = []
    
    for i in index_list:
    image = np.reshape(images_data[i],[1,IMAGE_ROW,IMAGE_COL]).astype('float32')
    label = np.reshape(images_label[i],[1]).astype('int64')
    image_list.append(image)
    label_list.append(label)
    
    if len(image_list) == BATCH_NUM:
    yield np.array(image_list),np.array(label_list)
    image_list = []
    label_list = []
    
    if len(image_list) > 0:
    yield np.array(image_list),np.array(label_list)
    
    return data_generator
    
    class MNIST(fluid.dygraph.Layer):
    def __init__(self):
    super(MNIST,self).__init__()
    self.conv1 = Conv2D(num_channels=1,num_filters=20,filter_size=5,stride=1,padding=2,act='relu')
    self.pool1 = Pool2D(pool_size=2,pool_stride=2,pool_type='max')
    self.conv2 = Conv2D(num_channels=20,num_filters=20,filter_size=5,stride=1,padding=2,act='relu')
    self.pool2 = Pool2D(pool_size=2,pool_stride=2,pool_type='max')
    self.fc = Linear(input_dim=980,output_dim=10,act='softmax')
    
    def forward(self,inputs,label,check_shape=False,check_context=False):
    output1 = self.conv1(inputs)
    output2 = self.pool1(output1)
    output3 = self.conv2(output2)
    output4 = self.pool2(output3)
    _outputs4 = fluid.layers.reshape(output4,[output4.shape[0],-1])
    output5 = self.fc(_outputs4)
    
    if check_shape:
    print("\n########### print network layer's superparams #####")
    print('conv1--kernel_size:{}, padding:{}, stride:{}'.format(self.conv1.weight.shape,self.conv1._padding,self.conv1._stride))
    print('conv2--kernel_size:{}, padding:{}, stride:{}'.format(self.conv2.weight.shape,self.conv2._padding,self.conv2._stride))
    print('pool1--pool_type:{}, pool_size:{}, pool_stride:{}'.format(self.pool1._pool_type,self.pool1._pool_size,self.pool1._pool_stride))
    print('pool2--pool_type:{}, pool_size:{}, pool_stride:{}'.format(self.pool2._pool_type,self.pool2._pool_size,self.pool2._pool_stride))
    print('fc--weight_size:{}, bias_size:{}, activation:{}'.format(self.fc.weight.shape,self.fc.bias.shape,self.fc._act))
    
    print("\n####### print shape of feature of every layer #######")
    print("input_shape:{}".format(inputs))
    print("output1_shape:{}".format(output1))
    print("output2_shape:{}".format(output2))
    print("output3_shape:{}".format(output3))
    print("output4_shape:{}".format(output4))
    print("output5_shape:{}".format(output5))
    
    if check_context:
    print("\n##### print convolution layer's kernel #######")
    print("conv1 params -- kernel weights:",self.conv1.weight[0][0])
    print("conv2 params -- kernel weights:",self.conv2.weight[0][0])
    
    if label is not None:
    acc = fluid.layers.accuracy(input=output5,label=label)
    return output5,acc
    else:
    return output5
    
    use_gpu = False
    place = fluid.CUDAPlace(0) if use_gpu else fluid.CPUPlace()
    
    def main():
    train_loader = load_data('train')
    
    with fluid.dygraph.guard(place):
    model = MNIST()
    model.train()
    
    optimizer = fluid.optimizer.SGDOptimizer(learning_rate=0.01,parameter_list=model.parameters())
    
    EPOCH_NUM = 1
    for epoch_id in range(EPOCH_NUM):
    for batch_id, data in enumerate(train_loader()):
    images_data,labels_data = data
    images = fluid.dygraph.to_variable(images_data)
    labels = fluid.dygraph.to_variable(labels_data)
    
    if batch_id == 0 and epoch_id == 0:
    predict,acc = model(images,labels,check_shape=True,check_context=False)
    elif batch_id == 401:
    predict,acc = model(images,labels,check_shape=False,check_context=True)
    else:
    predict,acc = model(images,labels)
    
    loss = fluid.layers.cross_entropy(predict,labels)
    avg_loss = fluid.layers.mean(loss)
    
    if batch_id % 200 == 0:
    print("epoch: {}, batch: {}, loss is: {}, acc is {}".format(epoch_id, batch_id, avg_loss.numpy(),
    acc.numpy()))
    avg_loss.backward()
    optimizer.minimize(avg_loss)
    model.clear_gradients()
    fluid.save_dygraph(model.state_dict(),'mnist_acc')print("Model has been saved")
    
    if __name__ == '__main__':
    main()
    

    总结:

    这里用案例的形式和大家进行讲解,讲解方式对新人非常不友好,若你是新人,你需要有大量的前置知识,如神经网络,python基础等。但我个人在学习过程中发现,我比较适合以案例的形式进行学习,早期我学习大量的python基础知识,但让我制作一样东西时,我却无从下手,实战经验果然还是要通过实战获取,我在学习这个案例时,除了标题中的5个步骤以外的内容基本看不懂,都是通过背代码、print打各个参数信息、百度等途径一点一点的磨出来的,相信你也可以做到。
    由于是第一次写博客,写的多烂我心理也有数,欢迎大家的批评

    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: