美文网首页
Keras初尝试——Minst手写数字识别

Keras初尝试——Minst手写数字识别

作者: answerLDA | 来源:发表于2019-10-21 11:17 被阅读0次

Keras简介

Keras是Python中以CNTK、Tensorflow或者Theano为计算后台的一个深度学习建模环境。相对于其他深度学习的计算软件,如:Tensorflow、Theano、Caffe等,Keras在实际应用中有一些显著的优点,其中最主要的优点就是Keras已经高度模块化了,支持现有的常见模型(CNN、RNN等),更重要的是建模过程相当方便快速,加快了开发速度。

使用的是基于Tensorflow为计算后台。接下来将介绍一些建模过程的常用层、搭建模型和训练过程,而Keras中的文字、序列和图像数据预处理,我们将在相应的实践项目中进行讲解。

image

1.核心层(各层函数只介绍一些常用参数,详细参数介绍可查阅Keras文档)

1.1全连接层:

神经网络中最常用到的,实现对神经网络里的神经元激活。

Dense(units, activation=’relu’, use_bias=True)

参数说明:

units: 全连接层输出的维度,即下一层神经元的个数。

activation:激活函数,默认使用Relu。

use_bias:是否使用bias偏置项。

1.2激活层:

对上一层的输出应用激活函数。

Activation(activation)

参数说明:

Activation:想要使用的激活函数,如:’relu’、’tanh’、‘sigmoid’等。

1.3Dropout层:

对上一层的神经元随机选取一定比例的失活,不更新,但是权重仍然保留,防止过拟合。

Dropout(rate)

参数说明:

rate:失活的比例,0-1的浮点数。

1.4Flatten层:

将一个维度大于或等于3的高维矩阵,“压扁”为一个二维矩阵。即保留第一个维度(如:batch的个数),然后将剩下维度的值相乘作为“压扁”矩阵的第二个维度。

Flatten()

1.5Reshape层:

该层的作用和reshape一样,就是将输入的维度重构成特定的shape。

Reshape(target_shape)

参数说明:

target_shape:目标矩阵的维度,不包含batch样本数。

如我们想要一个9个元素的输入向量重构成一个(None, 3, 3)的二维矩阵:

Reshape((3,3), input_length=(16, ))

1.6卷积层:

卷积操作分为一维、二维、三维,分别为Conv1D、Conv2D、Conv3D。一维卷积主要应用于以时间序列数据或文本数据,二维卷积通常应用于图像数据。由于这三种的使用和参数都基本相同,所以主要以处理图像数据的Conv2D进行说明。

Conv2D(filters, kernel_size, strides=(1, 1), padding=’valid’)

参数说明:

filters:卷积核的个数。

kernel_size:卷积核的大小。

strdes:步长,二维中默认为(1, 1),一维默认为1。

Padding:补“0”策略,’valid‘指卷积后的大小与原来的大小可以不同,’same‘则卷积后大小与原来大小一致。

1.7池化层:

与卷积层一样,最大统计量池化和平均统计量池化也有三种,分别为MaxPooling1D、MaxPooling2D、MaxPooling3D和AveragePooling1D、AveragePooling2D、AveragePooling3D,由于使用和参数基本相同,所以主要以MaxPooling2D进行说明。

MaxPooling(pool_size=(2,2), strides=None, padding=’valid’)

参数说明:

pool_size:长度为2的整数tuple,表示在横向和纵向的下采样样子,一维则为纵向的下采样因子。

padding:和卷积层的padding一样。

1.8循环层:

循环神经网络中的RNN、LSTM和GRU都继承本层,所以该父类的参数同样使用于对应的子类SimpleRNN、LSTM和GRU。

Recurrent(return_sequences=False)

return_sequences:控制返回的类型,“False”返回输出序列的最后一个输出,“True”则返回整个序列。当我们要搭建多层神经网络(如深层LSTM)时,若不是最后一层,则需要将该参数设为True。

1.9嵌入层:

该层只能用在模型的第一层,是将所有索引标号的稀疏矩阵映射到致密的低维矩阵。如我们对文本数据进行处理时,我们对每个词编号后,我们希望将词编号变成词向量就可以使用嵌入层。

Embedding(input_dim, output_dim, input_length)

参数说明:

Input_dim:大于或等于0的整数,字典的长度即输入数据的个数。

output_dim:输出的维度,如词向量的维度。

input_length:当输入序列的长度为固定时为该长度,然后要在该层后加上Flatten层,然后再加上Dense层,则必须指定该参数,否则Dense层无法自动推断输出的维度。

该层可能有点费解,举个例子,当我们有一个文本,该文本有100句话,我们已经通过一系列操作,使得文本变成一个(100,32)矩阵,每行代表一句话,每个元素代表一个词,我们希望将该词变为64维的词向量:

Embedding(100, 64, input_length=32)

则输出的矩阵的shape变为(100, 32, 64):即每个词已经变成一个64维的词向量。


keras常用模块介绍

image

'Input','Model','Sequential',这三个模块是以前老的接口,新的版本已经将它们融合到后面的模块当中

以'__'开头的模块是一些内嵌的模块

'activations'是激活函数,包括像sigmoid,relu,softmax等

'applications'是应用,这里面提供了已经训练好的keras模型,像图像识别的VGG等

'backend'是后端函数,keras通过它来操作其他的后端执行代码,像tensorflow,theano等,在后面使用models时,models会自动地调用

'callbacks'是一个回调的抽象函数,在高级应用里面可以用来展示训练过程中网络内部的状态

'constraints'是一个约束项,主要是能够对神经网络进行约束,来防止神经网络的过拟合

'datasets'里面包含了很多神经网络常用的数据集

'engine'是引擎模块,是layers的核心代码,主要是用来实现神经网络的拓补结构,后面的层的构建都是从这里继承而来

'initializers'是初始化方法

'layers'里面包含了keras已经实现的一些网络层,像全连接层Dense,卷积神经网络中的Conv

'legacy'是遗留代码,旧版本的代码都放在里面

'losses'是目标函数,也就损失函数,代价函数等,包括像均方差误差,交叉熵等等,用来衡量神经网络训练过程中的训练的好坏,能够看在迭代的过程中神经网络的一个训练情况

'metrics'是评估函数,可以用来评估神经网络的性能,里面包括像准确度,召回率等

'models'是模型库,Keras有两种类型的模型,序贯模型(Sequential)和函数式模型(Model),函数式模型应用更为广泛,序贯模型是函数式模型的一种特殊情况。序贯模型:使用序贯模型可以像搭积木一样一层一层地网上叠加神经网络

'optimizers'是优化器,神经网络编译时必备的参数之一,可以用来在神经网络训练过程当中来更新权值的一个方法

'preprocessing'是预处理模块,包括对数据,序列,文本以及图像数据的预处理

'regularizers'是正则化方法,是用来防止神经网络在训练过程中出现过拟合

'utils'工具模块,本模块提供了一系列有用工具,用于提供像数据转换,数据规范化等功能

'wrappers'包装器(层封装器),能够将普通层进行包装,比如将普通数据封装成时序数据


Keras模型构建——简单的Minst手写数字识别

代码里面有注释,查看注释即可。

# ===================Hello Keras for mnist=================
# 这是一个简单的全连接神经网络的例子。
import keras
from keras.models import Sequential  # 采用贯序模型
from keras.layers import Input, Dense, Dropout, Activation
from keras.models import Model
from keras.optimizers import SGD
from keras.datasets import mnist
import numpy as np

#数据预处理
def dataProcess(f):

    #区分训练集和测试集
    X_train, y_train = f['x_train'], f['y_train']
    X_test, y_test = f['x_test'], f['y_test']
    f.close()

    # 由于mist的输入数据维度是(num, 28, 28),这里需要把后面的维度直接拼起来变成784维
    X_train = X_train.reshape(X_train.shape[0], X_train.shape[1] * X_train.shape[2])
    X_test = X_test.reshape(X_test.shape[0], X_test.shape[1] * X_test.shape[2])
    # 这个能生成一个OneHot的10维向量,作为Y_train的一行,这样Y_train就有60000行OneHot作为输出
    Y_train = (np.arange(10) == y_train[:, None]).astype(int)  # 整理输出
    Y_test = (np.arange(10) == y_test[:, None]).astype(int)  # np.arange(5) = array([0,1,2,3,4])
    return X_train,Y_train,X_test,Y_test

def designModel():
    model = Sequential()  # 采用贯序模型
    #构建网络层
    #构建网络只是构建了一个网络结构,并定义网络的参数,此时还没有输入的数据集
    # 构建的第一个层作为输入层
    # Dense 这是第一个隐藏层,并附带定义了输入层,该隐含层有500个神经元。输入则是 784个节点
    model.add(Dense(784, input_shape=(784,)))  # 输入层,28*28=784 输入层将二维矩阵换成了一维向量输入
    model.add(Activation('tanh'))  # 激活函数是tanh 为双曲正切  tanh(x) = sinh(x)/cosh(x) = (e^x - e^(-x))/(e^x + e^(-x))
    model.add(Dropout(0.5))  # 采用50%的dropout  随机取一半进行训练

    # 构建的第2个层作为隐藏层2, (如果加上输入层,实际上是第三层)
    model.add(Dense(784))  # 隐藏层节点500个
    model.add(Activation('tanh'))
    model.add(Dropout(0.5))

    model.add(Dense(784))  # 隐藏层3,节点500个
    model.add(Activation('tanh'))
    # model.add(Dropout(0.5))

    # 构建的第3个层作为输出层
    model.add(Dense(10))  # 输出结果是10个类别,所以维度是10
    # softmax介绍可以参考https://blog.csdn.net/haolexiao/article/details/72757796
    model.add(Activation('softmax'))  # 最后一层用softmax作为激活函数

    #网络优化和编译
    #   lr:大于0的浮点数,学习率
    #   momentum:大于0的浮点数,动量参数
    #   decay:大于0的浮点数,每次更新后的学习率衰减值
    #   nesterov:布尔值,确定是否使用Nesterov动量
    sgd = SGD(lr=0.005, decay=1e-6, momentum=0.9, nesterov=True)  # 优化函数,设定学习率(lr)等参数

    # 只有通过了编译,model才真正的建立起来,这时候才能够被使用
    # model.compile(loss='categorical_crossentropy', optimizer=sgd, class_mode='categorical') # 使用交叉熵作为loss函数 这是原例子,但是执行出错
    model.compile(loss='categorical_crossentropy', optimizer=sgd)  # 使用交叉熵作为loss函数    # 去掉 class_mode 即可。可能是版本不同导致的???
    return model

def validate(model,X_test,Y_test,tBatchSize):
    #第五步:输出
    print("test set")
    # 误差评价 :按batch计算在batch用到的输入数据上模型的误差
    scores = model.evaluate(X_test, Y_test, batch_size=tBatchSize, verbose=0)
    print("")
    print("The test loss is %f" % scores)

    # 根据模型获取预测结果  为了节约计算内存,也是分组(batch)load到内存中的,
    result = model.predict(X_test, batch_size=tBatchSize, verbose=1)

    # 找到每行最大的序号
    result_max = np.argmax(result, axis=1)  # axis=1表示按行 取最大值   如果axis=0表示按列 取最大值 axis=None表示全部
    test_max = np.argmax(Y_test, axis=1)  # 这是结果的真实序号

    result_bool = np.equal(result_max, test_max)  # 预测结果和真实结果一致的为真(按元素比较)
    true_num = np.sum(result_bool)  # 正确结果的数量
    print("The accuracy of the model is %f" % (true_num / len(result_bool)))  # 验证结果的准确率


def main():
    # 使用Keras自带的mnist工具读取数据(第一次需要联网),有墙,获取数据失败,只能用预下载的数据
    # (X_train, y_train), (X_test, y_test) = mnist.load_data()
    # 数据集获取 mnist 数据集的介绍可以参考 https://blog.csdn.net/simple_the_best/article/details/75267863
    path = './mnist.npz'
    f = np.load(path)
    X_train, Y_train, X_test, Y_test = dataProcess(f)
    tBatchSize = 128
    model = designModel()
    '''
       训练
       .fit的一些参数
       batch_size:对总的样本数进行分组,每组包含的样本数量
       epochs :训练次数
       shuffle:是否把数据随机打乱之后再进行训练
       validation_split:拿出百分之多少用来做交叉验证
       verbose:屏显模式 0:不输出  1:输出进度  2:输出每次的训练结果
    '''
    model.fit(X_train, Y_train, batch_size=tBatchSize, epochs=20, shuffle=True, verbose=2, validation_split=0.3)
    # model.evaluate(X_test, Y_test, batch_size=200, verbose=0)
    validate(model,X_test,Y_test,tBatchSize)


if __name__ == '__main__':
    main()
image

相关文章

网友评论

      本文标题:Keras初尝试——Minst手写数字识别

      本文链接:https://www.haomeiwen.com/subject/mbttvctx.html