18 深度学习案例——基于卷积神经网络的手写体识别

基于卷积神经网络的手写体识别

  • 19.2 深度学习的概念及关键技术
    • 1、神经网络模型
    • 2、深度学习之卷积神经网络
  • 19.3 Python深度学习库——Keras
    • 1、Keras的安装
    • 2、Keras的网络层
    • 3、用Keras构建神经网络
  • 19.4 程序设计的思路
  • 19.5 源代码
    • 1、MNIST数据集
    • 2、手写体识别案例体现
    • 3、预测自己手写图像

#!/usr/bin/env python
# coding: utf-8

19.2 深度学习的概念及关键技术

1、神经网络模型

·生物神经元
·轴突(输出)终端为其他神经元的树突(输入)
·人工神经网络

2、深度学习之卷积神经网络

·深度学习结构:含有多隐层的神经网络。
·池化:子采样,可看作一种特殊的卷积过程。
·激活函数:sigmoid、tanh、relu
    ·sigmoid:把一个实数压缩至0~1(分类的概率)
    ·relu:对于随机梯度下降的收敛有巨大的加速作用。
    但脆弱,易造成不可逆转的死亡。
·卷积神经网络的网络结构
    若干卷积层(配合relu) + 池化层 + 全连接层(分类器的作用)

19.3 Python深度学习库——Keras

1、Keras的安装

import numpy,scipy


# In[ ]:


import tensorflow as tf


# In[ ]:


import keras

2、Keras的网络层

(包括:常用层、卷积层、池化层、局部连接层、递归层、嵌入层、高级激活层、规范层、噪声层、包装层,自己编写的层)
·二维卷积层
·Dense层(全连接层)

3、用Keras构建神经网络

步骤:
    1、选择模型
    2、构建网络层
    3、编译
    4、训练
    5、预测

19.4 程序设计的思路

数据集的描述:
   ·训练与测试数据:28*28像素
   ·训练数据集:测试数据集 = 60000 : 10000
   ·输出层:十个神经元


网络结构:
    ·输入层:原始训练图像
    ·第一卷积层:6个5*5的卷积核,步长为1
    ·第一池化层:2*2的卷积核,步长为2的最大池化
    ·第一卷积层:12个5*5的卷积核,步长为1
    ·第一池化层:2*2的卷积核,步长为2的最大池化
    ·输出层:十维向量,激活函数为sigmoid


代码流程简述:
    (1)获取训练数据 和 测试数据
    (2)训练网络的超参数的定义(学习率,每次迭代中训练的样本数目,迭代次数)
    (3)构建网络层级结构
    (4)编译模型
    (5)训练模型
    (6)网络模型评估

19.5 源代码

1、MNIST数据集

·一个计算机视觉数据集(7包含0000张手写数字的灰度图片)28*28像素点

2、手写体识别案例体现

# 读取MNIST数据集
import numpy as np


# In[ ]:


# 数据加载基类,派生出 图片加载器 和 标签加载器
class Loader(object):
    def __init__(self, path, count):
        self.path = path
        self.count = count
        
    def get_file_count(self):
        print(self.path)
        f = open(self.path, 'rb')
        content = f.read()
        f.close()
        return content


# In[ ]:


# 图像数据加载器
class ImageLoader(Loader):
    
    # 内部函数,从文件字节数组中获取第index个图像数据
    def get_picture(self, content, index):
        start = index * 28 * 28 +16
        picture = []
        for i in range(28):
            picture.append([])
            for j in range(28):
                byte1 = content[start + i*28 + j]
                picture[i].append(byte1)
        return picture
    
    # 将图像数据转化成长度为784行向量形式
    def get_one_sample(self, picture):
        sample = []
        for i in range(28):
            for j in range(28):
                sample.append(picture[i][j])
        return sample
    
    # 加载数据文件,获得全部样本的输入向量,onerow表示是否将每张图片转化为行向量,to2表示是否转化为0,1矩阵
    def load(self, onerow = False):
        content = self.get_file_content()
        data_set = []
        for index in range(self.count):
            onepic = self.get_picture(content, index)
            if onerow: 
                onepic = self.get_one_sample(onepic)
            data_set.append(onepic)
        return data_set
    
 


# In[ ]:


# 标签数据加载器
class LabelLoader(Loader):
    
    # 加载数据文件,获得全部样本的标签向量
    def load(self):
        content = self.get_file_content()
        labels = []
        for index in range(self.count):
            onelabel = content[index + 8]
            onelabelvec = self.norm(onelabel)
            labels.append(onelabelvec)
        return labels
    
    # 内部函数,one-hot编码,用于将一个值转换为10维标签向量
    def norm(self, label):
        label_vec = []
        label_value = label
        for i in range(10):
            if i == label_value:
                label_vec.append(1)
            else:
                label_vec.append(0)
        return label_vec
    
    # 获得训练数据集,onerow表示是否将每张图片转化为行向量
    def get_training_data_set(num, onerow = False):
        image_loader = ImageLoader('train-images.idx3-ubyte', num)
        label_loader = LabelLoader('train-labels.idx1-ubyte', num)
        return image_loader(onerow), label_loader.load()
    
    # 获得测试数据集, onerow表示是否将每张图片转化为行向量
    def get_test_data_set(num, onerow = False):
        image_loader = ImageLoader('t10k-images.idx3-ubyte', num)
        label_loader = LabelLoader('t10k-labels.idx1-ubyte', num)
        return image_loader.load(onerow), label_loader.load()
    
    # 将个长度为784的行向量打印成图形的样式
    def printimg(onepic): 
        onepic = onepic.reshape(28, 28)
        for i in range(28):
            for j in range(28):
                if onepic[i, j] == 0:
                    print(' ', end = '')
                else:
                    print('* ', end = '')
            print('')


# In[ ]:


# 训练及测试数据集

import numpy as np
np.random.seed(1337)
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Conv2D, MaxPooling2D, AveragePooling2D
import MNIST


# In[ ]:


# 全局变量
batch_size = 128                        # 批处理样本数量
nb_classes = 10                         # 分类数目
epochs = 600                            # 迭代次数
img_rows, img_cols = 28, 28             # 输入图片样本的宽、高
nb_filters = 32                         # 卷积核的个数
pool_size = (2, 2)                      # 池化层的大小
kernel_size = (5, 5)                    # 卷积核的大小
input_shape = (img_rows, img_cols, 1)   # 输入图片的维度


# In[ ]:


X_train, Y_train = MNIST.get_test_data_set(6000, False)
X_test, Y_test = MNIST.get_test_data_set(1000, False)

X_train = np.array(X_train).astype(bool).astype(float) / 255 # 数据归一化
X_train = X_train[:,:,:,np.newaxis]                          #  添加一个通道,代表图片通道
Y_train = np.array(Y_train)

X_test = np.array(X_test).astype(bool).astype(float) / 255 # 数据归一化
X_test = X_test[:,:,:,np.newaxis]                          #  添加一个通道,代表图片通道
Y_test = np.array(Y_test)

print('样本数据集的维度:', X_train.shape, Y_train.shape)
print('测试数据集的维度:', X_test.shape, Y_test.shape)


# In[ ]:


# 构建模型
model = Sequential()
model.add(Conv2D(6, kernel_size, input_shape=input_shape, strides=1))

model.add(AveragePooling2D(pool_size=pool_size, strides=2))

model.add(Conv2D(12, kernel_size, strides=1))

model.add(AveragePooling2D(pool_size=pool_size, strides=2))

model.add(Flatten())                                         # 拉成一维度矩阵

model.add(Dense(nb_classes))

model.add(Activation('sigmoid'))


# In[ ]:


# 编译模型
model.compile(loss = 'categorical_crossentropy', optimizer='adadelta', metrics= ['accuracy'])


# In[ ]:


# 训练模型(420最为精确!!)
model.fit(X_train, Y_train, batch_size=batch_size, epochs=epochs, verbose=1, validation_data=(X_test, Y_test))


# In[ ]:


# 评估模型
score = model.evaluate(X_test, Y_test, verbose=0)
print('Test score:', score[0])
print('Trst accuracy:', score[1])


# In[ ]:


# 保存模型!!!
model.save('cnn_model.h5')

3、预测自己手写图像

# In[2]:


from keras.models import load_model
import numpy as np
import cv2


# In[ ]:


model = load_model('cnn_model.h5')
image = cv2.imread('1.png', 0)
img = cv2.imread('1.png', 0)
img = np.reshape(img, (1,28,28,1)).astype(bool).astype('float32')

my_proba = model.predict_proba(img)
my_predict = model.predict_classes(img)
print('识别为:')
print(my_proba * 10**10)
print(my_predict * 10**10)
cv2.imshow('Image1', image)
cv2.waitKey(0)

你可能感兴趣的:(十九个小项目,卷积,神经网络,网络,python,机器学习)