美文网首页Artificial Intelligence我爱编程程序员
Tensorflow-MNIST-手写数字图像识别案例-翻译整理

Tensorflow-MNIST-手写数字图像识别案例-翻译整理

作者: zhyuzh3d | 来源:发表于2018-04-02 21:07 被阅读46次

    本篇文章主要介绍如何创建卷积神经网络(CNN:Convolutional Neural Network)用来训练模型,识别手写数字图片。

    Tensorflow的layer模型可以帮助我们方便的构建神经网络,包括密集层dense layer layer(full-connected layer全连接层)或卷积层convolutional layer。


    下载数据集

    这个数据集包含了6000个训练样本和1000个测试样本,都是手写数字0~9,灰度图片28像素x28像素。

    MNIST dataset 手写数字集图片官方地址
    百度网盘下载,密码:w0sk


    代码框架

    from __future__ import absolute_import
    from __future__ import division
    from __future__ import print_function
    
    import numpy as np
    import tensorflow as tf
    from tensorflow.examples.tutorials.mnist import input_data
    
    tf.logging.set_verbosity(tf.logging.INFO) #设定输出日志的模式
    
    #我们的程序代码将放在这里
    
    #这个文件能够直接运行,也可以作为模块被其他文件载入
    if __name__ == "__main__":
      tf.app.run()
    

    关于卷积神经网络

    卷积神经网络Convolutional neural networks (CNNs) 是目前图像识别领域最先进的模型结构。CNNs对图像应用各种过滤并从中学习得到高级结构,进而实现图像分类。

    卷积神经网络包含3个组成部分:

    • Convolutional layers卷积层 对图像应用特定数量的卷积过滤。对于每个子区域,神经层都会在输出特征映射中产生单个值,卷积层通常会将一个ReLU(Rectified Linear Units修正线性单元)激活函数应用到输出,进而在模型内产生一个非线性的结果。

    修正线性单元 (ReLU, Rectified Linear Unit),一种激活函数,ƒ(x)=max(0,x),其规则如下:如果输入为负数或 0,则输出 0;如果输入为正数,则输出等于输入。ReLU属于非饱和算法non-saturating neurons,就是说没有把输出值限定在某个特定区间,与它对应的饱和算法有sigmod:ƒ(x)=(1+e-x)-1;tanh:ƒ(x)=|tanh(x)|,ƒ(x)=tanh(x);

    激活函数 (activation function),一种函数(例如ReLUS型函数),用于对上一层的所有输入求加权和,然后生成一个输出值(通常为非线性值),并将其传递给下一层。

    • Pooling layers池化层,对卷积层提取的图像数据进行向下采样,减少特征维度,加快处理速度。常用的池化算法是最大化池化max pooling,它把输入的图像分成不重叠的子矩形区域,对每个子区域,保留最大值,忽略其他值,也控制了整体的过采样。理论基础是特征之间的关联比局部特征更加重要。

    • Dense layer密集层(full-connected layer全连接层),基于卷积层提取的特征和池化层的向下采样,进行分类classification。

      RoI pooling to size 2x2. In this example region proposal (an input parameter) has size 7x5.

    标准意义上讲,CNN网络是组合堆叠多个卷机模块,进行特征提取。每个卷积模块包含一个卷积层以及跟随其后的池化层。最后的卷积模块跟随着一个或多个密集层以进行分类。CNN网络中最后的密集层为每个可能的分类设定了一个节点,并对这每个节点使用sigmod函数输出0~1之间的值,表示该图形属于某个分类的可能性。


    构建CNN MNIST分类器

    1. Convolutional Layer卷积层 #1: 应用 32 5x5 滤镜提取5x5像素子区域,使用ReLU激活函数
    2. Pooling Layer池化层 #1: 执行最大化池化2x2滤镜,步幅stride=2确保区域不重叠
    3. Convolutional Layer卷积层 #2: 应用64 5x5过滤,使用ReLU激活函数
    4. Pooling Layer池化层 #2: Again, performs max pooling with a 执行最大池化2x2过滤,步幅2
    5. Dense Layer密集层 #1: 1,024个神经元, 丢弃正则率0.4 (训练过程中可能性低于0.4的元素将被丢弃)
    6. Dense Layer密集层 #2 (Logits Layer逻辑层): 10个神经元, 对应0~9数字

    tf.layers对象包含了创建以上三种神经层的方法:

    • conv2d(),创建2维的卷积层,参数包含:过滤数量,过滤核心尺寸,填充padding,激活函数。
    • max_pooling2d(), 使用最大化算法创建一个2维池化层。参数包含:过滤尺寸、步幅。
    • dense(),创建密集层,参数包含:神经元数量、激活函数。

    这些方法都接收一个张量tensor作为输入,然后经过变换再输出一个新的张量,这样就可以一环一环相连起来。

    接下来我们向代码结构文件中添加cnn_model_fn(features, labels, mode)函数,它接收MNIST数据的特征、标签和mode(TRAIN,EVAL,PREDICT),返回train训练、loss损失函数、predict预测三个方法。这是Tensorflow Estimator的标准接口。

    更多自定义Estimator的详情请看Tensorflow-Estimator-自定义估算器以及Tensorflow-Estimator-估算器-翻译整理两篇文章。

    添加后的代码如下:

    from __future__ import absolute_import
    from __future__ import division
    from __future__ import print_function
    
    import os
    import numpy as np
    import tensorflow as tf
    from tensorflow.examples.tutorials.mnist import input_data
    
    tf.logging.set_verbosity(tf.logging.INFO) #设定输出日志的模式
    
    #我们的程序代码将放在这里
    def cnn_model_fn(features, labels, mode):
        #输入层,-1表示自动计算,这里是图片批次大小,宽高各28,最后1表示颜色单色
        input_layer = tf.reshape(features["x"], [-1, 28, 28, 1])
    
        #1号卷积层,过滤32次,核心区域5x5,激活函数relu
        conv1 = tf.layers.conv2d(
            inputs=input_layer,#接收上面创建的输入层输出的张量
            filters=32,
            kernel_size=[5, 5],
            padding="same",
            activation=tf.nn.relu)
    
        #1号池化层,接收1号卷积层输出的张量
        pool1 = tf.layers.max_pooling2d(inputs=conv1, pool_size=[2, 2], strides=2)
    
        #2号卷积层
        conv2 = tf.layers.conv2d(
            inputs=pool1,#继续1号池化层的输出
            filters=64,
            kernel_size=[5, 5],
            padding="same",
            activation=tf.nn.relu)
        
        #2号池化层
        pool2 = tf.layers.max_pooling2d(inputs=conv2, pool_size=[2, 2], strides=2)
    
        #对2号池化层的输入变换张量形状
        pool2_flat = tf.reshape(pool2, [-1, 7 * 7 * 64])
        
        #密度层
        dense = tf.layers.dense(inputs=pool2_flat, units=1024, activation=tf.nn.relu)
        
        #丢弃层进行简化
        dropout = tf.layers.dropout(
          inputs=dense, rate=0.4, training=mode == tf.estimator.ModeKeys.TRAIN)
    
        #使用密度层作为最终输出,unit可能的分类数量
        logits = tf.layers.dense(inputs=dropout, units=10)
        
        #预测和评价使用的输出数据内容
        predictions = {
          #产生预测,argmax输出第一个轴向的最大数值
          "classes": tf.argmax(input=logits, axis=1),
          #输出可能性
          "probabilities": tf.nn.softmax(logits, name="softmax_tensor")
        }
    
        #以下是根据mode切换的三个不同的方法,都返回tf.estimator.EstimatorSpec对象
      
        #预测
        if mode == tf.estimator.ModeKeys.PREDICT:
            return tf.estimator.EstimatorSpec(mode=mode, predictions=predictions)
    
        #损失函数(训练与评价使用),稀疏柔性最大值交叉熵
        loss = tf.losses.sparse_softmax_cross_entropy(labels=labels, logits=logits)
    
        #训练,使用梯度下降优化器,
        if mode == tf.estimator.ModeKeys.TRAIN:
            optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.001)
            train_op = optimizer.minimize(
                loss=loss,
                global_step=tf.train.get_global_step())
            return tf.estimator.EstimatorSpec(mode=mode, loss=loss, train_op=train_op)
    
        #评价函数(上面两个mode之外else)添加评价度量(for EVAL mode)
        eval_metric_ops = {
            "accuracy": tf.metrics.accuracy(
                labels=labels, predictions=predictions["classes"])}
        return tf.estimator.EstimatorSpec(
            mode=mode, loss=loss, eval_metric_ops=eval_metric_ops)
    
    
    
    #这个文件能够直接运行,也可以作为模块被其他文件载入
    if __name__ == "__main__":
      tf.app.run()
    

    这时候以上代码还不能运行。以下将逐个代码块详细解说。


    Input Layer输入层

    tf.layers中创建神经层的方法参数格式是:
    [batch_size,imgage_width,imgage_height,channels]

    • batch_size批次尺寸,在训练过程中梯度下降所使用的样本子集的大小。
    • image_width和image_height,图像的宽高。
    • channels通道,图片像素的颜色通道数,一般是3(RGB),在这里是黑白图片只有1个颜色。

    MNIST的图片是28x28单色,[batch_size,28,28,1],我们用-1表示依靠features['x']数量动态计算得到这个数值,那么把它变换一下:

    input_layer = tf.reshape(features["x"], [-1, 28, 28, 1])

    在这里batch_size作为一个超参数hyperparameters,如果我们使用batch_size=5,那么input_layers的形状就是[5,28,28,1],它将包含5x28x28x1=3920个值,每个值表示一个颜色,每784个值表示一张图,5张为一批次。


    Convolutional layer #1卷积层1号

    conv1 = tf.layers.conv2d(
        inputs=input_layer,
        filters=32,
        kernel_size=[5, 5],
        padding="same",
        activation=tf.nn.relu)
    

    我们使用了32次5x5像素过滤filters,使用ReLU作为激活函数。由于承接了input_layer的输出,所以进入的张量形状是[batch_size,28,28,1].
    padding参数有两个可选,默认的"valid"或"same",为了保持输出的宽高不变,我们选择了"same",Tensorflow会自动用0补齐以确保图像是28x28像素。(如果不使用padding,那么在28x28个网格中只有24x24的区域可以放置5x5的面片,如下图所示黄色区域,也就是会产生24x24的张量。)

    激活函数ReLU将应用在卷积输出的张量上。最终从conv2d层输出的张量形状是[batch_size,28,28,32],这里的32是指我们进行了32次过滤产生的不同结果。


    Pooling Layer #1池化层1号

    pool1 = tf.layers.max_pooling2d(inputs=conv1, pool_size=[2, 2], strides=2)

    conv1作为输入层,将会输入的张量形状是[batch_size,28,28,32]。
    pool_size设定了最大池化过滤的尺寸[width,height]就是[2,2]。
    stredes表示过滤的步长,我们这里设定了stredes=2,表示滤镜对子区域subregions进行提取是按照宽高分别间隔2像素进行的,由于过滤尺寸也是[2,2],所以不会产生重叠也不会产生丢失。



    max_pooling层pool1输出的张量形状是[batch_size,14,14,32],因为2x2过滤把宽高减少了一半。


    Convolutional layer #2 & Pooling layer #2卷积层2号和池化层2号

    conv2 = tf.layers.conv2d(
        inputs=pool1,
        filters=64,
        kernel_size=[5, 5],
        padding="same",
        activation=tf.nn.relu)
    
    pool2 = tf.layers.max_pooling2d(inputs=conv2, pool_size=[2, 2], strides=2)
    

    2号卷积层我们使用了64次5x5区域的过滤,仍然是ReLU激活函数。而2号池化层我们仍然使用了[2,2]区域2步幅间隔的设定。

    注意2号卷积层设定了padding="same"且64次过滤,所以输出的张量形状是[batch_size,14,14,64]。
    池化层2号则再次把维度降低到[batch_size,7,7,64]。


    Dense layer密集层

    接下来我们将添加一个1024神经元ReLU激活的密集层(全连接层),基于上面卷积层和池化层得到的结果进行分类。

    首先,我们把上面pool2池化层得到的特征映射features map([batch_size,7,7,64])展开,转换到[batch_size,features]。

    pool2_flat = tf.reshape(pool2, [-1, 7 * 7 * 64])

    -1表示这个维度根据计算得到,在这里我们将得到一个[batch_size,3136]的张量(7764=3136)。

    然后我们再把这个结果传递到密集层Dense layer:

    dense = tf.layers.dense(inputs=pool2_flat, units=1024, activation=tf.nn.relu)

    为了改进我们模型的结果,增加一个dropout丢弃规则,

    dropout = tf.layers.dropout(
        inputs=dense, rate=0.4, training=mode == tf.estimator.ModeKeys.TRAIN)
    

    这里rate=0.4表示在训练过程中,40%的元素会被随机丢弃。注意training参数限定了尽在训练模式下才执行随机丢弃,预测和评价时候不丢弃。

    最终,由于使用了1024个神经元,dropout输出的张量形状是[batch_size,1024]。


    Logits layer逻辑层

    逻辑层是我们神经网络的最后一层,他将输出预测的原始数据。我们使用dense创建了10个神经元的密集层,表示0~9个数字,使用默认的linear线性激活函数。

    logits = tf.layers.dense(inputs=dropout, units=10)

    这样,我们的CNN卷积神经网络最后输出的张量形状就是[batch_size,10]。


    生成预测函数

    以上,逻辑层生成的张量是[batch_size,10]。我们用两个函数将这个原始数据转为两个不同的格式,作为最终的预测结果:

    • 每个样本的预测分类predicted class,0~9中的一个数字。
    • 每个样本属于每个分类的可能性probabilities,样本可能是0,可能是1,可能是2,可能是...

    tf.argmax(input=logits, axis=1)

    对于我们这个案例,每个样本的预测分类,就是逻辑层输出张量中对应行中值最高的元素。我们使用argmax方法取得它:

    tf.argmax(input=logits, axis=1)

    注意这里axis等于1而不是0,因为我们从逻辑层获得的张量形状是[batch_size,10],也就是10对应的列中每个元素,选取值最大的元素返回。

    我们把预测结果封装到一个字典,放入EstimatorSpec对象:

    predictions = {
        "classes": tf.argmax(input=logits, axis=1),
        "probabilities": tf.nn.softmax(logits, name="softmax_tensor")
    }
    if mode == tf.estimator.ModeKeys.PREDICT:
      return tf.estimator.EstimatorSpec(mode=mode, predictions=predictions)
    

    Calculate loss计算损失函数

    对于训练和预测,我们需要定义一个损失函数loss function来评估我们的模型预测的有多么准确。对于多个类别的分类问题,交叉熵算法是最常用的测量标准。

    onehot_labels = tf.one_hot(indices=tf.cast(labels, tf.int32), depth=10)
    loss = tf.losses.softmax_cross_entropy(
        onehot_labels=onehot_labels, logits=logits)
    

    这里cast是转变数据类型的方法,labels的数据类似[1, 9, 6,7,3...],我们把它转为one_hot独热格式的张量:

    [[0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
     ...]
    

    tf.one_hot带有两个参数:

    • indices索引,独热数组哪一个热,比如上面第一行对应的labels是1,就是第1个是1(其他都是0);
    • depth深度,独热数组有多少个元素,在这里就是有多少个分类。

    然后,我们计算onehot_labels和逻辑层输出的张量[batch_size,10]的这两者的柔性最大交叉熵。

    loss = tf.losses.softmax_cross_entropy(
        onehot_labels=onehot_labels, logits=logits)
    

    tf.losses.softmax_cross_entropy方法返回一个标量scalar张量。


    设置训练操作Configure the training Op

    在以上,我们定义了loss函数用于评估我们预测模型最终logits层输出的结果与实际标签labels的差异度,下面让我们的模型在训练的时候反复优化这个差异度,让模型达到最佳。
    我们使用随机梯度下降函数stochastic gradient desent作为优化算法,使用学习率learning_rate=0.1:

    if mode == tf.estimator.ModeKeys.TRAIN:
      optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.001)
      train_op = optimizer.minimize(
          loss=loss,
          global_step=tf.train.get_global_step())
      return tf.estimator.EstimatorSpec(mode=mode, loss=loss, train_op=train_op)
    

    在这里,我们看到,所谓的训练操作train_op就是优化函数optimizer根据损失函数loss,一步一步尝试构造更好的模型结构。


    添加评价度量Evaluation metrics

    eval_metric_ops = {
        "accuracy": tf.metrics.accuracy(
            labels=labels, predictions=predictions["classes"])}
    return tf.estimator.EstimatorSpec(
        mode=mode, loss=loss, eval_metric_ops=eval_metric_ops)
    

    训练和评价CNN MNIST分类器

    上面我们已经完成了CNN MNIST模型函数的编写,下面我们继续实现模型的训练和预测。


    载入训练和测试数据

    首先从把从百度网盘(密码:w0sk)下载的MNIST_data文件夹(包含四个文件)放在和我们的代码相同目录下。

    然后我们添加main主函数,代码载入数据集

    dir_path = os.path.dirname(os.path.realpath(__file__))
    data_path=os.path.join(dir_path,'MNIST_data')
    def main(args):
        #载入训练和测试数据
        mnist = input_data.read_data_sets(data_path)
        train_data = mnist.train.images #得到np.array
        train_labels = np.asarray(mnist.train.labels, dtype=np.int32)
        eval_data = mnist.test.images #得到np.array
        eval_labels = np.asarray(mnist.test.labels, dtype=np.int32)
    

    你也可以参照 这篇文章 自己手工从官方下载这个数据集。


    创建估算器Estimator

    Estimator是Tensorflow的一个高级接口high-level API,专门用来对模型进行训练、和评估和预测的。

    在main里面添加下面的代码

        #创建估算器
        mnist_classifier = tf.estimator.Estimator(
            model_fn=cnn_model_fn, model_dir="/tmp/mnist_convnet_model")
    

    这里使用的两个参数:

    • model_fn,我们在上面创建神经网络CNN的主要函数,里面实现了训练、评价和预测功能。
    • model_dir,这是设置我们训练出来的模型存储的目录,只要这里设置一次,以后Tensorflow都会自动从这里读取我们训练好的模型,不需要我们添加任何其他代码。当然也可以再训练,会覆盖更新。

    设置日志钩子logging hook

    CNN训练需要花一点时间,呆看屏幕没有任何反应等待会很难熬,我们可以让Tensorflow在训练的时候输出一些有用的日志信息。

        #设置输出预测的日志
        tensors_to_log = {"probabilities": "softmax_tensor"}
        logging_hook = tf.train.LoggingTensorHook(
            tensors=tensors_to_log, every_n_iter=50)
    

    我们在这里用tensors_to_log字典来存储需要打印出来的数据,注意这里的softmax_tensor,实际是我们在上面定义过的名称(实际上我们在编写整个计算模型时候定义的张量name都可以):

    predictions = {
          "classes": tf.argmax(input=logits, axis=1),
          "probabilities": tf.nn.softmax(logits, name="softmax_tensor")
        }
    

    然后,我们创建了钩子函数LoggingTensorHook,并关联到我们的需要输出的张量,每50次迭代打印一次。


    训练模型

    为了训练模型,我们必须创建一个喂食数据的函数train_input_fn,向main函数添加以下代码:

        #训练喂食函数
        train_input_fn = tf.estimator.inputs.numpy_input_fn(
            x={"x": train_data},
            y=train_labels,
            batch_size=100,
            num_epochs=None,
            shuffle=True)
    

    我们使用了numpy_input_fn方法,它的参数里面xy对应了我们的训练特征数据和训练标签数据,batch_size表示每步数step最少训练100个样本,num_epochs=None周期数不设定表示我们一直训练直到到达指定步数为止(训练时候设定)。shuffle=true洗牌为真表示我们将随机调整样品顺序。

    我们再向main函数添加代码启动训练:

        #启动训练
        mnist_classifier.train(
            input_fn=train_input_fn,
            steps=20000,
            hooks=[logging_hook])
    

    在这里我们设定了步数20000,并且把日志钩子logging_hook传递进去。

    不要着急,我们先继续添加一些其他内容。


    评价模型Evaluate model

    训练完成后,我们希望使用测试数据集来评估一下我们的模型的精确度,看它是否足够好。继续向main函数添加下面的代码:

        #评价喂食函数
        eval_input_fn = tf.estimator.inputs.numpy_input_fn(
            x={"x": eval_data},
            y=eval_labels,
            num_epochs=1,
            shuffle=False)
        
        #启动评价并输出结果
        eval_results = mnist_classifier.evaluate(input_fn=eval_input_fn)
        print(eval_results)
    

    同样,我们也需要一个评价喂食函数,不断把需要评价的图片数据输入到模型,然后再把模型输出的预测结果和我们真实的标签对比,这样就能知道我们的模型是不是足够准确。
    注意在这里我没设置周期是1,不进行反复训练;设置shuffle=False也不随机调整顺序。


    运行吧!

    整个过程可能需要一些时间,不要着急,训练20000步数会很慢,请耐心等候。

    续,十多分钟过去了,目前才到step3000多...求祝福,求光环...
    续,我也不知道最终用了多久,大概1个多小时,这是运行后的结果,精度接近97%:

    INFO:tensorflow:Saving dict for global step 20004: accuracy = 0.9691, global_step = 20004, loss = 0.10082044
    {'accuracy': 0.9691, 'loss': 0.10082044, 'global_step': 20004}
    

    下面是完整代码,如果你的代码运行中出现问题,可以复制它:

    from __future__ import absolute_import
    from __future__ import division
    from __future__ import print_function
    
    import os
    import numpy as np
    import tensorflow as tf
    from tensorflow.examples.tutorials.mnist import input_data
    
    tf.logging.set_verbosity(tf.logging.INFO) #设定输出日志的模式
    
    #我们的程序代码将放在这里
    def cnn_model_fn(features, labels, mode):
        #输入层,-1表示自动计算,这里是图片批次大小,宽高各28,最后1表示颜色单色
        input_layer = tf.reshape(features["x"], [-1, 28, 28, 1])
    
        #1号卷积层,过滤32次,核心区域5x5,激活函数relu
        conv1 = tf.layers.conv2d(
            inputs=input_layer,#接收上面创建的输入层输出的张量
            filters=32,
            kernel_size=[5, 5],
            padding="same",
            activation=tf.nn.relu)
    
        #1号池化层,接收1号卷积层输出的张量
        pool1 = tf.layers.max_pooling2d(inputs=conv1, pool_size=[2, 2], strides=2)
    
        #2号卷积层
        conv2 = tf.layers.conv2d(
            inputs=pool1,#继续1号池化层的输出
            filters=64,
            kernel_size=[5, 5],
            padding="same",
            activation=tf.nn.relu)
        
        #2号池化层
        pool2 = tf.layers.max_pooling2d(inputs=conv2, pool_size=[2, 2], strides=2)
    
        #对2号池化层的输入变换张量形状
        pool2_flat = tf.reshape(pool2, [-1, 7 * 7 * 64])
        
        #密度层
        dense = tf.layers.dense(inputs=pool2_flat, units=1024, activation=tf.nn.relu)
        
        #丢弃层进行简化
        dropout = tf.layers.dropout(
          inputs=dense, rate=0.4, training=mode == tf.estimator.ModeKeys.TRAIN)
    
        #使用密度层作为最终输出,unit可能的分类数量
        logits = tf.layers.dense(inputs=dropout, units=10)
        
        #预测和评价使用的输出数据内容
        predictions = {
          #产生预测,argmax输出第一个轴向的最大数值
          "classes": tf.argmax(input=logits, axis=1),
          #输出可能性
          "probabilities": tf.nn.softmax(logits, name="softmax_tensor")
        }
    
        #以下是根据mode切换的三个不同的方法,都返回tf.estimator.EstimatorSpec对象
      
        #预测
        if mode == tf.estimator.ModeKeys.PREDICT:
            return tf.estimator.EstimatorSpec(mode=mode, predictions=predictions)
    
        #损失函数(训练与评价使用),稀疏柔性最大值交叉熵
        loss = tf.losses.sparse_softmax_cross_entropy(labels=labels, logits=logits)
    
        #训练,使用梯度下降优化器,
        if mode == tf.estimator.ModeKeys.TRAIN:
            optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.001)
            train_op = optimizer.minimize(
                loss=loss,
                global_step=tf.train.get_global_step())
            return tf.estimator.EstimatorSpec(mode=mode, loss=loss, train_op=train_op)
    
        #评价函数(上面两个mode之外else)添加评价度量(for EVAL mode)
        eval_metric_ops = {
            "accuracy": tf.metrics.accuracy(
                labels=labels, predictions=predictions["classes"])}
        return tf.estimator.EstimatorSpec(
            mode=mode, loss=loss, eval_metric_ops=eval_metric_ops)
    
    
    
    dir_path = os.path.dirname(os.path.realpath(__file__))
    data_path=os.path.join(dir_path,'MNIST_data')
    def main(args):
      #载入训练和测试数据
        mnist = input_data.read_data_sets(data_path)
        train_data = mnist.train.images #得到np.array
        train_labels = np.asarray(mnist.train.labels, dtype=np.int32)
        eval_data = mnist.test.images #得到np.array
        eval_labels = np.asarray(mnist.test.labels, dtype=np.int32)
        
        #创建估算器
        mnist_classifier = tf.estimator.Estimator(
            model_fn=cnn_model_fn, model_dir="/tmp/mnist_convnet_model")
        
        #设置输出预测的日志
        tensors_to_log = {"probabilities": "softmax_tensor"}
        logging_hook = tf.train.LoggingTensorHook(
            tensors=tensors_to_log, every_n_iter=50)
        
        #训练喂食函数
        train_input_fn = tf.estimator.inputs.numpy_input_fn(
            x={"x": train_data},
            y=train_labels,
            batch_size=100,
            num_epochs=None,
            shuffle=True)
        
        #启动训练
        mnist_classifier.train(
            input_fn=train_input_fn,
            steps=20000,
            hooks=[logging_hook])
        
        #评价喂食函数
        eval_input_fn = tf.estimator.inputs.numpy_input_fn(
            x={"x": eval_data},
            y=eval_labels,
            num_epochs=1,
            shuffle=False)
        
        #启动评价并输出结果
        eval_results = mnist_classifier.evaluate(input_fn=eval_input_fn)
        print(eval_results)    
    
    
    #这个文件能够直接运行,也可以作为模块被其他文件载入
    if __name__== "__main__":
        tf.app.run()
    

    探索人工智能的新边界

    如果您发现文章错误,请不吝留言指正;
    如果您觉得有用,请点喜欢;
    如果您觉得很有用,感谢转发~


    END

    相关文章

      网友评论

        本文标题:Tensorflow-MNIST-手写数字图像识别案例-翻译整理

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