1安装tensorflow
这个库应该挺大,最后还是用清华镜像源安装的,参见我的第一篇博客
安装完成后,在敲这句代码时:
问题:
from tensorflow.examples.tutorials.minst import input_data
出现这样的错误:
2020-04-03 22:23:19.902293: W tensorflow/stream_executor/platform/default/dso_loader.cc:55] Could not load dynamic library 'cudart64_101.dll'; dlerror: cudart64_101.dll not found
2020-04-03 22:23:19.903293: I tensorflow/stream_executor/cuda/cudart_stub.cc:29] Ignore above cudart dlerror if you do not have a GPU set up on your machine.
解决方案
然后我升级安装了tensorflow2.0的版本并使用
import tensorflow as tf
print(tf.__version__)
验证版本安装成功,但是依旧会报错,最后参考网上的博客资料下载补充资源在python库里面。
问题
敲构建对话时会报错,原因可能是同时安装了两个版本的tensorflow不兼容吧
解决方案
# sess = tf.InteractiveSession() 安装了tensorflow1后又安装了tensorflow2 直接使用这句话会报错,改为下面这句
sess = tf.compat.v1.Session() #创建对话
2初步使用并实现手写数字识别:
minst数据集
数据集还是用的minst数据集,下面有这个数据集的详细描述,
http://yann.lecun.com/exdb/mnist/
这个数据集的图像都被压缩在2828大小,同时归一化为了灰度级。据数据集的介绍,其不适合用于模板的分类方法,比如SVM和K最近邻,当数字以边界框而不是质心为中心时,错误率会提高。
这里贴下图像质心的定义:
这个数据集在课程网站的资源中已经下载好了,接下来看其他方面的知识
(2)学习lenet5卷积网络
通过课堂上老师的讲解,结合实验指导书以及https://blog.csdn.net/tjlakewalker/article/details/83275322博客中的知识熟悉了卷积网络的使用。
在本实验中主要使用lenet-5构建深度学习模型,这个模型实际调试的时候,C1、C2层的卷积核使用了55和33两种进行测试,达到98%以上的准确率之后进行保存,将保存的模型文件用于自己画的图像中进行测试。
(3)将保存的模型应用
①第一个想法是将自己用画图程序剪裁的一个2828的图像用保存的模型进行识别,画了一个数字,并带有一定的噪声点,实验证明可以检测出来。
②第二个想法使用GUI界面实现实时画图检测:由于之前没有学过关于这方面的知识,参考了此博客中关于如何构建实时界面,
https://blog.csdn.net/creatorgg/article/details/81542837
并且按照画图需要的要求添加控件,使用鼠标画图的步骤,实验证明采用尽量大一些的像素笔绘画时的成功率较高。
(1)设置main函数:作为一个应用程序的主要执行流和入口点,因此,先编写一个main函数,这个可以作为pyQT程序的main函数框架
(2)设计主界面:从面向对象的角度来设计程序,首先,我们需要一个主界面,程序的核心都属于这个主界面.为主界面设计一个类,命名为MainWidget, 并让这个类继承QWidget
(3)设计paintBoard:设计一块画板,设计一个类,并命名为PaintBoard,同样继承类QWidget。PaintBoard成员__board即实际的画板,实现最基本的画图功能。用鼠标画图时,会涉及到鼠标的按下,鼠标的移动,鼠标的松开这三种事件,这三种事件分别对应了QWidget类中可以重写的三个事件函数 mousePressEvent, mouseMoveEvent, mouseReleaseEvent。画图的逻辑即:在鼠标按下时,记录落点坐标作为上一次的位置,在鼠标的每一次移动发生时,更新当前位置,并在上一次位置和当前位置间画线段。本程序中用于记录鼠标坐标的数据类型是QPoint
(4)设计按键:把画板塞进主界面,顺带在主界面里加几个控件,比如退出按键,清空画板按键,保存作品按键,使用橡皮擦的选择框,画笔粗细,画笔颜色选取
三:解决方案
(一)整个项目需要导入的代码:
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import Sequential, layers, optimizers, losses, metrics
import numpy as np
import matplotlib.pyplot as plt
import gzip
import os
以上:shuzisb.py
import cv2
import tensorflow as tf
以上:moxingceshi.py
from PyQt5.QtWidgets import QWidget
from PyQt5.Qt import QPixmap, QPainter, QPoint, QPen, QColor, QSize
from PyQt5.QtCore import Qt
以上:PrintBoard.py
from PyQt5.Qt import QWidget, QColor, QPixmap, QIcon, QSize, QCheckBox
from PyQt5.QtWidgets import QHBoxLayout, QVBoxLayout, QPushButton, QSplitter, \
QComboBox, QLabel, QSpinBox, QFileDialog, QApplication
from PaintBoard import PaintBoard
import numpy as np
from PIL import Image
import sys
以上:keshihua.py
(二)函数和网络结构设计:学习率设置为0.01,一次训练数据设置为1000(视电脑性能决定),epoch初始设置为5次,随后为了提高准确度可以对以上的参数进行更改。
网络结构参照lenet-5的网络结构,分析了下其他条件不变当C1、C2使用55的卷积核时,准确率要比C1、C2使用33的卷积核时高一些。
损失函数使用的多分类损失函数
loss_object = losses.CategoricalCrossentropy(from_logits=True)
loss = loss_object(y_onehot, out)
对分类结果使用one-hot(一位有效编码)
网络结构主要参照lenet5网络的经典结构:使用了33的卷积核以及55的卷积核进行实验。采用55的卷积核进行卷积的时候训练次数比较小的情况下可以取得比33卷积核更好的准确度。
#搭lenet-5建网络层
```python
networks = tf.keras.models.Sequential ([
layers.Conv2D(6, kernel_size=3, strides=1, padding='same'), #C1卷积核是2d的由6个3*3/5*5的卷积核组成,步长为1
layers.MaxPooling2D(pool_size=2, strides=2), #S2池化层对C1中的2*2区域求和加偏置组成
layers.ReLU(), #激活函数使用Relu
layers.Conv2D(16, kernel_size=3, strides=1, padding='same'), #16个特征函数的3*3/5*5的卷集合步长为1
layers.MaxPooling2D(pool_size=2, strides=2), #同第一个池化层
layers.ReLU(), #激活函数同上
layers.Flatten(), #准备全连接层
layers.Dense(120, activation='relu'), #120个节点的全连接层
layers.Dense(84, activation='relu'), #84个节点的全连接层
layers.Dense(10) #10个节点的全连接层
])
networks.build(input_shape=(batch_size, 28, 28, 1)) #输入给网络的形状,batch_size指一次性训练多少数据
(三)创新点:在完成基本要求后,看到有人做了手写画板的识别工作,所以想到能不能把自己的模型直接应用到界面上。参照了此博客中关于如何构建实时界面,
https://blog.csdn.net/creatorgg/article/details/81542837
并且按照画图需要的要求添加控件,使用鼠标画图的步骤,实验证明采用尽量大一些的像素笔绘画时的成功率较高。
四:实验分析和总结
(1)数据集介绍:minst数据集,下面链接有这个数据集的详细描述,http://yann.lecun.com/exdb/mnist/
这个数据集的图像被压缩在28*28像素大小,同时归一化为了灰度级图像。据数据集的介绍,其不适合用于模板的分类方法,比如SVM和K最近邻,当数字以边界框而不是质心为中心时,错误率会提高,之前没有了解过图像边框和质心的分别,这里贴下图像质心的定义:
在本试验中,可以打开老师给的数据集的压缩包,里面有四个包,主要是训练集、测试集的图像和对应的标签(0-9);
(2)实验结果分析:
按照Lenet-5的网络结构,以及参考了一些博客的编程思路,以下是本代码实现的一些效果
![图一:显示数据集的形状和大小](https://img-blog.csdnimg.cn/20200516003418606.png)
![图二:读取了数据集中的十个图片和对应标签 ](https://img-blog.csdnimg.cn/20200516003433424.png)
![图三:Lenet-5网络](https://img-blog.csdnimg.cn/20200516003452540.png)
![图四:采用5*5卷积核epoch为7部分数值
](https://img-blog.csdnimg.cn/20200516003504184.png)
![图五:采用3*3卷积核epoch为10部分数值](https://img-blog.csdnimg.cn/20200516003515442.png)
![图六:使用画图构建画的28*28的5,带有噪声点](https://img-blog.csdnimg.cn/20200516003541978.png)
![图六:moxingceshi.py 识别结果](https://img-blog.csdnimg.cn/20200516003526688.png)
![图七:实时画图识别正确的效果 ](https://img-blog.csdnimg.cn/20200516003552395.png)
![ 图八:实时画图识别错误的效果](https://img-blog.csdnimg.cn/20200516003603117.png)
(三)总结:
错误率分析:由于整个数据集的图片数据大小只有28*28,我个人认为会一定程度上影响到后续使用清晰的图片进行测试的时候的正确率。如图八所示,认为是3的数值为12.3而认为是7的数值为-17,这两者的差别不是很大。经过反复的测试,最后可以得出:尽量使像素笔的大小更大,然后使数字在图像界面的占比更多(写的更大),可以提升准确度。另外还有一点,我在翻看数据集介绍时,发现有人提及由于数据集是由国外进行收集的,所以在测试的时候应该尽量使用接近他们书写的方式进行图像测试。