05. 卷积神经网络(CNN)

1. 卷积神经网络与简单的全连接神经网络的比较

  • 深度学习网络与更常见的单一隐藏层神经网络的区别在于深度,深度学习网络中,每一个节点层在前一层输出的基础上学习识别一组特定的特征。随着神经网络深度增加,节点所能识别的特征也就越来越复杂。

  • 全连接神经网络的缺点

    • 参数太多,在cifar-10的数据集中,只有32323,就会有这么多权重,如果说更大的图片,比如2002003就需要120000多个,这完全是浪费
    • 没有利用像素之间位置信息,对于图像识别任务来说,每个像素与周围的像素都是联系比较紧密的。
    • 层数限制

2. 卷积神经网络的发展历史(图)

在这里插入图片描述
在这里插入图片描述

3. 卷积神经网络的结构分析

3.1. 图

在这里插入图片描述

3.2. 简单定义

  • 神经网络(neural networks)的基本组成包括输入层、隐藏层、输出层。而卷积神经网络的特点在于隐藏层分为卷积层和池化层(pooling layer,又叫下采样层)。
    • 卷积层:通过在原始图像上平移来提取特征,每一个特征就是一个特征映射
    • 池化层:通过特征后稀疏参数来减少学习的参数,降低网络的复杂度,(最大池化和平均池化)

3.3. 神经网络的结构及体积变换

3.3.1. 卷积层过滤器

  • 个数
  • 大小
  • 步长
  • 零填充

3.3.2. 激活函数


  • 在这里插入图片描述

  • 演示链接

    • http://playground.tensorflow.org/
  • 采用relu而不用sigmoid的原因

    • 采用sigmoid等函数,反向传播求误差梯度时,计算量相对大,而采用Relu激活函数,整个过程的计算量节省很多
    • 对于深层网络,sigmoid函数反向传播时,很容易就会出现梯度消失的情况(求不出权重和偏置)

3.3.3. 池化层

  • Pooling层主要的作用是特征提取,通过去掉Feature Map中不重要的样本,进一步减少参数数量。Pooling的方法很多,最常用的是Max Pooling。

  • 在这里插入图片描述

3.3.4. 全连接层

  • 前面的卷积和池化相当于做特征工程,后面的全连接相当于做特征加权。最后的全连接层在整个卷积神经网络中起到“分类器”的作用。

3.3.5. 体积变换

  • 输入体积大小H1 * W1 * D1

    • 输入高度:H1
    • 输入宽度:W1
    • 输入深度:D1
  • 四个超参数

    • 过滤器数量K
    • 过滤器大小F
    • 步长S
    • 零填充大小P
  • 输出体积大小 H2 * W2 * D2

    • 输出体积高度H2 = (H1 - F + 2P) / S + 1
    • 输出体积宽度W2 = (W1 - F + 2P) / S + 1
    • 输出体积深度D2 = K

3.3.6. 卷积层的零填充

  • 卷积核在提取特征映射时的动作称之为padding(零填充),由于移动步长不一定能整出整张图的像素宽度。其中有两种方式,SAME和VALID
    = SAME:越过边缘取样,取样的面积和输入图像的像素宽度一致
    • VALID:不越过边缘取样,取样的面积小于输入人的图像的像素宽度

4. API介绍

4.1. 卷积网络API

  • tf.nn.conv2d(input, filter, strides=, padding=, name=None) 计算给定4-D input和filter张量的2维卷积
    • input:给定的输入张量,具有[batch,heigth,width,channel],类型为float32,64
    • filter:指定过滤器的大小,[filter_height, filter_width, in_channels, out_channels]
    • strides:strides = [1, stride, stride, 1],步长
    • padding:“SAME”, “VALID”,使用的填充算法的类型,使用“SAME”。其中”VALID”表示滑动超出部分舍弃,“SAME”表示填充,使得变化后height,width一样大

4.2. 激活函数

  • tf.nn.relu(features, name=None)
    • features:卷积后加上偏置的结果
    • return:结果

4.3. 池化

  • tf.nn.max_pool(value, ksize=, strides=, padding=,name=None)输入上执行最大池数

    • value:4-D Tensor形状[batch, height, width, channels]
    • ksize:池化窗口大小,[1, ksize, ksize, 1]
    • strides:步长大小,[1,strides,strides,1]
    • padding:“SAME”, “VALID”,使用的填充算法的类型,使用“SAME”
  • 注意: 池化层零填充如果用的是SAME, 大小可和输入不一定一样

5. 面试题

  • 输入图片大小为200x200 一次经过一次卷积(过滤器大小kernel size 5x5, 零填充padding 1, 步长 stride 2), pooling(kernel size 3x3, padding 0 stride 1), 又一层卷积(kernel size 3x3, padding 1, stride 1)之后, 输出特征图大小为:C
    • A. 95
    • B. 96
    • C. 97
    • D. 98
    • E. 99
    • F. 100

6. Mnist手写数字图片识别卷积神经案例

6.1. 数据样本

  • 特征值:[None, 784]
  • 目标值:[None, 10] 10个类别

6.2. 卷积神经网络

  • 一层卷积

    • 卷积: 32个filter, 5*5, strides=1, padding=“SAME” 偏置bias=32

      • 输入:[None, 28, 28, 1]
      • 输出:[None, 28, 28, 32]
    • 激活:[None, 28, 28, 32]

    • 池化: 2*2, strides=2, padding=“SAME”

      • 输入:[None, 28, 28, 32]
      • 输出:[None, 14, 14, 32]
  • 二层卷积

    • 卷积: 64个filter, 5532(, 也就是输入通道,影响卷积时,过滤器的设置), strides=1, padding=“SAME” 偏置bias=64

      • 输入:[None, 14, 14, 32]
      • 输出:[None, 14, 14, 64]
    • 激活:[None, 14, 14, 64]

    • 池化: 2*2, strides=2, padding=“SAME”

      • 输入:[None, 14, 14, 64]
      • 输出:[None, 7, 7, 64]
  • 全连接层FC

    • 输入:[None, 7764] [7764, 10] 偏置bias=10
    • 输出:[None, 10]

6.3. 代码实现

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data 


def conv_fc():
    """ 卷积神经网络
    """
    # 获取真实的数据
    mnist = input_data.read_data_sets("./mnist_data/input/", one_hot=True)
    # 定义模型, 得出输出
    x, y_true, y_predict = model()
    # 进行交叉熵损失计算
    # 3. 求出所有样本的损失,然后求平均值
    with tf.variable_scope("soft_cross"):
        # 求平均交叉熵损失
        loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_true, logits=y_predict))
    
    # 4. 梯度下降,求出损失
    with tf.variable_scope("optimizer"):
        train_op = tf.train.GradientDescentOptimizer(0.0001).minimize(loss)
        
    # 5. 计算准确率
    with tf.variable_scope("acc"):
        equal_list = tf.equal(tf.argmax(y_true, 1), tf.argmax(y_predict, 1))
        # equal_list None个样本[1,0,1,0,1,1........]
        accuracy = tf.reduce_mean(tf.cast(equal_list, tf.float32))
    
    # 定义一个初始化变量的op
    init_op = tf.global_variables_initializer()
    # 开启会话
    with tf.Session() as sess:
        sess.run(init_op)
        
        # 循环去训练
        for i in range(1000):
            # 获得真实存在的特征值和目标值
            mnist_x, mnist_y = mnist.train.next_batch(50)
            # 运行train_op训练
            sess.run(train_op, feed_dict={x: mnist_x, y_true: mnist_y})

            # 注意巡行的时候,要始终跟上feed_dict
            print("训练第{}步, 准确率为:{}".format(i, sess.run(accuracy, feed_dict={x: mnist_x, y_true: mnist_y})))
    

def weight_variables(shape):
    """定义一个初始化权重的函数
    """
    w = tf.Variable(tf.random_normal(shape=shape, mean=0.0, stddev=1.0))
    return w


def bias_variables(shape):
    """定义一个初始化偏置的函数
    """
    b = tf.Variable(tf.constant(0.0, shape=shape))
    return b


def model():
    """模型
    """
    # 1. 建立数据的占位符 x[None, 784]  y_true[None, 10]
    with tf.variable_scope("data"):
        x = tf.placeholder(tf.float32, [None, 784])
        y_true = tf.placeholder(tf.int32, [None, 10])
        
    # 2. 一卷积层 卷积:5*5*1, 32个, strides=1  激活:tf.nn.relu  池化
    with tf.variable_scope("conv1"):
        # 随机初始化权重[5,5,1,32], 偏置[32]
        w_conv1 = weight_variables([5,5,1,32])
        b_conv1 = bias_variables([32])
        
        # 对形状进行改变[None, 784], [None, 28, 28,1]
        x_reshape = tf.reshape(x, [-1, 28, 28, 1])
        
        # [None, 28,28, 1] -----> [None, 28, 28, 32]
        x_relu1 = tf.nn.relu(tf.nn.conv2d(x_reshape, w_conv1, strides=[1,1,1,1], padding="SAME") + b_conv1)
        
        # 池化 2*2 , strides=2 [None, 28, 28, 32] -----> [None, 14, 14, 32]
        x_pool1 = tf.nn.max_pool(x_relu1, ksize=[1,2,2,1], strides=[1,2,2,1], padding="SAME")
    # 3. 二卷积层: 5*5*32, 64个filter, strides=1 激活 tf.nn.relu 池化
    with tf.variable_scope("conv2"):
        # 随机初始化权重[5,5,32,64], 偏置[64]
        w_conv2 = weight_variables([5,5,32,64])
        b_conv2 = bias_variables([64])
        
        # 卷积,激活,池化计算
        # [None, 14,14,32] -----> [None, 14, 14, 64]
        x_relu2 = tf.nn.relu(tf.nn.conv2d(x_pool1, w_conv2, strides=[1,1,1,1], padding="SAME") + b_conv2)
        
        # 池化 2*2, strides=2, [None, 14,14,64] -----> [None, 7, 7, 64]
        x_pool2 = tf.nn.max_pool(x_relu2, ksize=[1,2,2,1], strides=[1,2,2,1], padding="SAME")
    # 4. 全连接层[None, 7, 7, 64] ---> [None, 7*7*64] * [7*7*64, 10] + [10] == [None, 10]
    with tf.variable_scope("fc_connect"):
        # 随机初始化权重[7*7*64,10], 偏置[10]
        w_fc = weight_variables([7*7*64, 10])
        b_fc = bias_variables([10])
    
        # 修改形状 [None, 7, 7, 64] -----> [None, 7*7*64]
        x_fc_reshape = tf.reshape(x_pool2, [-1, 7*7*64])
    
        # 进行矩阵运算得出每个样本的10个结果
        y_predict = tf.matmul(x_fc_reshape, w_fc) + b_fc
        
    return x, y_true, y_predict


if __name__ == "__main__":
    conv_fc()

#7. GoogleNet

  • from tensorflow.contrib.slim.python.slim.nets.inception_v3 import inception_v3_base

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值