前言

本节学习卷积神经网络,然后使用经典的LENET-5神经网络训练手势识别。
教程地址:视屏地址

课程笔记

深度学习模型:
建模——>损失函数——>参数学习

全连接神经网络的不足:

  • 模型不够灵活,输入图片尺寸变换时网络需要修改
  • 模型参数太多

卷积神经网络特点:

  • 局部连接
  • 权值共享
  • 降采样

LENET-5网络模型

本节主要根据这张图设计LENET5模型并编写paddle代码。

首先看下卷积函数的定义源码:

    def __init__(self,num_channels,num_filters,filter_size,stride=1,padding=0,dilation=1,groups=None,param_attr=None,bias_attr=None,use_cudnn=True,act=None,dtype='float32'):
  • num_channels:通道数
  • num_filters:卷积核数
  • filter_size:卷积核大小,卷积核一般是正方形的所以就一个边长参数
  • stride:卷积步长

卷积步长参照下图,蓝色方格每次向右移动两列或向下移动两行表示步长为2:

分析LENET-5网络的input层

Yann LeCun教授的输入是灰度的图片单通道的,大小32 × 32。所以他的输入是32 × 32 × 1,但是我们用的手势数据是彩色的三通道的,所以我们需要做一点修改并且把输入的图片resize成32 × 32 × 3,resize代码:

images = np.array([x[0].reshape(3, 32, 32) for x in data], np.float32)

分析LENET-5网络的C1层

  • 卷积核大小:5 * 5
  • 卷积核数目:6
  • 卷积步长:1
  • 输入通道数: 3

这里要注意的就是卷积核数目,一个卷积核会对应图片的一种特征,n个卷积核就能得出n个特征,n个输出的特征就是下一层的通道个数。
这里我们说了采用的是彩色图片所以我们的input是32 * 32 * 3的,也就是C1层的输入是3通道的,C1层卷积核个数是6个,卷积核尺寸是5,步长是1所以得出paddle源码:

self.c1 = Conv2D(3, 6, 5, 1)

分析LENET-5网络的S2层池化层

  • 池化大小:2 × 2
  • 池化步长:2

paddle源码:

self.s2 = Pool2D(pool_size=2, pool_type='max', pool_stride=2)

分析LENET-5网络的C3层

  • 卷积核大小:5 * 5
  • 卷积核数目:16
  • 卷积步长:1
  • 输入通道数:6

paddle源码:

self.c3 = Conv2D(6, 16, 5, 1)

分析LENET-5网络的S4层池化层

  • 池化大小:2 × 2
  • 池化步长:2

paddle源码:

self.s4 = Pool2D(pool_size=2, pool_type='max', pool_stride=2)

分析LENET-5网络的C5层

  • 卷积核大小:5 * 5
  • 卷积核数目:120
  • 卷积步长:1
  • 输入通道数:16

paddle源码:

self.c5 = Conv2D(16, 120, 5, 1)

分析LENET-5网络的F6层

  • 全连接层输入:120
  • 全连接层输出:84

paddle源码:

self.f6 = Linear(120, 84, act='relu')

分析LENET-5网络的OUTPUT层

  • 全连接层输入:84
  • 全连接层输出:0

paddle源码:

self.f7 = Linear(84, 10, act='softmax')

前向传播模型构建

    def forward(self, input):print("input shape : " + str(input.shape))x = self.c1(input)print("C1 : " + str(x.shape))x = self.s2(x)print("S2 : " + str(x.shape))x = self.c3(x)print("C3 : " + str(x.shape))x = self.s4(x)print("S4 : " + str(x.shape))x = self.c5(x)print("C5 : " + str(x.shape))x = fluid.layers.reshape(x, shape=[-1, 120])x = self.f6(x)y = self.f7(x)return y

重点在这里:

x = fluid.layers.reshape(x, shape=[-1, 120])

在卷积层和全连接层间有一个过度,C5层的输出是120 × 1 × 1的,相当于是一维的,所以这里做了一个reshape,reshape中的-1参数表示设置为一维,120就是输入的通道数。

训练结果

识别结果

完整训练代码

gestureTrain.py代码:

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 Lineardef makeListFile(data_path):# 生成图像列表#data_path = '/home/xmy/PycharmProjects/test/paddle/data/gesture'# 返回指定的文件夹包含的文件或文件夹的名字的列表。character_folders = os.listdir(data_path)# 删除存在的train_data.list和test_data.listif (os.path.exists('./train_data.list')):os.remove('./train_data.list')if (os.path.exists('./test_data.list')):os.remove('./test_data.list')# 遍历所有的folderfor character_folder in character_folders:# 写入train_datawith open('./train_data.list', 'a') as f_train:with open('./test_data.list', 'a') as f_test:# 遍历目录下的所有图片文件character_imgs = os.listdir(os.path.join(data_path, character_folder))# 用count图片分类count = 0for img in character_imgs:# 这里是9:1的设置为训练集和测试集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 += 1print('列表已生成')# 对图片进行预处理
def data_mapper(sample):img, label = sampleimg = Image.open(img)img = img.resize((32, 32), Image.ANTIALIAS)img = np.array(img).astype('float32')# 将读出来的rgb,rgb,rgb......转换成rrr......ggg......bbbimg = img.transpose((2, 0, 1))# 对图片归一化img = img / 255.0return img, labeldef 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)#定义DNN网络
# class MyDNN(fluid.dygraph.Layer):
#     def __init__(self):
#         super(MyDNN,self).__init__()
#         self.hidden1 = Linear(100,100,act='tanh')
#         self.hidden2 = Linear(100,100,act='tanh')
#         self.hidden3 = Linear(100,100,act='tanh')
#         # 10是输出10类,3 × 100 × 100是做了个拉伸但是这样会跟hidden3的输出不匹配所以在前向传播的时候做了reshape
#         self.hidden4 = Linear(3*100*100,10,act='softmax')
#     def forward(self,input):
#         x = self.hidden1(input)
#         x = self.hidden2(x)
#         x = self.hidden3(x)
#         # 拉伸变换。这里搞不明白为什么要拉伸成3 × 100 × 100
#         x = fluid.layers.reshape(x,shape=[-1,3*100*100])
#         y = self.hidden4(x)
#         return y# 定义网络
class MyLeNet(fluid.dygraph.Layer):def __init__(self):super(MyLeNet, self).__init__()self.c1 = Conv2D(3, 6, 5, 1)self.s2 = Pool2D(pool_size=2, pool_type='max', pool_stride=2)self.c3 = Conv2D(6, 16, 5, 1)self.s4 = Pool2D(pool_size=2, pool_type='max', pool_stride=2)self.c5 = Conv2D(16, 120, 5, 1)self.f6 = Linear(120, 84, act='relu')self.f7 = Linear(84, 10, act='softmax')def forward(self, input):print("input shape : " + str(input.shape))x = self.c1(input)print("C1 : " + str(x.shape))x = self.s2(x)print("S2 : " + str(x.shape))x = self.c3(x)print("C3 : " + str(x.shape))x = self.s4(x)print("S4 : " + str(x.shape))x = self.c5(x)print("C5 : " + str(x.shape))x = fluid.layers.reshape(x, shape=[-1, 120])# print(x.shape)x = self.f6(x)y = self.f7(x)return yif __name__ == '__main__':data_path = '/home/xmy/PycharmProjects/test/paddle/data/gesture'makeListFile(data_path)# 用于训练的数据提供器,buf_size越大越乱序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)# 用动态图进行训练with fluid.dygraph.guard():model = MyLeNet()  # 模型实例化model.train()  # 训练模式opt = fluid.optimizer.SGDOptimizer(learning_rate=0.01,parameter_list=model.parameters())  # 优化器选用SGD随机梯度下降,学习率为0.001.epochs_num = 50  # 迭代次数for pass_num in range(epochs_num):for batch_id, data in enumerate(train_reader()):# 将图片大小处理成3 * 32 × 32的为了与lenet相同images = np.array([x[0].reshape(3, 32, 32) for x in data], np.float32)labels = np.array([x[1] for x in data]).astype('int64')# 给labels升维度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(), 'MyLeNet')  # 保存模型# 模型校验with fluid.dygraph.guard():accs = []model_dict, _ = fluid.load_dygraph('MyLeNet')model = MyLeNet()model.load_dict(model_dict)  # 加载模型参数model.eval()  # 训练模式for batch_id, data in enumerate(test_reader()):  # 测试集images = np.array([x[0].reshape(3, 32, 32) 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)

完整模型使用代码

gestureRecongnition.py

import numpy as np
from PIL import Image
import paddle.fluid as fluid
import cv2
from gestureTrain import MyLeNet#读取预测图像,进行预测
def load_image(path):img = Image.open(path)img = img.resize((32, 32), Image.ANTIALIAS)img = np.array(img).astype('float32')img = img.transpose((2, 0, 1))img = img/255.0print(img.shape)return img#构建预测动态图过程
with fluid.dygraph.guard():infer_path = '/home/xmy/PycharmProjects/test/paddle/proj1_gestureRecongnize/手势.JPG'model=MyLeNet()#模型实例化model_dict,_=fluid.load_dygraph('/home/xmy/PycharmProjects/test/paddle/proj1_gestureRecongnize/MyLeNet')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)cv2.imshow("手势",cv2.imread(infer_path))print(np.argmax(result.numpy()))cv2.waitKey(1000)

完整工程和数据集下载

csdn下载链接

百度飞桨(3)—— 手势识别相关推荐

  1. 基于百度飞桨PaddlePaddle模型训练的手势识别模型控制音乐播放器

    基于百度飞桨paddle模型训练的手势识别模型控制音乐播放器 前言 一.什么是百度飞桨PaddlePaddle? 一.1 飞桨AI Studio 二.实际使用 1.配置虚拟环境 2.安装 三.实战 四 ...

  2. 百度飞桨七日深度学习手势识别

    百度飞桨七日深度学习手势识别,paddlepaddle免费GPU算力,以及很好的封装,对初学者灰常友好~~~~. 下面是其中的手势识别作业,采用LeNet网络,初步感受了调参的魅力(雾

  3. 百度飞桨 如何撑起了AI产业生态?

    4月1日消息,从刷脸打卡上班.收听数字人播报新闻.接听AI语音电话,到春游时用AI识别花花草草种类,甚至工厂都开始用AI识别受损零件了--AI应用在我们身边越来越普遍,也越来越好用. 如果将时间拨回到 ...

  4. 百度飞桨七天训练营结营总结

    背景: 全国大学生智能车大赛在2020年遇到了前所未有的阻力,一是疫情影响,二是赞助商的撤资,好在卓大大力挽狂澜,拉到了好几个赞助,保证了大赛的顺利进行.这里真心感谢卓大大.创意组拉来了百度赞助,题目 ...

  5. 【组队学习】【34期】百度飞桨AI达人创造营

    百度飞桨AI达人创造营 航路开辟者:百度飞桨 领航员:六一 航海士:阿水.颜鑫.宋泽山.刘洋.张文恺 基本信息 内容属性:合作课程 练习平台:https://aistudio.baidu.com/ai ...

  6. 百度飞桨成为北京市首个AI产业方向创新应用平台

    1月20日,北京市经济和信息化局正式授予百度公司"北京市人工智能产业创新应用平台(百度飞桨)".当前,北京市正在创建国家人工智能创新应用先导区,人工智能作为新科技革命和产业变革前沿 ...

  7. 百度飞桨全新升级:重磅推出PaddleHelix平台、开源框架V2.0RC,硬件生态路线图全公开...

    12月20日,WAVE SUMMIT+2020深度学习开发者峰会在北京举办.本届峰会,百度飞桨带来八大全新发布与升级,有支持前沿技术探索和应用的生物计算平台PaddleHelix螺旋桨,开发更加便捷的 ...

  8. 支持量子机器学习,王海峰发布最新百度飞桨全景图

    出品 | AI科技大本营(ID:rgznai100) 刚刚,WAVE SUMMIT 2020深度学习开发者峰会上,百度CTO王海峰开场即披露了一组飞桨数据:飞桨累计开发者数量已超过190万,服务企业数 ...

  9. 2021语言与智能技术竞赛上线!百度飞桨提供平台算力支持

    ↑↑↑关注后"星标"Datawhale 每日干货 & 每月组队学习,不错过 Datawhale竞赛 主办方:中国计算机学会.中国中文信息学会 人工智能是让机器像人一样感知和 ...

  10. 精度45.9%,推理速度72.9FPS,百度飞桨推出工业级目标检测模型 PP-YOLO

    允中 发自 凹非寺 量子位 编辑 | 公众号 QbitAI 工业视觉.自动驾驶.安防.新零售等我们身边熟知的各行各业都需要目标检测技术,由于其很好的平衡了标注成本.检测精度和速度等,成为当前智能制造产 ...

最新文章

  1. Android keymaster的介绍和总结
  2. scp错误 WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!
  3. 九大经典算法之基数排序、桶排序
  4. angularjs中的分页指令
  5. H264实时编码及NALU,RTP传输(ZZ)
  6. mysql未指定错误_使用mysql的系统中常见sql错误
  7. Vue3(setup函数介绍)
  8. mysql开启中继日志,MySQL复制应用中继日志解析
  9. MobaXterm怎么复制粘贴以及多窗口执行
  10. luogu P1364 医院设置
  11. Fiddler证书过期解决
  12. java 如何获取前时间的日期,比如两个月前的日期
  13. asterisk cdr mysql_asterisk cdr写入mysql为空的解决办法
  14. YUV图片查看器以及测试文件(YUV420)
  15. linux可变剪切分析,可变剪切的意义和重要性
  16. java jpanel边框_JPanel设置边框
  17. Linux CRDA(Central Regulatory Domain Agent)
  18. Tello talent无人机扩展模块库分析(default.ino)
  19. FaceID调用的几个注意点
  20. 企业选购服务器的9点参考

热门文章

  1. 基于PHP的校园二手信息网站的设计与实现毕业设计源码251656
  2. 3D图形学(一):三维几何学基础(1):三维坐标系
  3. 研发质量管理工作经验总结(一)----质量管理知识
  4. Python 处理医学影像学中的DICOM
  5. Python 带你花式过情人节
  6. log4net 配置文件相对路径配置
  7. Tablecloth:美化表格的 javascript应用
  8. python实现微信发消息
  9. oracle 数据泵介绍,ORACLE-数据泵
  10. 查看电脑的真实Ip(可连接访问的IP)