深度学习图像处理目标检测图像分割计算机视觉 05--深度学习基础

本文详细介绍了卷积神经网络的基础构成,包括卷积层、池化层和全连接层的作用,以及误差反向传播的计算过程。通过代码实现展示了CNN在MNIST数据集上的应用,并引用了一篇关于深度学习在医疗图像分类中的应用论文,该论文提出了基于多尺度梯度GAN的脑肿瘤分类方法,取得了98.57%的高准确率。

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

摘要

本文主要介绍卷积神经网络的基本构成,以及每一部分的基本作用,并且给出误差反向传播的具体计算过程以帮助理解整个网络架构。文章也给出具体的代码实现过程,分步分析具体的作用以及运行结果,也给出MNIST手写数据集的训练和测试过程。
This article mainly introduces the basic structure of convolutional neural network, and the basic function of each part, and gives the specific calculation process of error back propagation to help understand the entire network architecture. The article also gives the specific code implementation process, step-by-step analysis of specific functions and running results, and also gives the training and testing process of the MNIST handwritten data set.

一、卷积层

卷积神经网络主要由三个组件构成,卷积层,池化层和全连接层。卷积层进行特征提取,池化层特征融合,并且两个层都可以进行降维,
在这里插入图片描述
卷积层主要是靠滤波器也就是卷积核对图像做卷积来提取局部特征,但是他的权重参数是需要学习的,每一次卷积之后的通道数是由卷积核的数量来确定的。
在这里插入图片描述
关于卷积层的卷积核,有一些超参数需要确认,核的具体数量,尺寸大小,步长,和零填充的行数。
在这里插入图片描述
比如下图是一个小例子,零填充1行,核尺寸为3,步长为2,核数量为5.
在这里插入图片描述
值得注意的是,卷积核的通道数要与输入图片的通道数保持一致,卷积核的数量可以根据要求自定义,但是一旦确认之后,意味着卷积之后的图像的通道数也确定了,就是卷积核的个数。如图所示:
一个32x32x3的原始图片,卷积核的尺寸为5x5x3,定义卷积核的数量为6,在不进行零填充的情况下,输出的特征为28x28x6。
在这里插入图片描述
卷积神经网络的卷积层的激活函数为ReLU,小于0的数,全部为零,其余的取本身。
在这里插入图片描述
ReLU激活函数的好处是可以明显减轻梯度消失的问题。
在这里插入图片描述
在CNN中,激活函数主要用于卷积层每一次提取特征之后进行一次激活函数的运算,它并不会改变特征的尺度,
在这里插入图片描述

二、池化层

池化层的主要作用是特征融合和降维
在这里插入图片描述

三、全连接层

在这里插入图片描述

四、误差反向传播

当在计算误差反向传播时,要考虑到卷积层和池化层的先后顺序,

4.1 池化层的误差反向传播

已知池化层的残差,求解上一层卷积层的残差
在这里插入图片描述
因为池化层有两种池化方式,先考虑平均池化:

在这里插入图片描述

再考虑最大池化方式:
在这里插入图片描述

4.2 卷积层的误差反向传播

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

那么卷积层的误差反向传播具体计算过程如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

一个简单的小例子,具体的计算一下误差反向传播
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

五、代码实现

首先导入一些需要用到的模块

%matplotlib inline
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt

输入一张3x3的灰度图

sess = tf.InteractiveSession()
image = np.array([[[[1],[2],[3]],
                   [[4],[5],[6]], 
                   [[7],[8],[9]]]], dtype=np.float32)
print(image.shape)
plt.imshow(image.reshape(3,3), cmap='Greys')

在这里插入图片描述

用一个2x2的卷积核进行卷积操作,但是原始图片不进行补零操作

print("image.shape", image.shape)
weight = tf.constant([[[[1.]],[[1.]]],
                      [[[1.]],[[1.]]]])
print("weight.shape", weight.shape)
conv2d = tf.nn.conv2d(image, weight, strides=[1, 1, 1, 1], padding='VALID')
conv2d_img = conv2d.eval()
print("conv2d_img.shape", conv2d_img.shape)
conv2d_img = np.swapaxes(conv2d_img, 0, 3)
for i, one_img in enumerate(conv2d_img):
    print(one_img.reshape(2,2))
    plt.subplot(1,2,i+1), plt.imshow(one_img.reshape(2,2), cmap='gray')

在这里插入图片描述

在这里插入图片描述

进行补零操作的情况

# print("imag:\n", image)
print("image.shape", image.shape)

weight = tf.constant([[[[1.]],[[1.]]],
                      [[[1.]],[[1.]]]])
print("weight.shape", weight.shape)
conv2d = tf.nn.conv2d(image, weight, strides=[1, 1, 1, 1], padding='SAME')
conv2d_img = conv2d.eval()
print("conv2d_img.shape", conv2d_img.shape)
conv2d_img = np.swapaxes(conv2d_img, 0, 3)
for i, one_img in enumerate(conv2d_img):
    print(one_img.reshape(3,3))
    plt.subplot(1,2,i+1), plt.imshow(one_img.reshape(3,3), cmap='gray')

在这里插入图片描述

在这里插入图片描述

当卷积核是三通道时,结果会输出三个结果

print("image.shape", image.shape)

weight = tf.constant([[[[1.,10.,-1.]],[[1.,10.,-1.]]],
                      [[[1.,10.,-1.]],[[1.,10.,-1.]]]])
print("weight.shape", weight.shape)
conv2d = tf.nn.conv2d(image, weight, strides=[1, 1, 1, 1], padding='SAME')
conv2d_img = conv2d.eval()
print("conv2d_img.shape", conv2d_img.shape)
conv2d_img = np.swapaxes(conv2d_img, 0, 3)
for i, one_img in enumerate(conv2d_img):
    print(one_img.reshape(3,3))
    plt.subplot(1,3,i+1), plt.imshow(one_img.reshape(3,3), cmap='gray')

在这里插入图片描述

最大池化:当我们输入的是([[[[4],[3]],[[2],[1]]]])输出结果为4

image = np.array([[[[4],[3]],
                    [[2],[1]]]], dtype=np.float32)
pool = tf.nn.max_pool(image, ksize=[1, 2, 2, 1],
                    strides=[1, 1, 1, 1], padding='VALID')
print(pool.shape)
print(pool.eval())

在这里插入图片描述

当我们在做池化并且进行零填充时,同样的输入,输出的结果为4,3,2,1

image = np.array([[[[4],[3]],
                    [[2],[1]]]], dtype=np.float32)
pool = tf.nn.max_pool(image, ksize=[1, 2, 2, 1],
                    strides=[1, 1, 1, 1], padding='SAME')
print(pool.shape)
print(pool.eval())

在这里插入图片描述

当我们训练著名的MNIST手写数字集时,引入数据集

from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

数据集中每一个图片都是28x28的灰度图

img = mnist.train.images[0].reshape(28,28)
plt.imshow(img, cmap='gray')

在这里插入图片描述
对上图进行零填充然后做卷积操作进行特征提取

sess = tf.InteractiveSession()

img = img.reshape(-1,28,28,1)
W1 = tf.Variable(tf.random_normal([3, 3, 1, 5], stddev=0.01))
conv2d = tf.nn.conv2d(img, W1, strides=[1, 2, 2, 1], padding='SAME')
print(conv2d)
sess.run(tf.global_variables_initializer())
conv2d_img = conv2d.eval()
conv2d_img = np.swapaxes(conv2d_img, 0, 3)
for i, one_img in enumerate(conv2d_img):
    plt.subplot(1,5,i+1), plt.imshow(one_img.reshape(14,14), cmap='gray')

在这里插入图片描述
进行最大池化操作

pool = tf.nn.max_pool(conv2d, ksize=[1, 2, 2, 1], strides=[
                        1, 2, 2, 1], padding='SAME')
print(pool)
sess.run(tf.global_variables_initializer())
pool_img = pool.eval()
pool_img = np.swapaxes(pool_img, 0, 3)
for i, one_img in enumerate(pool_img):
    plt.subplot(1,5,i+1), plt.imshow(one_img.reshape(7, 7), cmap='gray')

在这里插入图片描述
介绍一种tensorflow中对MNIST手写数据集进行训练和测试的过程:
在这里插入图片描述

More info: http://yann.lecun.com/exdb/mnist/

from __future__ import division, print_function, absolute_import

# Import MNIST data,MNIST数据集导入
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data", one_hot=False)

import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np
# Training Parameters,超参数
learning_rate = 0.001 #学习率
num_steps = 2000 # 训练步数
batch_size = 128 # 训练数据批的大小

# Network Parameters,网络参数
num_input = 784 # MNIST数据输入 (img shape: 28*28)
num_classes = 10 # MNIST所有类别 (0-9 digits)
dropout = 0.75 # Dropout, probability to keep units = (1-p),保留神经元相应的概率为(1-p)=(1-0.75)=0.25

# Create the neural network,创建深度神经网络
def conv_net(x_dict, n_classes, dropout, reuse, is_training):
    
    # Define a scope for reusing the variables,确定命名空间
    with tf.variable_scope('ConvNet', reuse=reuse):
        # TF Estimator类型的输入为像素
        x = x_dict['images']

        # MNIST数据输入格式为一位向量,包含784个特征 (28*28像素)
        # 用reshape函数改变形状以匹配图像的尺寸 [高 x 宽 x 通道数]
        # 输入张量的尺度为四维: [(每一)批数据的数目, 高,宽,通道数]
        x = tf.reshape(x, shape=[-1, 28, 28, 1])

        # 卷积层,32个卷积核,尺寸为5x5
        conv1 = tf.layers.conv2d(x, 32, 5, activation=tf.nn.relu)
        # 最大池化层,步长为2,无需学习任何参量
        conv1 = tf.layers.max_pooling2d(conv1, 2, 2)

        # 卷积层,64个卷积核,尺寸为3x3
        conv2 = tf.layers.conv2d(conv1, 64, 3, activation=tf.nn.relu)
        # 最大池化层,步长为2,无需学习任何参量
        conv2 = tf.layers.max_pooling2d(conv2, 2, 2)

        # 展开特征为一维向量,以输入全连接层
        fc1 = tf.contrib.layers.flatten(conv2)

        # 全连接层
        fc1 = tf.layers.dense(fc1, 1024)
        # 应用Dropout (训练时打开,测试时关闭)
        fc1 = tf.layers.dropout(fc1, rate=dropout, training=is_training)

        # 输出层,预测类别
        out = tf.layers.dense(fc1, n_classes)

    return out

# 确定模型功能 (参照TF Estimator模版)
def model_fn(features, labels, mode):
    
    # 构建神经网络
    # 因为dropout在训练与测试时的特性不一,我们此处为训练和测试过程创建两个独立但共享权值的计算图
    logits_train = conv_net(features, num_classes, dropout, reuse=False, is_training=True)
    logits_test = conv_net(features, num_classes, dropout, reuse=True, is_training=False)
    
    # 预测
    pred_classes = tf.argmax(logits_test, axis=1)
    pred_probas = tf.nn.softmax(logits_test)
    
    if mode == tf.estimator.ModeKeys.PREDICT:
        return tf.estimator.EstimatorSpec(mode, predictions=pred_classes) 
        
    # 确定误差函数与优化器
    loss_op = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(
        logits=logits_train, labels=tf.cast(labels, dtype=tf.int32)))
    optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate)
    train_op = optimizer.minimize(loss_op, global_step=tf.train.get_global_step())
    
    # 评估模型精确度
    acc_op = tf.metrics.accuracy(labels=labels, predictions=pred_classes)
    
    # TF Estimators需要返回EstimatorSpec
    estim_specs = tf.estimator.EstimatorSpec(
      mode=mode,
      predictions=pred_classes,
      loss=loss_op,
      train_op=train_op,
      eval_metric_ops={'accuracy': acc_op})

    return estim_specs

# 构建Estimator
model = tf.estimator.Estimator(model_fn)

# 确定训练输入函数
input_fn = tf.estimator.inputs.numpy_input_fn(
    x={'images': mnist.train.images}, y=mnist.train.labels,
    batch_size=batch_size, num_epochs=None, shuffle=True)
# 开始训练模型
model.train(input_fn, steps=num_steps)
# 评判模型
# 确定评判用输入函数
input_fn = tf.estimator.inputs.numpy_input_fn(
    x={'images': mnist.test.images}, y=mnist.test.labels,
    batch_size=batch_size, shuffle=False)
model.evaluate(input_fn)

# 预测单个图像
n_images = 6
# 从数据集得到测试图像
test_images = mnist.test.images[:n_images]
# 准备输入数据
input_fn = tf.estimator.inputs.numpy_input_fn(
    x={'images': test_images}, shuffle=False)
# 用训练好的模型预测图片类别
preds = list(model.predict(input_fn))

# 可视化显示
for i in range(n_images):
    plt.imshow(np.reshape(test_images[i], [28, 28]), cmap='gray')
    plt.show()
    print("Model prediction:", preds[i])

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

六、论文

6.1 摘要

在医疗行业中,疾病误诊是公认的最常见和最有害的医疗错误,它可能以生命为代价。放射科医生需要大量的时间来手动注释和分割图像。近年来,深度学习在计算机视觉领域发挥着至关重要的作用。它在医疗行业的一个关键用途是最小化误诊和标注和分割图像所花费的时间。本文介绍了一种新的基于深度学习的MRI图像脑肿瘤分类方法。在生成对抗网络(generative adversarial network, GAN)中预先训练深度神经网络作为鉴别器,利用多尺度梯度GAN (multiscale gradient GAN, MSGGAN)进行辅助分类,提取特征并对图像进行分类。在鉴别器中,一个全连接块作为辅助分类器,另一个全连接块作为对抗器。完全连接的辅助块层被微调以区分肿瘤类型。提出的方法在两个公开可用的MRI数据集作为一个整体进行测试,这些数据集包括四种类型的脑肿瘤(胶质瘤、脑膜瘤、垂体和无肿瘤)。该方法的准确度为98.57%,优于现有的方法。此外,当医学图像的可用性有限时,我们的方法似乎是一种有用的技术。

6.2 论文结构

6.2.1 简介

放射科医生使用两种方法对脑瘤进行分类。一种方法是确定给定的脑MR图像是正常的还是异常的,另一种方法是将异常的脑MR图像分类为不同的肿瘤类型。对于大量的MRI数据,手工进行脑肿瘤分类效率低,耗时长。为了解决这个问题,放射科医生可以使用自动分类来识别最小介入的脑肿瘤MR图像。
各种医学成像技术中,磁共振成像MRI是应用最广泛的技术。在MRI采集过程中,每次扫描提供大约150片(可能因设备不同而不同)的2D图像,以在没有电离辐射[3]的情况下,用高软组织对比度表示3D脑体积

6.2.2 模型结构

该体系结构基于MSG-GAN(多尺度梯度)体系[8],并结合ACGAN论文[6]启发的辅助分类训练。我们的氮化镓架构和其他氮化镓架构一样,由两大神经网络组成:生成器和鉴别器。
生成器结构
待生成图像的潜在向量和标签是生成器所需的输入。将潜向量与标签相乘并发送到嵌入层,在训练过程中,当潜向量与它相乘(已标记的潜向量)时,嵌入层从潜向量学习标签表示。然后将嵌入层的输出传输到Conv 2d转置层,该层执行“反卷积”并从潜在向量生成4x4图像。然后根据选择的深度,提高图像分辨率(4x4->8x8->16x16->等),将图像传输到N个上采样和卷积块,生成图像。最后,将生成指定类的高分辨率图像。
在这里插入图片描述
鉴别器结构
发生器的输出,它是馈入鉴别器的图像。使用卷积块和平均池化,图像每一步向下采样2。在那之后,它通过一个小批量标准偏差运行。在这一步中,计算激活图中每个特征的标准偏差,然后在小批处理中取平均值。这种新的激活产生了地图。这些新的激活图被添加到鉴别器网络的末端。Mini-batch standard deviation的输出被输入到一个卷积块中,然后该卷积块被并行地(即分别地)转移到两个全连接块中。其中一个全连接块作为辅助分类器,决定输入图像属于哪一类;另一个全连接块作为对抗分类器,决定图像是真还是假
在这里插入图片描述
由于鉴别器已经学习了大脑和脑肿瘤的必要特征,网络的各层可以用于特征提取/迁移学习。在我们的微调过程中,我们冻结了所有的特征提取层(因为它们有GAN预先训练的权值,擅长特征提取),只使用训练数据和验证数据对辅助块的全连接层进行训练/微调。辅助块的初始全连接层由单个线性层组成,输出代表类的4个神经元。为了进行微调,在辅助块中的单一线性层之前,我们添加了另一个512单位的线性层。用亚当作为学习率0.001或4e-5的优化器,和交叉熵损失函数。

6.3 总结

在本文中,我们提出了一种利用GAN作为预训练模型从MR图像中分类脑肿瘤的新方法。我们使用公开可用的脑MRI数据集评估了它的性能。我们的结果表明,提出的前训练方法显著提高了整体效率。此外,当数据的可用性有限时,这种技术也很有用,可以应用于各种图像分类任务。我们将我们的结果与之前使用相同数据集的工作进行了比较。该方法在脑肿瘤MRI图像分类中准确率最高,为98.57%。
作为未来的工作,我们将改进我们的体系结构,以生成更真实的高分辨率MRI图像,这将有助于增加数据集的大小和解决数据集不平衡的问题。此外,我们将在未来测试我们的方法的效率以及对其他医学图像的改进。

总结

本文主要介绍了卷积神经网络的详细结构,以及每一部分的工作原理以及具体的计算过程,本文也给出具体的实现过程。卷积层主要通过卷积操作做特征提取,当卷积核的步长大于2时,也有降维的作用。池化层做特征融合和降维,有两种池化方式,平均池化和最大池化,平均池化是将残差等值分布,但是在反向传播时残差总和是不变的,所以要除以池化区域的大小,使其总和保持一致。最大池化需要记录在前向传播时池化区域的最大值的位置,在进行还原,其余部位补零即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值