我的tensorflow学习笔记(9):tf中的CNN

本文介绍了在TensorFlow中如何使用卷积神经网络(CNN),包括直接卷积、在MNIST数据集上的应用,以及利用tf.layers简化CNN的构建。通过两层卷积网络和ReLU激活函数,结合Max Pooling,提高图像识别效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、直接卷积

    

    卷积在深度学习中非常常见。并且实际上我们可以不经过训练直接使用卷积,一个常见的用途是进行图片模糊:


    为了在tensorflow中使用卷积,我们可以使用几个内置图层。你可以使用一维卷积(输入为2维),二维卷积(输入为3维),三维卷积(输入为4维)。我们主要关注二维卷积,关于其他维度卷积的介绍,参考runhani’s StackOverflow answer

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
    对于步幅,不要在第一个和第四个维度中使用除1之外的任何数字,因为我们不想跳过批次中的任何样本或图像中的任何通道。 扩张也是一样。还有其他的卷积操作,更多信息参考官方文档。
conv2d: Filters that mix channels together.
depthwise_conv2d: Filters that operate on each channel independently.
separable_conv2d: A depthwise spatial filter followed by a pointwise filter.

二、在MNIST中使用CNN

    我们之前完成过单层全连接网络的逻辑拟合,效果不尽人意,让我们看看使用卷积网络的效果如何。

    对于MNIST,我们将使用两层卷积网络,每层后面跟着ReLU和Max Pooling,以及两层全连接层,每个卷积层的步长都是[1,1,1,1]。(关于ReLU,参考知乎如何理解ReLU activation function?


    因为我们将重复多次相同操作,可重复使用的代码是一个好主意。使用variable scope同样重要,这样我们可以在不同图层间使用同名变量。一个名为'weights'的变量在变量域'conv1'中将会成为'conv1/weights'。为每个图层创建一个变量域,这样就不会出现名称冲突。

    卷积层

    一个通用操作是将卷积层和非线性化归为同一组,我们将创建conv_relu以供两层共同使用。

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)

    池化层

    pooling是一种下采样技术,用于降低从卷积层提取的特征映射的维度,以减少处理时间。 pooling layer用(希望)代替数据的一个子区域,其最具代表性的特征。 最流行的池化算法,即max pooling,用其最大值替换数据的子区域。 另一种算法是average pooling,对一个子区域中的所有值进行平均。在pooling layer使用tf.nn.maxpool。

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')

    查看结果


三、tf.layers

    事实上,我们无需编写conv_relu等图层,tensorflow的tf.layers提供了很多现成的图层,更高级别的库如Keras也有很多可直接使用的模型。

    使用tf.layers创建relu非线性化的卷积层:

conv1 = tf.layers.conv2d(inputs=self.img,
                                  filters=32,
                                  kernel_size=[5, 5],
                                  padding='SAME',
                                  activation=tf.nn.relu,
                                  name='conv1')
    池化层和全连接层:
pool1 = tf.layers.max_pooling2d(inputs=conv1, 
                                        pool_size=[2, 2], 
                                        strides=2,
                                        name='pool1')

fc = tf.layers.dense(pool2, 1024, activation=tf.nn.relu, name='fc')
    使用tf.layers时要注意一点:需要一个变量来指示它处于训练模式还是评估模式。我们在训练时会剔除(drop out)神经元,但评估时使用全部。
dropout = tf.layers.dropout(fc, 
                                    self.keep_prob, 
                                    training=self.training, 
                                    name='dropout')
    更多参考: A Guide to tf.layers



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值