Day02-深度学习原理与使用方法

Day02-深度学习原理与使用方法

作业说明

今天的实战项目是基于深度神经网络的“手势识别”。

作业要求:

  • 1、根据课上所学内容,构建 DNN模型并跑通。在此基础上可尝试构造其他网络。
  • 2、思考并动手进行调参、优化,提高测试集准确率

课件和数据集的链接请去绪论部分寻找 正式学习前的绪论

day02文件夹中包含的就是我们所需要的所有数据。Dataset.zip是我们需要使用的数据集,手势.jpg是最后用来测试效果的图片。

示例代码

  1. 导入python库
import os
import time
import random
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
import paddle
import paddle.fluid as fluid
import paddle.fluid.layers as layers
from multiprocessing import cpu_count
from paddle.fluid.dygraph import Pool2D,Conv2D
from paddle.fluid.dygraph import Linear
  1. 生成图像列表
# Dataset就是数据集
data_path = 'Dataset'
character_folders = os.listdir(data_path)
# print(character_folders)if(os.path.exists('./train_data.list')):
    os.remove('./train_data.list')
if(os.path.exists('./test_data.list')):
    os.remove('./test_data.list')
    
# 按照9:1划分训练集和测试集
for character_folder in character_folders:
    
    with open('./train_data.list', 'a') as f_train:
        with open('./test_data.list', 'a') as f_test:
            if character_folder == '.DS_Store':
                continue
            character_imgs = os.listdir(os.path.join(data_path,character_folder))
            count = 0 
            for img in character_imgs:
                if img =='.DS_Store':
                    continue
                if count%10 == 0:
                    f_test.write(os.path.join(data_path,character_folder,img) + '\t' + character_folder + '\n')
                else:
                    f_train.write(os.path.join(data_path,character_folder,img) + '\t' + character_folder + '\n')
                count +=1
print('列表已生成')
  1. 定义训练集和测试集的reader
def data_mapper(sample):
    img, label = sample
    img = Image.open(img)
    img = img.resize((100, 100), Image.ANTIALIAS)
    img = np.array(img).astype('float32')
    img = img.transpose((2, 0, 1))
    img = img/255.0
    return img, label

def data_reader(data_list_path):
    def reader():
        with open(data_list_path, 'r') as f:
            lines = f.readlines()
            for line in lines:
                img, label = line.split('\t')
                yield img, int(label)
    return paddle.reader.xmap_readers(data_mapper, reader, cpu_count(), 512)
  1. 创建数据提供器
# 用于训练的数据提供器
train_reader = paddle.batch(reader=paddle.reader.shuffle(reader=data_reader('./train_data.list'), buf_size=256), batch_size=32)
# 用于测试的数据提供器
test_reader = paddle.batch(reader=data_reader('./test_data.list'), batch_size=32) 
  1. 定义DNN网络(补全代码)

class MyDNN(fluid.dygraph.Layer):
    def __init__(self):
        super(MyDNN,self).__init__()
        self.hidden1 = Linear()
        self.hidden2 = Linear()
        self.hidden3 = Linear()
        self.hidden4 = Linear()
     
    def forward(self,input):
    
    
    
    
        return y
  1. 用动态图进行训练
with fluid.dygraph.guard():
    model=MyDNN() #模型实例化
    model.train() #训练模式
    opt=fluid.optimizer.SGDOptimizer(learning_rate=0.01, parameter_list=model.parameters())#优化器选用SGD随机梯度下降,学习率为0.01.

    epochs_num=20 #迭代次数
    
    for pass_num in range(epochs_num):
        
        for batch_id,data in enumerate(train_reader()):
            
            images=np.array([x[0].reshape(3,100,100) for x in data],np.float32)
            
            labels = np.array([x[1] for x in data]).astype('int64')
            labels = labels[:, np.newaxis]
            # print(images.shape)
            image=fluid.dygraph.to_variable(images)
            label=fluid.dygraph.to_variable(labels)
            predict=model(image)#预测
            # print(predict)
            loss=fluid.layers.cross_entropy(predict,label)
            avg_loss=fluid.layers.mean(loss)#获取loss值
            
            acc=fluid.layers.accuracy(predict,label)#计算精度
            
            if batch_id!=0 and batch_id%50==0:
                print("train_pass:{},batch_id:{},train_loss:{},train_acc:{}".format(pass_num,batch_id,avg_loss.numpy(),acc.numpy()))
            
            avg_loss.backward()
            opt.minimize(avg_loss)
            model.clear_gradients()
            
    fluid.save_dygraph(model.state_dict(),'MyDNN')#保存模型
  1. 模型校验
with fluid.dygraph.guard():
    accs = []
    model_dict, _ = fluid.load_dygraph('MyDNN')
    model = MyDNN()
    model.load_dict(model_dict) #加载模型参数
    model.eval() #训练模式
    for batch_id,data in enumerate(test_reader()):#测试集
        images=np.array([x[0].reshape(3,100,100) for x in data],np.float32)
        labels = np.array([x[1] for x in data]).astype('int64')
        labels = labels[:, np.newaxis]

        image=fluid.dygraph.to_variable(images)
        label=fluid.dygraph.to_variable(labels)
        
        predict=model(image)       
        acc=fluid.layers.accuracy(predict,label)
        accs.append(acc.numpy()[0])
        avg_acc = np.mean(accs)
    print(avg_acc)
  1. 读取预测图像,进行预测
def load_image(path):
    img = Image.open(path)
    img = img.resize((100, 100), Image.ANTIALIAS)
    img = np.array(img).astype('float32')
    img = img.transpose((2, 0, 1))
    img = img/255.0
    print(img.shape)
    return img
  1. 构建预测动态图过程
with fluid.dygraph.guard():
    infer_path = '手势.JPG'
    model=MyDNN()#模型实例化
    model_dict,_=fluid.load_dygraph('MyDNN')
    model.load_dict(model_dict)#加载模型参数
    model.eval()#评估模式
    infer_img = load_image(infer_path)
    infer_img=np.array(infer_img).astype('float32')
    infer_img=infer_img[np.newaxis,:, : ,:]
    infer_img = fluid.dygraph.to_variable(infer_img)
    result=model(infer_img)
    display(Image.open('手势.JPG'))
    print(np.argmax(result.numpy()))

完成作业

定义DNN网络:

我们定义了三个隐藏层,激活函数都是使用的‘ReLu’线性整流函数,输出层的激励函数使用的是‘Softmax’分类函数。

Sigmoid函数或 Softmax函数可以将分类器的原始输出值映射为概率,然而 Sigmoid函数和 Softmax函数会得出不同结果。
原因在于,Sigmoid函数会分别处理各个原始输出值,因此其结果相互独立,概率总和不一定为1。Softmax函数的输出值相互关联,其概率的总和始终为1。

class MyDNN(fluid.dygraph.Layer):
    def __init__(self):
        super(MyDNN,self).__init__()
        # 定义三层隐藏层,输入维度和输出维度都是100,激活函数为ReLu
        self.hidden1 = Linear(input_dim=100, output_dim=100, act='relu')
        self.hidden2 = Linear(input_dim=100, output_dim=100, act='relu')
        self.hidden3 = Linear(input_dim=100, output_dim=100, act='relu')
        # 定义输出层,输入维度3*100*100,输出维度100,激励函数softmax
        self.hidden4 = Linear(input_dim=3*100*100, output_dim=10, act='softmax')

    def forward(self,input):
        x = self.hidden1(input)
        x = self.hidden2(x)
        x = self.hidden3(x)
        x = fluid.layers.reshape(x, shape=[-1, 3 * 100 * 100])
        y = self.hidden4(x)
        return y

如果是在百度AIStudio平台上,直接补全代码运行即可。

如果是把代码复制到本地来运行,还需要修改一处地方才能运行。把第9步的 display(Image.open(‘手势.JPG’))改成

im = Image.open('手势.JPG')
im.show()

示例中在第6步,动态图训练时,定义的迭代次数是20次,可以看到,训练集上的准确率 train_acc并不高。
day20

用测试集进行模型校验的结果在0.20左右,这个准确率实在是太低了。
day21

最后用手势.jpg图片进行测试时,果不其然会出错。正确结果应该是5而预测结果是1。
day22

于是我们要想办法提高准确率,一种调参方式是增加迭代次数,对神经网络反复进行训练。我们把迭代次数改为200次,训练集的准确率到后期会很高。
day23

测试集准确率提升为0.82,这是一个不错的提升。
day24

用手势图片进行测试,结果也是正确的。
day25

还有一种调参方式是修改学习率,我们在第六步动态图训练时采取的学习率是0.01,可以改为0.005再次尝试。或者我们可以更改优化器,将 SGD优化器换成别的优化器试试效果。助教表示,用调参优化比较好的 DNN可以达到 0.95左右的准确率。

当然,我们也可以构造其他网络,比如 CNN、RNN等。

发布了61 篇原创文章 · 获赞 25 · 访问量 7173

猜你喜欢

转载自blog.csdn.net/qq_42582489/article/details/105300553