深度学习-CNN模型的简单实现

利用Tensorflow实现一个简单的CNN模型

CONV2D→RELU→MAXPOOL→CONV2D→RELU→MAXPOOL→FULLCONNECTED

1.导入模块

import math
import numpy as np
import h5py
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import tensorflow as tf
from tensorflow.python.framework import ops
import cnn_utils

2.创建占位符

def create_placeholders(n_H0,n_W0,n_C0,n_y):
  '''
    为session创建占位符

    参数:
        n_H0 - 实数,输入图像的高度
        n_W0 - 实数,输入图像的宽度
        n_C0 - 实数,输入的通道数
        n_y  - 实数,分类数

    输出:
        X - 输入数据的占位符,维度为[None, n_H0, n_W0, n_C0],类型为"float"
        Y - 输入数据的标签的占位符,维度为[None, n_y],维度为"float"
    '''
  X=tf.placeholder(tf.float32,[None,n_H0,n_W0,n_C0])
  Y=tf.placeholder(tf.float32,[None, n_y])

  return X,Y

3.初始化参数

现在我们将使用tf.contrib.layers.xavier_initializer(seed = 0) 来初始化权值/过滤器W1、W2。在这里,我们不需要考虑偏置,因为TensorFlow会考虑到的。需要注意的是我们只需要初始化为2D卷积函数,全连接层TensorFlow会自动初始化的。

初始化函数:tf.contrib.layers.xavier_initializer(seed = 0) 
def initialize_parameters():
    """
    初始化权值矩阵,这里我们把权值矩阵硬编码:
    W1 : [4, 4, 3, 8]
    [卷积核高度,卷积核宽度,图像通道数,卷积核个数]
    这一层输出的通道数就是8 也就是下一层输入的通道数
    W2 : [2, 2, 8, 16]

    返回:
        包含了tensor类型的W1、W2的字典
    """
    tf.set_random_seed(1)

    W1 = tf.get_variable("W1",[4,4,3,8],initializer=tf.contrib.layers.xavier_initializer(seed=0))#这里优点疑问?
    W2 = tf.get_variable("W2",[2,2,8,16],initializer=tf.contrib.layers.xavier_initializer(seed=0))

    parameters = {"W1": W1,
                  "W2": W2}

    return parameters

测试代码:

tf.reset_default_graph()
with tf.Session() as sess_test:
    parameters = initialize_parameters()
    init = tf.global_variables_initializer()
    sess_test.run(init)
    print("W1 = " + str(parameters["W1"].eval()[1,1,1]))
    print("W2 = " + str(parameters["W2"].eval()[1,1,1]))

    sess_test.close()

总结:

1.输入图像的通道数必须与卷积核通道数相等
2.如果输入是6x6x3 卷积核是3x3x3 那么输出就是一个4x4x1
3.输入:nxnxc 卷积核 fxfxc 输出:(n-f+1)x (n-f+1) x c2(卷积核个数也是下一层的通道数目)
4.上面的情况是没有padding的 如过padding会有变化
5.如果有padding :则变为 (n+2p-f/s)+1  x (n+2p-f/s)+1

4.前向传播

卷积操作:

tf.nn.conv2d(X,W1,strides=[1,s,s,1],padding='SAME')

Input: 输入的input必须为一个4d tensor,而且每个input的格式必须为float32 或者float64. Input=[batchsize,image_w,image_h,in_channels],也就是[每一次训练的batch数,图片的长,图片的宽,图片的通道数]。

Filter: 和input类似。样式为:[ 卷积核的长,卷积核的宽,输入的通道,输出的通道]

Strides:长度为4的list,且元素类型为int…格式为:[1,x,y,1].表示的是每一维度滑动的的步长。
1-D Tensor of length 4。步长。Shape和input相同,一般batch和channels恒定为1,即[1, height, weight, 1]

Padding: 有"Same",“VALID” 两种选择。SAME:为要对图像进行补零操作,VALID不要对图像进行补零操作。

use_cudnn_on_gpu: 布尔类型,True, False 两种选择。表示是否用GPU训练。

Name:

表示该操作的名字

参考网站:https://www.jianshu.com/p/c72af2ff5393

池化操作:

tf.nn.max_pool(A, ksize = [1,f,f,1], strides = [1,s,s,1], padding = 'SAME')

给定输入X,该函数将会使用大小为(f,f)以及步伐为(s,s)的窗口对其进行滑动取最大值,
你也可以看一下文档:https://www.cnblogs.com/smartwhite/p/7819689.html

计算Relu激活函数

tf.nn.relu(Z1)

全连接操作:

tf.contrib.layers.fully_connected(F, num_outputs)
tf.contrib.layers.flatten(P):

给定一个输入P,此函数将会把每个样本转化成一维的向量,
然后返回一个tensor变量,其维度为(batch_size,k).

使用tf.contrib.layers.fully_connected(F, num_outputs)的时候,
全连接层会自动初始化权值且在你训练模型的时候它也会一直参与,
所以当我们初始化参数的时候我们不需要专门去初始化它的权值。

我们实现前向传播的时候,我们需要定义一下我们模型的大概样子:

CONV2D→RELU→MAXPOOL→CONV2D→RELU→MAXPOOL→FULLCONNECTED

我们具体实现的时候,我们需要使用以下的步骤和参数:

Conv2d : 步伐:1,填充方式:“SAME”
ReLU
Max pool : 过滤器大小:8x8,步伐:8x8,填充方式:“SAME”
Conv2d : 步伐:1,填充方式:“SAME”
ReLU
Max pool : 过滤器大小:4x4,步伐:4x4,填充方式:“SAME”
一维化上一层的输出
全连接层(FC):使用没有非线性激活函数的全连接层。这里不要调用SoftMax, 这将导致输出层中有6个神经元,然后再传递到softmax。 在TensorFlow中,softmax和cost函数被集中到一个函数中,在计算成本时您将调用不同的函数。

#开始使用tensorflow进行前向传播
def forward_propagation(X,parameters):
    '''
   实现前向传播
    CONV2D -> RELU -> MAXPOOL -> CONV2D -> RELU -> MAXPOOL -> FLATTEN -> FULLYCONNECTED

    参数:
        X - 输入数据的placeholder,维度为(输入节点数量,样本数量)
        parameters - 包含了“W1”和“W2”的python字典。

    返回:
        Z3 - 最后一个LINEAR节点的输出

    '''
    W1=parameters['W1']
    W2=parameters['W2']
    #卷积 步长 1 填充方式 same 中间2个1就是步长
    Z1=tf.nn.conv2d(X,W1,strides=[1,1,1,1],padding="SAME")#一般batch和channels恒定为1 一头一尾
    #relu
    A1=tf.nn.relu(Z1)
    #Max pool: 窗口大小8x8 步长8x8 same
    P1=tf.nn.max_pool(A1,ksize=[1,8,8,1],strides=[1,8,8,1],padding="SAME")
    # 第二次卷积
    Z2=tf.nn.conv2d(P1,W2,strides=[1,1,1,1],padding="SAME")
    #relu
    A2=tf.nn.relu(Z2)
    #最大池化
    P2=tf.nn.max_pool(A2,ksize=[1,4,4,1],strides=[1,4,4,1],padding="SAME")
    #一维化上一层输出
    P=tf.contrib.layers.flatten(P2)
    #全连接层
    Z3=tf.contrib.layers.fully_connected(P,6,activation_fn=None)
    '''
    tf.contrib.layers.fully_connected(F, num_outputs,activation_fn)
    F ---[batch_size,images_pixels],tensornum_outputs 
    --- numbers of outputs,[batch_size,num_outputs]activation_fn ---采用指定的非线性激励函数,默认不是None,如果不需要的话,要赋值None
    '''
    return  Z3

测试代码:

 tf.reset_default_graph()
 np.random.seed(1)

 with tf.Session() as sess_test:
     X,Y = create_placeholders(64,64,3,6)
     parameters = initialize_parameters()
     Z3 = forward_propagation(X,parameters)

     init = tf.global_variables_initializer()
     sess_test.run(init)

     a = sess_test.run(Z3,{X: np.random.randn(2,64,64,3), Y: np.random.randn(2,6)})
     print("Z3 = " + str(a))

     sess_test.close()

5.计算损失

我们要在这里实现计算成本的函数,下面的两个函数是我们要用到的:

tf.nn.softmax_cross_entropy_with_logits(logits = Z3 , lables = Y):

计算softmax的损失函数。这个函数既计算softmax的激活,也计算其损失

tf.reduce_mean:

计算的是平均值,使用它来计算所有样本的损失来得到总成本。

def compute_cost(Z3,Y):
        """
        计算成本
        参数:
            Z3 - 正向传播最后一个LINEAR节点的输出,维度为(6,样本数)。
            Y - 标签向量的placeholder,和Z3的维度相同

        返回:
            cost - 计算后的成本

        """

        cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=Z3, labels=Y))

        return cost

博客设置页面,选择一款你喜欢的代码片高亮样式,下面展示同样高亮的 代码片.

// An highlighted block
var foo = 'bar';

6.构建模型

最后,我们已经实现了我们所有的函数,我们现在就可以实现我们的模型了。

我们之前在课程2就实现过random_mini_batches()这个函数,它返回的是一个mini-batches的列表。

在实现这个模型的时候我们要经历以下步骤:

1.创建占位符
2.初始化参数
3.前向传播
4.计算成本
5.反向传播
6.创建优化器
7.最后,我们将创建一个session来运行模型。

def model(X_train, Y_train, X_test, Y_test, learning_rate=0.009,
         num_epochs=100,minibatch_size=64,print_cost=True,isPlot=True):
    """
    使用TensorFlow实现三层的卷积神经网络
    CONV2D -> RELU -> MAXPOOL -> CONV2D -> RELU -> MAXPOOL -> FLATTEN -> FULLYCONNECTED

    参数:
        X_train - 训练数据,维度为(None, 64, 64, 3)
        Y_train - 训练数据对应的标签,维度为(None, n_y = 6)
        X_test - 测试数据,维度为(None, 64, 64, 3)
        Y_test - 训练数据对应的标签,维度为(None, n_y = 6)
        learning_rate - 学习率
        num_epochs - 遍历整个数据集的次数
        minibatch_size - 每个小批量数据块的大小
        print_cost - 是否打印成本值,每遍历100次整个数据集打印一次
        isPlot - 是否绘制图谱

    返回:
        train_accuracy - 实数,训练集的准确度
        test_accuracy - 实数,测试集的准确度
        parameters - 学习后的参数
    """
    ops.reset_default_graph()  #能够重新运行模型而不覆盖tf变量
    tf.set_random_seed(1)    #确保你的数据和我一样
    seed = 3                 #指定numpy的随机种子
    (m , n_H0, n_W0, n_C0) = X_train.shape
    n_y = Y_train.shape[1]
    costs = []

    #为当前维度创建占位符
    X , Y = create_placeholders(n_H0, n_W0, n_C0, n_y)

    #初始化参数
    parameters = initialize_parameters()

    #前向传播
    Z3 = forward_propagation(X,parameters)

    #计算成本
    cost = compute_cost(Z3,Y)

    #反向传播,由于框架已经实现了反向传播,我们只需要选择一个优化器就行了
    optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)

    #全局初始化所有变量
    init = tf.global_variables_initializer()

    #开始运行
    with tf.Session() as sess:
        #初始化参数
        sess.run(init)
        #开始遍历数据集
        for epoch in range(num_epochs):
            minibatch_cost = 0
            num_minibatches = int(m / minibatch_size) #获取数据块的数量
            seed = seed + 1
            minibatches = cnn_utils.random_mini_batches(X_train,Y_train,minibatch_size,seed)

            #对每个数据块进行处理
            for minibatch in minibatches:
                #选择一个数据块
                (minibatch_X,minibatch_Y) = minibatch
                #最小化这个数据块的成本
                _ , temp_cost = sess.run([optimizer,cost],feed_dict={X:minibatch_X, Y:minibatch_Y})

                #累加数据块的成本值
                minibatch_cost += temp_cost / num_minibatches

            #是否打印成本
            if print_cost:
                #每5代打印一次
                if epoch % 5 == 0:
                    print("当前是第 " + str(epoch) + " 代,成本值为:" + str(minibatch_cost))

            #记录成本
            if epoch % 1 == 0:
                costs.append(minibatch_cost)

        #数据处理完毕,绘制成本曲线
        if isPlot:
            plt.plot(np.squeeze(costs))
            plt.ylabel('cost')
            plt.xlabel('iterations (per tens)')
            plt.title("Learning rate =" + str(learning_rate))
            plt.show()

        #开始预测数据
        ## 计算当前的预测情况
        #predict_op = tf.arg_max(Z3,1)
        #corrent_prediction = tf.equal(predict_op , tf.arg_max(Y,1))

        ##计算准确度
        # accuracy = tf.reduce_mean(tf.cast(corrent_prediction,"float"))
        # print("corrent_prediction accuracy= " + str(accuracy))
        #
        # train_accuracy = accuracy.eval({X: X_train, Y: Y_train})
        # test_accuary = accuracy.eval({X: X_test, Y: Y_test})
        #
        # print("训练集准确度:" + str(train_accuracy))
        # print("测试集准确度:" + str(test_accuary))
        # 计算准确率
        predict_op = tf.argmax(Z3, 1)
        correct_prediction = tf.equal(predict_op, tf.argmax(Y, 1))

        accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))

        train_accuracy = accuracy.eval({X: X_train, Y: Y_train})
        test_accuracy = accuracy.eval({X: X_test, Y: Y_test})
        print("Train Accuracy:", train_accuracy)
        print("Test Accuracy:", test_accuracy)

        return (train_accuracy,test_accuracy,parameters)

_, _, parameters = model(X_train, Y_train, X_test, Y_test,num_epochs=10)
  • 1
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
CNN(卷积神经网络)是一种深度学习算法,用于图像识别、目标检测和模式识别等任务。MATLAB是一种编程语言和环境,可以用于实现CNN。 要在MATLAB中实现CNN,首先需要安装并使用Deep Learning Toolbox。该工具箱提供了一些预先训练的CNN模型,如AlexNet和VGG-16,也可以创建自定义的CNN模型。 在创建CNN模型之前,需要定义模型的架构。这包括选择卷积层、池化层、全连接层和激活函数等。可以使用MATLAB中提供的函数,如convolution2dLayer和fullyConnectedLayer,来定义各个层的参数和参数。 然后,可以使用训练数据来训练CNN模型。使用函数如trainNetwork来加载图像数据和标签,并通过反向传播算法来优化模型的权重和偏差。训练的过程可以设置参数,如学习率和迭代次数,以获得更好的性能。 在训练完成后,可以使用经过训练的CNN模型来对新的图像进行预测。可以使用函数如classify来对图像进行分类,或者使用analyzeNetwork来查看CNN模型的详细结构。 在实现CNN时,还可以使用MATLAB中的一些辅助函数和工具来进行数据增强、模型调优和结果分析等。此外,MATLAB还提供了各种教程、示例和文档,可以帮助理解CNN的工作原理和实现细节。 总之,通过MATLAB的Deep Learning Toolbox,我们可以在相对简单的步骤中实现CNN,并用于图像识别和其他相关应用。它提供了丰富的功能和工具,可以帮助开发人员更轻松地构建和优化CNN模型

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值