美文网首页斯坦福机器学习课程
CS20si 第7课: TensorFlow中的卷积

CS20si 第7课: TensorFlow中的卷积

作者: tech0ne | 来源:发表于2018-08-02 21:44 被阅读6次

    第7课: TensorFlow中的卷积

    CS20si课程资料和代码Github地址

    没有训练的卷积

    你有可能已经熟悉数学或物理中的“卷积”,牛津词典对“卷积”在数学领域的定义如下:

    一个由两个给定的函数集成的函数,表达一个函数的形状是如何被另一个函数修改的。

    这就是卷积在机器学习中的含义,卷积是一个原始输入Input被一个核Kernel(或者叫滤波器Filter/特征图Feature Map)修改。更多的细节参照CS231n课程。

    事实上,我们可以不用训练而直接使用卷积。比如我们可以用一个3x3的卷积来模糊一张图片。

    image

    在TensorFlow中去做卷积,我们有很多内建的层可以使用。你可以输入2维数据做1维卷积,输入3维数据做2维卷积,输入4维数据做3维卷积,最常用的是2维卷积。

    tf.nn.conv2d(
        input,
        filter,
        strides,
        padding,
        use_cudnn_on_gpu=True,
        data_format='NHWC',
        dilations=[1, 1, 1, 1],
        name=None
    )
    
    Input: Batch size (N) x Height (H) x Width (W) x Channels (C)
    Filter: Height x Width x Input Channels x Output Channels
    (e.g. [5, 5, 3, 64])
    Strides: 4 element 1-D tensor, strides in each direction
    (often [1, 1, 1, 1] or [1, 2, 2, 1])
    Padding: 'SAME' or 'VALID'
    Dilations: The dilation factor. If set to k > 1, there will be k-1 skipped cells between each filter element on that dimension.
    Data_format: default to NHWC
    

    这儿还有一些其它的内建卷积:

    depthwise_conv2d: 单独处理每个channel的数据。
    separable_conv2d: 一个depthwise的空间滤波器后面跟一个逐点滤波器。
    

    作为一个有趣的练习,你可以在课程的GitHub中的kernes.py文件中看到一些著名的核的值,在07_basic_kernels.py中看到它们的用法。

    image

    在练习中,我们硬编码这些核的值,但是在训练一个CNN时,我们不知道核的最优值而是学习出它们。我们会用老朋友MNIST来做学习核的练习。

    用CNN处理MNIST

    我们曾经用含有一个全连接层的逻辑回归处理MNIST,结果是糟糕的。现在让我们看看用局部连接的CNN是否会好一些。

    我们将会用两个步长为1的卷积层,每个跟随一个relu激活和最大池化层maxpool,最后加上两个全连接层。

    image

    卷积层

    def conv_relu(inputs, filters, k_size, stride, padding, scope_name):
        with tf.variable_scope(scope_name, reuse=tf.AUTO_REUSE) as scope:
            in_channels = inputs.shape[-1]
            kernel = tf.get_variable('kernel', [k_size, k_size, in_channels, filters], 
                                    initializer=tf.truncated_normal_initializer())
            biases = tf.get_variable('biases', [filters],
                                initializer=tf.random_normal_initializer())
            conv = tf.nn.conv2d(inputs, kernel, strides=[1, stride, stride, 1], padding=padding)
        return tf.nn.relu(conv + biases, name=scope.name)
    

    池化层

    def maxpool(inputs, ksize, stride, padding='VALID', scope_name='pool'):
        with tf.variable_scope(scope_name, reuse=tf.AUTO_REUSE) as scope:
            pool = tf.nn.max_pool(inputs, 
                                ksize=[1, ksize, ksize, 1], 
                                strides=[1, stride, stride, 1],
                                padding=padding)
        return pool
    

    全连接层

    def fully_connected(inputs, out_dim, scope_name='fc'):
        with tf.variable_scope(scope_name, reuse=tf.AUTO_REUSE) as scope:
            in_dim = inputs.shape[-1]
            w = tf.get_variable('weights', [in_dim, out_dim],
                                initializer=tf.truncated_normal_initializer())
            b = tf.get_variable('biases', [out_dim],
                                initializer=tf.constant_initializer(0.0))
            out = tf.matmul(inputs, w) + b
        return out
    

    放在一起

    有了上面这些层,我们可以简单地建立我们的模型

    def inference(self):
            conv1 = conv_relu(inputs=self.img,
                            filters=32,
                            k_size=5,
                            stride=1,
                            padding='SAME',
                            scope_name='conv1')
            pool1 = maxpool(conv1, 2, 2, 'VALID', 'pool1')
            conv2 = conv_relu(inputs=pool1,
                            filters=64,
                            k_size=5,
                            stride=1,
                            padding='SAME',
                            scope_name='conv2')
            pool2 = maxpool(conv2, 2, 2, 'VALID', 'pool2')
            feature_dim = pool2.shape[1] * pool2.shape[2] * pool2.shape[3]
            pool2 = tf.reshape(pool2, [-1, feature_dim])
            fc = tf.nn.relu(fully_connected(pool2, 1024, 'fc'))
            dropout = tf.layers.dropout(fc, self.keep_prob, training=self.training, name='dropout')
            
            self.logits = fully_connected(dropout, self.n_classes, 'logits')
    

    在训练时,需要评估每个epoch的准确率。

    def eval(self):
            '''
            Count the number of right predictions in a batch
            '''
            with tf.name_scope('predict'):
                preds = tf.nn.softmax(self.logits)
                correct_preds = tf.equal(tf.argmax(preds, 1), tf.argmax(self.label, 1))
                self.accuracy = tf.reduce_sum(tf.cast(correct_preds, tf.float32))
    

    可以在课程Github的07_convnet_mnist.py中查看完整代码。

    译者注:这篇略过了很多和CS231n重复的东西,CS20si中的CNN相关课程主要看看Tensorflow的代码组织,CNN的知识还是推荐看CS231n系列课程

    相关文章

      网友评论

        本文标题:CS20si 第7课: TensorFlow中的卷积

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