美文网首页数据挖掘&机器学习大数据
基于tensorflow的MNIST手写数字识别(三)--神经

基于tensorflow的MNIST手写数字识别(三)--神经

作者: 会打代码的扫地王大爷 | 来源:发表于2016-06-17 01:03 被阅读8316次

    基于tensorflow的MNIST手写字识别(一)--白话卷积神经网络模型

    基于tensorflow的MNIST手写数字识别(二)--入门篇

    基于tensorflow的MNIST手写数字识别(三)--神经网络篇

    想想还是要说点什么

    抱歉啊,第三篇姗姗来迟,确实是因为我懒,而不是忙什么的,所以这次再加点料,以表示我的歉意。废话不多说,我就直接开始讲了。

    加入神经网络的意义

    1.  前面也讲到了,使用普通的训练方法,也可以进行识别,但是识别的精度不够高,因此我们需要对其进行提升,其实MNIST官方提供了很多的组合方法以及测试精度,并做成了表格供我们选用,谷歌官方为了保证教学的简单性,所以用了最简单的卷积神经网络来提升这个的识别精度,原理是通过强化它的特征(比如轮廓等),其实我也刚学,所以能看懂就说明它确实比较简单。

    2. 我的代码都是在0.7版本的tensorflow上实现的,建议看一下前两篇文章先。

    流程和步骤

    其实流程跟前面的差不多,只是在softmax前进行了卷积神经网络的操作,所也就不仔细提出了,这里只说卷积神经网络的部分。

    如第一篇文章所说,我们的卷积神经网络的,过程是卷积->池化->全连接.

    # 卷积函数

    # convolution

    defconv2d(x, W):

    return   tf.nn.conv2d(x, W, strides=[1,1,1,1], padding='SAME')

    #这里tensorflow自己带了conv2d函数做卷积,然而我们自定义了个函数,用于指定步长为1,边缘处理为直接复制过来

    # pooling

    defmax_pool_2x2(x):

    return  tf.nn.max_pool(x, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')

    tf.nn.conv2d(input, filter, strides, padding, use_cudnn_on_gpu=None, name=None)

    Computes a 2-D convolution given 4-D input and filter tensors.

    Given an input tensor of shape [batch, in_height, in_width, in_channels] and a filter / kernel tensor of shape [filter_height, filter_width, in_channels, out_channels], this op performs the following:

    Flattens the filter to a 2-D matrix with shape [filter_height * filter_width * in_channels, output_channels].

    Extracts image patches from the the input tensor to form a virtual tensor of shape [batch, out_height, out_width, filter_height * filter_width * in_channels].

    For each patch, right-multiplies the filter matrix and the image patch vector.

    In detail,

    output[b, i, j, k] =

    sum_{di, dj, q} input[b, strides[1] * i + di, strides[2] * j + dj, q] * filter[di, dj, q, k]

    Must have strides[0] = strides[3] = 1. For the most common case of the same horizontal and vertices strides, strides = [1, stride, stride, 1].

    Args:

    input: A Tensor. Must be one of the following types: float32, float64.

    filter: A Tensor. Must have the same type as input.

    strides: A list of ints. 1-D of length 4. The stride of the sliding window for each dimension of input.

    padding: A string from: “SAME”, “VALID”. The type of padding algorithm to use.

    use_cudnn_on_gpu: An optional bool. Defaults to True.

    name: A name for the operation (optional).

    Returns:

    A Tensor. Has the same type as input.

    tf.nn.max_pool(value, ksize, strides, padding, name=None)

    Performs the max pooling on the input.

    Args:

    value: A 4-D Tensor with shape [batch, height, width, channels] and type float32, float64, qint8, quint8, qint32.

    ksize: A list of ints that has length >= 4. The size of the window for each dimension of the input tensor.

    strides: A list of ints that has length >= 4. The stride of the sliding window for each dimension of the input tensor.

    padding: A string, either ‘VALID’ or ‘SAME’. The padding algorithm.

    name: Optional name for the operation.

    Returns:

    A Tensor with the same type as value. The max pooled output tensor.

    初始化权重和偏置值矩阵,值是空的,需要后期训练。

    def weight_variable(shape):

           initial = tf.truncated_normal(shape,stddev=0.1)

           return tf.Variable(initial)

    def bias_variable(shape):

         initial = tf.constant(0.1, shape = shape)

        # print(tf.Variable(initial).eval())

         return tf.Variable(initial)

    #这是做了两次卷积和池化

    h_conv1 = tf.nn.relu(conv2d(x_image, w_conv1) + b_conv1)

    h_pool1 = max_pool_2x2(h_conv1)

    h_conv2 = tf.nn.relu(conv2d(h_pool1, w_conv2) + b_conv2)

    h_pool2 = max_pool_2x2(h_conv2)

    这里是做了全连接,还用了relu激活函数(RELU在下面会提到)

    h_pool2_flat = tf.reshape(h_pool2, [-1,7*7*64])

    h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, w_fc1) + b_fc1)

    #为了防止过拟合化,这里用dropout来关闭一些连接(DROP下面会提到)

    h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

    然后得到的结果再跟之前的一样,使用softmax等方法训练即可得到参数。

    RELU激活函数

    激活函数有很多种,最常用的是以下三种

    Sigmoid

    将数据映射到0-1范围内

    #### 公式如下

    ####函数图像如下

    Tanh

    将数据映射到-1-1的范围内

    公式如下

    函数图像如下

    RELU

    小于0的值就变成0,大于0的等于它本身

    函数图像

    具体的参考这个http://blog.csdn.net/u012526120/article/details/49149317

    dropout的作用

    1.以前学习数学我们常用到一种方法,叫做待定系数法,就是给定2次函数上的几个点,然后求得2次函数的参数。

    2.一样的道理,我们这里用格式训练集训练,最后训练得到参数,其实就是在求得一个模型(函数),使得它能跟原始数据的曲线进行拟合(说白了,就是假装原始数据都在我们计算出来的函数上)

    3.但是这样不行啊,因为我们还需要对未知数据进行预测啊,如果原始的数据点都在(或者大多数都在)函数上了(这就是过拟合),那会被很多训练数据误导的,所以其实只要一个大致的趋势函数就可以了

    4.所以Dropout函数就是用来,减少某些点的全连接(可以理解为把一些点去掉了),来防止过拟合

    具体的看这个http://www.cnblogs.com/tornadomeet/p/3258122.html

    代码

    水完了,看代码吧,注释上有写一些变量的维度,大家可以一步步地看过去,计算过去

    https://github.com/wlmnzf/tensorflow-train/blob/master/mnist/cnn_mnist.py

    相关文章

      网友评论

      • RitterLiu:感谢分享,很好的入门文章

      本文标题: 基于tensorflow的MNIST手写数字识别(三)--神经

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