zoukankan      html  css  js  c++  java
  • tensorflow处理mnist(二)

    用卷积神经网络解决mnist的分类问题.

    简单的例子

    一行一行解释这个代码. 这个不是google官方的例子,但是很简洁,便于入门.tensorflow是先定义模型,最后赋值,计算.为了讨论问题方便,还是按照以前的讨论方法,先假定数据集只有16张图片.x是16*784的矩阵.weights是一个包含多个矩阵的map. biases是包含多个向量的map.算法就是为了训练weights和biases.

    def conv2d(x, W, b, strides=1):
        x = tf.nn.conv2d(x, W, strides=[1, strides, strides, 1], padding='SAME')
        x = tf.nn.bias_add(x, b)
        return tf.nn.relu(x)
    x = tf.reshape(x, shape=[-1, 28, 28, 1])
    conv1 = conv2d(x, weights['wc1'], biases['bc1'])
    

    把x转化成16*28*28*1. 16表示有几张图片,28表示宽是几个像素,第2个28表示长有几个像素,1表示通道数,mnist是黑白图片,所以通道数是1.wc1是5*5*1*32的矩阵,bc1是长度为32的向量.strides的4个数分别代表滑动时4个值的偏移量.现在先暂时关注中间2个,长宽的偏移量.对于padding这个参数,这时不讨论它的实际意义,根据参考资料1,它影响的是图片周围补充0的个数.当padding=SAME时,图片周围补充0的个数计算方法如下:

    pad_along_height = max((out_height - 1) * strides[1] + filter_height - in_height, 0)
    pad_along_width = max((out_width - 1) * strides[2] + filter_width - in_width, 0)
    pad_top = pad_along_height
    pad_bottom = pad_along_height - pad_top
    pad_left = pad_along_width
    pad_right = pad_along_width - pad_left
    

    输出的宽高计算方法如下:

    out_height = ceil(float(in_height) / float(strides[1]))
    out_width  = ceil(float(in_width) / float(strides[2]))
    

    这里有可以运行的python代码:

    import math
    class PaddingConv:
        def __init__(self, strides, in_height, in_width, filter_height, filter_width):
            self.out_height = math.ceil(float(in_height) / float(strides[1]))
            self.out_width = math.ceil(float(in_width) / float(strides[2]))
            pad_along_height = max((self.out_height - 1) * strides[1] + filter_height - in_height, 0)
            pad_along_width = max((self.out_width - 1) * strides[2] + filter_width - in_width, 0)
            self.pad_top = pad_along_height
            self.pad_bottom = pad_along_height - self.pad_top
            self.pad_left = pad_along_width
            self.pad_right = pad_along_width - self.pad_left
    print("pad_top=" + str(p.pad_top))
    print("pad_bottom=" + str(p.pad_bottom))
    print("pad_left=" + str(p.pad_left))
    print("pad_right=" + str(p.pad_right))
    print("out_height=" + str(p.out_height))
    print("out_width=" + str(p.out_width))
    

    tf.nn.conv2d(x, W, strides=[1, strides, strides, 1], padding='SAME')之后x变成16*28*28*32,计算方法见上面的公式.bias_add,relu都不影响结果的结构.所以第一次conv2d之后,返回的是16*28*28*32的矩阵.

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

    卷积之后要进行池化操作.max_pool的strides,padding参数和conv2d中的是一样的.ksize只用关注中间2个数.代表卷积核的宽长是多少,就是上面filter_width,filter_height的大小.可以同样用PaddingConv计算池化后的宽长.

    p = PaddingConv(strides=[1, 2, 2, 1], in_height=28, in_width=28, filter_height=2, filter_width=2)
    print("out_height=" + str(p.out_height))
    print("out_width=" + str(p.out_width))
    print("pad_top=" + str(p.pad_top))
    print("pad_bottom=" + str(p.pad_bottom))
    print("pad_left=" + str(p.pad_left))
    print("pad_right=" + str(p.pad_right))
    

    池化不影响通道数.wc2是5*5*32*64的矩阵.bc2是长度为64的一维数组.输入是16*14*14*32的矩阵.通过PaddingConv可以计算出输出的长宽为14*14.输出通道数是64,即输出是16*14*14*64的矩阵.通过PaddingConv可以计算出池化后为16*7*7*64的矩阵.

    fc1 = tf.reshape(conv2, [-1, weights['wd1'].get_shape().as_list()[0]])
    

    conv2被转化为fc1,结果是16*3136.再乘下wd1(3136*1024),加上bd1.

    fc1 = tf.add(tf.matmul(fc1, weights['wd1']), biases['bd1'])
    

    fc1变成16*1024的矩阵

    fc1 = tf.nn.relu(fc1)
    fc1 = tf.nn.dropout(fc1, dropout)
    

    relu和dropout都不改变结果的形状.fc1仍为16*1024.

    tf.add(tf.matmul(fc1, weights['out']), biases['out'])
    

    out是1024*10,所以最终结果是16*10的矩阵.后面的代码和上一篇是非常类似的.不再解释.

    问题

    官方的例子没有完全弄明白.

    参考资料

    • tensorflow官方api
  • 相关阅读:
    sortColors
    搜索二维矩阵
    矩阵置零
    求解最大子数组的和
    length of the longest substring without repeating character
    求解最大回文子字符串
    求两数的和
    验证回文串的一点解题思路
    fiddler-10-结合 Mock.js 伪接口数据进行测试(下)
    fiddler-9-结合 Mock.js 伪接口数据进行测试(上)
  • 原文地址:https://www.cnblogs.com/zhouyang209117/p/6540938.html
Copyright © 2011-2022 走看看