浅易理解:卷积神经网络(CNN)

浅易理解卷积神经网络流程

本文的目录:

  1 什么卷积神经网络

  2 输入层

  3 卷积层

  4 池化层

  5 全连接层

传统的多层神经网络只有  输入层、隐藏层、输出层

卷积神经网络(CNN):

在多层神经网络的基础上,加入了更加有效的特征学习部分,具体就是在全连接层前加入了卷积层与池化层,卷积神经网络出现,使得神经网络层数得以加深,“深度学习”由此而来。

还可以用卷积层、激活层、池化层(又叫下采样层)、全连接层表示。

1 什么是卷积神经网络

1.1卷积神经网络(Convolutional Neural Networks, CNN)

        是一种前馈神经网络,它的人工神经元可以响应一部分覆盖范围内的周围单元,对于大型图像处理有出色表现。 它包括卷积层(convolutional layer)和池化层(pooling layer)。

1.2卷积神经网络整个运算过程:
  • 输入层:输入图像等信息
  • 卷积层:用来提取图像的底层特征
  • 池化层:防止过拟合,将数据维度减小
  • 全连接层:汇总卷积层和池化层得到的图像的底层特征和信息
  • 输出层:根据全连接层的信息得到概率最大的结果

  其中最重要的一层就是卷积层,这也是卷积神经网络名称的由来

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

1.3什么是卷积

        对图像(不同的数据窗口数据)和滤波矩阵(一组固定的权重:因为每个神经元的多个权重固定,所以又可以看做一个恒定的滤波器filter)做内积(逐个元素相乘再求和)的操作就是所谓的『卷积』操作,也是卷积神经网络的名字来源。

        非严格意义上来讲,下图中红框框起来的部分便可以理解为一个滤波器,即带着一组固定权重的神经元。多个滤波器叠加便成了卷积层。

    

  基本wx + b的形式,其中

  • 表示输入向量
  • 为权重,几个输入则意味着有几个权重,即每个输入都被赋予一个权重
  • b为偏置bias
  • g(z) 为激活函数
  • a 为输出

  

  如果只是上面这样一说,估计以前没接触过的十有八九又必定迷糊了。事实上,上述简单模型可以追溯到20世纪50/60年代的感知器,可以把感知器理解为一个根据不同因素、以及各个因素的重要性程度而做决策的模型。

    举个例子,这周末北京有一草莓音乐节,那去不去呢?决定你是否去有二个因素,这二个因素可以对应二个输入,分别用x1、x2表示。此外,这二个因素对做决策的影响程度不一样,各自的影响程度用权重w1、w2表示。一般来说,音乐节的演唱嘉宾会非常影响你去不去,唱得好的前提下 即便没人陪同都可忍受,但如果唱得不好还不如你上台唱呢。所以,我们可以如下表示:

:是否有喜欢的演唱嘉宾。 = 1 你喜欢这些嘉宾, = 0 你不喜欢这些嘉宾。嘉宾因素的权重 = 7
:是否有人陪你同去。 = 1 有人陪你同去, = 0 没人陪你同去。是否有人陪同的权重 = 3。
    这样,咱们的决策模型便建立起来了:g(z) = g( * + * + b ),g表示激活函数,这里的b可以理解成 为更好达到目标而做调整的偏置项。

    一开始为了简单,人们把激活函数定义成一个线性函数,即对于结果做一个线性变化,比如一个简单的线性激活函数是g(z) = z,输出都是输入的线性变换。后来实际应用中发现,线性激活函数太过局限,于是人们引入了非线性激活函数。

+++++++++++++++++++++++++++++++++++++++++++++++++++++

  具体的例子。比如下图中,图中左边部分是原始输入数据,图中中间部分是滤波器filter,图中右边是输出的新的二维数据。

即上图中的输出结果1具体是怎么计算得到的呢?其实,类似wx + b,w对应滤波器Filter w0,x对应不同的数据窗口,b对应Bias b0,相当于滤波器Filter w0与一个个数据窗口相乘再求和后,最后加上Bias b0得到输出结果1:

可以看到:

两个神经元,即depth=2,意味着有两个滤波器。
数据窗口每次移动两个步长取3*3的局部数据,即stride=2。
zero-padding=1。
    然后分别以两个滤波器filter为轴滑动数组进行卷积计算,得到两组不同的结果。

    如果初看上图,可能不一定能立马理解啥意思,但结合上文的内容后,理解这个动图已经不是很困难的事情:

左边是输入(7*7*3中,7*7代表图像的像素/长宽,3代表R、G、B 三个颜色通道)
中间部分是两个不同的滤波器Filter w0、Filter w1
最右边则是两个不同的输出
    随着左边数据窗口的平移滑动,滤波器Filter w0 / Filter w1对不同的局部数据进行卷积计算。

    值得一提的是:左边数据在变化,每次滤波器都是针对某一局部的数据窗口进行卷积,这就是所谓的CNN中的局部感知机制。

打个比方,滤波器就像一双眼睛,人类视角有限,一眼望去,只能看到这世界的局部。如果一眼就看到全世界,你会累死,而且一下子接受全世界所有信息,你大脑接收不过来。当然,即便是看局部,针对局部里的信息人类双眼也是有偏重、偏好的。比如看美女,对脸、胸、腿是重点关注,所以这3个输入的权重相对较大。
与此同时,数据窗口滑动,导致输入在变化,但中间滤波器Filter w0的权重(即每个神经元连接数据窗口的权重)是固定不变的,这个权重不变即所谓的CNN中的参数(权重)共享机制。

再打个比方,某人环游全世界,所看到的信息在变,但采集信息的双眼不变。btw,不同人的双眼 看同一个局部信息 所感受到的不同,即一千个读者有一千个哈姆雷特,所以不同的滤波器 就像不同的双眼,不同的人有着不同的反馈结果。
        看到上面这个动态图的时候,计算过程是“相乘后相加”,但到底具体是个怎么相乘后相加的计算过程 则无法一眼看出,网上也没有一目了然的计算过程。本文来细究下。

计算过程是“相乘后相加”

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

1.4 人工神经网络
1.4.1 神经元

在人工智能领域中,人工神经元是对生物神经元进行模拟的概念模型,它是构建人工神经网络的基本单元。人工神经元的设计意图是模仿生物大脑中神经元处理信息的方式,即接收输入信号、对信号进行加权处理并产生输出响应的能力。

 将下图的这种单个神经元:

组织在一起,便形成了神经网络。下图便是一个三层神经网络结构

        上图中最左边的原始输入信息称之为输入层,最右边的神经元称之为输出层(上图中输出层只有一个神经元),中间的叫隐藏层。

 什么叫输入层、输出层、隐藏层?

输入层(Input layer),众多神经元(Neuron)接受大量非线形输入讯息。输入的讯息称为输入向量。
输出层(Output layer),讯息在神经元链接中传输、分析、权衡,形成输出结果。输出的讯息称为输出向量。
隐藏层(Hidden layer),简称“隐层”,是输入层和输出层之间众多神经元和链接组成的各个层面。如果有多个隐藏层,则意味着多个激活函数。
        同时,每一层都可能由单个或多个神经元组成,每一层的输出将会作为下一层的输入数据。如中间隐藏层来说,隐藏层的3个神经元a1、a2、a3皆各自接受来自多个不同权重的输入(因为有x1、x2、x3这三个输入,所以a1 a2 a3都会接受x1 x2 x3各自分别赋予的权重,即几个输入则几个权重),接着,a1、a2、a3又在自身各自不同权重的影响下 成为的输出层的输入,最终由输出层输出最终结果。

        此外,上文中讲的都是一层隐藏层,但实际中也有多层隐藏层的,即输入层和输出层中间夹着数层隐藏层,层和层之间是全连接的结构,同一层的神经元之间没有连接。

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

1.5 激活函数

        常用的非线性激活函数有sigmoid、tanh、relu等等,前两者sigmoid/tanh比较常见于全连接层,后者relu常见于卷积层。这里先简要介绍下最基础的sigmoid函数(btw,在本博客中SVM那篇文章开头有提过)

        sigmoid的函数表达式如下:

sigmoid函数的数学表达式如下:

其中 x 是该函数的输入变量。sigmoid函数将输入 x 映射到 (0, 1) 区间内,呈现出S形曲线的特点,常用于神经网络作为激活函数,尤其是在二分类问题中,输出可以解释为属于某一类的概率。随着 x 值增加,sigmoid函数的输出值逐渐逼近1;随着 x值减少,输出值逐渐逼近0。

        其中z是一个线性组合,比如z可以等于:b + * + *。通过代入很大的正数或很小的负数到g(z)函数中可知,其结果趋近于0或1。

        因此,sigmoid函数g(z)的图形表示如下( 横轴表示定义域z,纵轴表示值域g(z) ):

        也就是说,sigmoid函数的功能是相当于把一个实数压缩至0到1之间。当z是非常大的正数时,g(z)会趋近于1,而z是非常小的负数时,则g(z)会趋近于0

激活函数:ReLU

Relu函数:f(x)=max(0,x)

采用非饱和线性单元——ReLU代替传统的经常使用的tanh和sigmoid函数,加速了网络训练的速度,降低了计算的复杂度,对各种干扰更加具有鲁棒性,并且在一定程度上避免了梯度消失问题。

优势:

  1. ReLU本质上是分段线性模型,前向计算非常简单,无需指数之类操作;
  2. ReLU的偏导也很简单,反向传播梯度,无需指数或者除法之类操作;
  3. ReLU不容易发生梯度发散问题,Tanh和Logistic激活函数在两端的时候导数容易趋近于零,多级连乘后梯度更加约等于0;
  4. ReLU关闭了右边,从而会使得很多的隐层输出为0,即网络变得稀疏,起到了类似L1的正则化作用,可以在一定程度上缓解过拟合。

缺点:

当然,ReLU也是有缺点的,比如左边全部关了很容易导致某些隐藏节点永无翻身之日,所以后来又出现pReLU、random ReLU等改进,而且ReLU会很容易改变数据的分布,因此ReLU后加Batch Normalization也是常用的改进的方法。

在PyTorch中使用ReLU激活函数的API调用示例:

import torch.nn as nn

# 定义一个模块,包含ReLU激活函数
class MyModel(nn.Module):
    def __init__(self):
        super(MyModel, self).__init__()
        self.linear = nn.Linear(in_features=100, out_features=64)
        self.relu = nn.ReLU()

    def forward(self, x):
        x = self.linear(x)
        x = self.relu(x)  # 应用ReLU激活函数
        return x

在Keras中使用ReLU激活函数的API调用示例:

from tensorflow.keras.layers import Activation

# 创建一个ReLU激活层
relu_activation = Activation('relu')

# 或者在构造卷积层或全连接层时直接指定激活函数
from tensorflow.keras.layers import Dense

dense_layer = Dense(units=64, activation='relu')  # 使用ReLU作为激活函数

在PaddlePaddle中使用ReLU激活函数的API调用示例:

import paddle.nn as nn
2
3# 创建一个ReLU激活层
4relu = nn.ReLU()
5
6# 或者在构造卷积层时直接指定ReLU作为激活函数
7conv2d_layer = nn.Conv2D(in_channels=3, out_channels=64, kernel_size=3, stride=1, padding=1, activation='relu')

为什么输入数据需要归一化(Normalized Data)

归一化后有什么好处呢?原因在于神经网络学习过程本质就是为了学习数据分布,一旦训练数据与测试数据的分布不同,那么网络的泛化能力也大大降低;另外一方面,一旦每批训练数据的分布各不相同(batch 梯度下降),那么网络就要在每次迭代都去学习适应不同的分布,这样将会大大降低网络的训练速度,这也正是为什么我们需要对数据都要做一个归一化预处理的原因。

对于深度网络的训练是一个复杂的过程,只要网络的前面几层发生微小的改变,那么后面几层就会被累积放大下去。一旦网络某一层的输入数据的分布发生改变,那么这一层网络就需要去适应学习这个新的数据分布,所以如果训练过程中,训练数据的分布一直在发生变化,那么将会影响网络的训练速度。

组成图片的最基本单位是像素

分布式计算:

AlexNet使用CUDA加速深度卷积网络的训练,利用GPU强大的并行计算能力,处理神经网络训练时大量的矩阵运算,AlexNet使用两个GTX580的GPU进行训练,单个GTX580只有3GB的显存,限制了可训练网络的最大规模,因此将其分布在两个GPU上,在每个GPU的显存中储存一般的神经元参数。

区域 CNN:R-CNN(2013年)、Fast R-CNN(2015年)、Faster R-CNN(2015年)

生成式对抗网络

生成对抗网络,假设有两个模型,一个生成模型,一个判别模型。判别模型的任务是决定某幅图像是真实的(来自数据库),还是机器生成的,而生成模型的任务则是生成能够骗过判别模型的图像。这两个模型彼此就形成了“对抗”,发展下去最终会达到一个平衡,生成器生成的图像与真实的图像没有区别,判别器无法区分两者。

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//

2 输入层

        输入图像,将其转换为对应的二维矩阵,这个二位矩阵就是由图像每一个像素的像素值大小组成的,一个例子,如下图所示的手写数字“8”的图像,计算机读取以像素值大小组成的二维矩阵存储的图像。​

        上图又称为灰度图像,因为其每一个像素值的范围是0~255(由纯黑色到纯白色),表示其颜色强弱程度。另外还有黑白图像,每个像素值要么是0(表示纯黑色),要么是255(表示纯白色)。我们日常生活中最常见的就是RGB图像,有三个通道,分别是红色、绿色、蓝色。每个通道的每个像素值的范围也是0~255,表示其每个像素的颜色强弱。但是我们日常处理的基本都是灰度图像,因为比较好操作(值范围较小,颜色较单一),有些RGB图像在输入给神经网络之前也被转化为灰度图像,也是为了方便计算,否则三个通道的像素一起处理计算量非常大。随着计算机性能的高速发展,现在有些神经网络也可以处理三通道的RGB图像。

          输入层的作用就是将图像转换为其对应的由像素值构成的二维矩阵,并将此二维矩阵存储。

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//

3 卷积层

3.1 CNN怎么进行识别

        通过卷积运算我们可以提取出图像的特征,通过卷积运算可以使得原始信号的某些特征增强,并且降低噪声。

        用一个滤波器fx去卷积一个输入的图像(第一阶段是输入的图像,后面的阶段就是卷积特征map了),然后加一个偏置bx,得到卷积层Cx。
下采样层:因为对图像进行下采样,可以减少数据处理量同时保留有用信息,采样可以混淆特征的具体位置,因为某个特征找出来之后,它的位置已经不重要了,我们只需要这个特征和其他特征的相对位置,可以应对形变和扭曲带来的同类物体的变化。

每邻域四个像素求和变为一个像素,然后通过标量Wx+1加权,再增加偏置bx+1,然后通过一个sigmoid激活函数,产生一个大概缩小四倍的特征映射图Sx+1。
 

3.2过滤器(卷积核)

        在卷积运算时,会给定一个大小为F*F的方阵,称为过滤器,又叫做卷积核,该矩阵的大小又称为感受野。过滤器的深度d和输入层的深度d维持一致,因此可以得到大小为F*F*d的过滤器,从数学的角度出发,其为d个F*F的矩阵。在实际的操作中,不同的模型会确定不同数量的过滤器,其个数记为K,每一个K包含d个F*F的矩阵,并且计算生成一个输出矩阵。

        一定大小的输入和一定大小的过滤器,再加上一些额外参数,会生成确定大小的输出矩阵。以下先介绍这些参数。

3.3 Padding

        在进行卷积运算时,输入矩阵的边缘会比矩阵内部的元素计算次数少,且输出矩阵的大小会在卷积运算中相比较于输入变小。因此,可在输入矩阵的四周补零,称为padding,其大小为P。比如当P=1时,原5*5的矩阵如下,蓝色框中为原矩阵,周围使用0作为padding。

from tensorflow.keras.layers import Conv2D

# 在Keras中创建一个卷积层并指定'padding'参数
conv_layer = Conv2D(filters=32, kernel_size=(3, 3), strides=1, padding='same')

        在这个例子中,kernel_size=(3, 3)意味着使用的是3x3大小的卷积核,而padding='same'表示我们想要保持输入和输出在空间维度上的尺寸相同。如果改为padding='valid',则不会有额外的填充,输出尺寸将会减小。

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

3.4 卷积的感受野
3.4.1感受野的概念

        在卷积神经网络中,感受野(Receptive Field)的定义是卷积神经网络每一层输出的特征图(feature map)上的像素点在输入图片上映射的区域大小。再通俗点的解释是,特征图上的一个点对应输入图上的区域,如图1所示。

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//

4 池化层

4.1 池化层的作用

池化层的作用:是对卷积层中提取的特征进行挑选。

        常见的池化操作有最大池化和平均池化,池化层是由n×n大小的矩阵窗口滑动来进行计算的,类似于卷积层,只不过不是做互相关运算,而是求n×n大小的矩阵中的最大值、平均值等。

池化层主要有以下几个作用:

1. 挑选不受位置干扰的图像信息。

2. 对特征进行降维,提高后续特征的感受野,也就是让池化后的一个像素对应前面图片中的一个区域。

3. 因为池化层是不进行反向传播的,而且池化层减少了特征图的变量个数,所以池化层可以减少计算量。

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//

5 全连接层

        池化层的后面一般接着全连接层,全连接层将池化层的所有特征矩阵转化成一维的特征大向量,全连接层一般放在卷积神经网络结构中的最后,用于对图片进行分类,到了全连接层,我们的神经网络就要准备输出结果了

        如下图所示,倒数第二列的向量就是全连接层的数据

        从池化层到全连接层会进行池化操作,数据会进行多到少的映射,进行降维,也就是为什么上图从20×12×12变成100个神经元了,数据在慢慢减少,说明离输出结果越来越近,从全连接层到输出层会再一次减少数据,变成更加低维的向量,这个向量的维度就是需要输出的类别数。然后将这个向量的每个值转换成概率的表示,这个操作一般叫做softmax,softmax使得向量中每个值范围在(0,1)之间,它是二分类函数sigmoid在多分类上的推广,目的是将多分类的结果以概率的形式展现出来。

        

5.1 全连接层的作用

因为从卷积层过来的数据太多了,全连接层的作用主要是对数据进行降维操作,不然数据骤降到输出层,可能会丢失一些图像特征的重要信息。

6 案例

下面是一个使用Keras库构建的简单卷积神经网络(CNN)案例,该网络用于解决MNIST手写数字识别问题:

# 导入所需库
from tensorflow.keras.datasets import mnist
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense

# 加载MNIST数据集
(x_train, y_train), (x_test, y_test) = mnist.load_data()

# 数据预处理
x_train = x_train.reshape(-1, 28, 28, 1).astype('float32') / 255.0
x_test = x_test.reshape(-1, 28, 28, 1).astype('float32') / 255.0
y_train = tf.keras.utils.to_categorical(y_train, 10)
y_test = tf.keras.utils.to_categorical(y_test, 10)

# 构建卷积神经网络模型
model = Sequential([
    Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=(28, 28, 1)),
    MaxPooling2D(pool_size=(2, 2)),
    Conv2D(64, kernel_size=(3, 3), activation='relu'),
    MaxPooling2D(pool_size=(2, 2)),
    Flatten(),
    Dense(128, activation='relu'),
    Dense(10, activation='softmax')  # 输出层,对应10个数字类别
])

# 编译模型
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])

# 训练模型
model.fit(x_train, y_train, batch_size=128, epochs=10, validation_data=(x_test, y_test))

# 评估模型
test_loss, test_acc = model.evaluate(x_test, y_test)
print(f'Test accuracy: {test_acc}')

这个简单的卷积神经网络包含两个卷积层(Conv2D)和两个最大池化层(MaxPooling2D),然后通过Flatten层展平数据,接着连接两个全连接层(Dense),最后是10个节点的输出层,采用softmax激活函数用于多分类任务。整个模型使用Adam优化器进行编译,并以交叉熵损失函数为目标进行训练。

7 常用框架

Caffe
 •源于Berkeley的主流CV工具包,支持C++,python,matlab
 •Model Zoo中有大量预训练好的模型供使用

PyTorch
 •Facebook用的卷积神经网络工具包
 •通过时域卷积的本地接口,使用非常直观
 •定义新网络层简单

TensorFlow
 •Google的深度学习框架
 •TensorBoard可视化很方便
 •数据和模型并行化好,速度快

感知机:

PlayGround

http://playground.tensorflow.org

PlayGround是一个在线演示、实验的神经网络平台,是一个入门神经网络非常直观的网站。这个图形化平台非常强大,将神经网络的训练过程直接可视化。同时也能让我们对Tensorflow有一个感性的认识。

PlayGround页面如图所示,主要分为DATA(数据),FEATURES(特征),HIDDEN LAYERS(隐含层),OUTPUT(输出层)。

最后代码实现手写字体识别

import tensorflow as tf
import os
from tensorflow.examples.tutorials.mnist import input_data
from tensorflow.contrib.slim.python.slim.nets.inception_v3 import inception_v3_base


# 1、利用数据,在训练的时候实时提供数据
# mnist手写数字数据在运行时候实时提供给给占位符

tf.app.flags.DEFINE_integer("is_train", 1, "指定是否是训练模型,还是拿数据去预测")
FLAGS = tf.app.flags.FLAGS


def create_weights(shape):
    return tf.Variable(initial_value=tf.random_normal(shape=shape, stddev=0.01))


def create_model(x):
    """
    构建卷积神经网络
    :param x:
    :return:
    """
    # 1)第一个卷积大层
    with tf.variable_scope("conv1"):

        # 卷积层
        # 将x[None, 784]形状进行修改
        input_x = tf.reshape(x, shape=[-1, 28, 28, 1])
        # 定义filter和偏置
        conv1_weights = create_weights(shape=[5, 5, 1, 32])
        conv1_bias = create_weights(shape=[32])
        conv1_x = tf.nn.conv2d(input=input_x, filter=conv1_weights, strides=[1, 1, 1, 1], padding="SAME") + conv1_bias

        # 激活层
        relu1_x = tf.nn.relu(conv1_x)

        # 池化层
        pool1_x = tf.nn.max_pool(value=relu1_x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")

    # 2)第二个卷积大层
    with tf.variable_scope("conv2"):

        # 卷积层
        # 定义filter和偏置
        conv2_weights = create_weights(shape=[5, 5, 32, 64])
        conv2_bias = create_weights(shape=[64])
        conv2_x = tf.nn.conv2d(input=pool1_x, filter=conv2_weights, strides=[1, 1, 1, 1], padding="SAME") + conv2_bias

        # 激活层
        relu2_x = tf.nn.relu(conv2_x)

        # 池化层
        pool2_x = tf.nn.max_pool(value=relu2_x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")

    # 3)全连接层
    with tf.variable_scope("full_connection"):
        # [None, 7, 7, 64]->[None, 7 * 7 * 64]
        # [None, 7 * 7 * 64] * [7 * 7 * 64, 10] = [None, 10]
        x_fc = tf.reshape(pool2_x, shape=[-1, 7 * 7 * 64])
        weights_fc = create_weights(shape=[7 * 7 * 64, 10])
        bias_fc = create_weights(shape=[10])
        y_predict = tf.matmul(x_fc, weights_fc) + bias_fc

    return y_predict


def full_connected_mnist():
    """
    单层全连接神经网络识别手写数字图片
    特征值:[None, 784]
    目标值:one_hot编码 [None, 10]
    :return:
    """
    mnist = input_data.read_data_sets("./mnist_data/", one_hot=True)
    # 1、准备数据
    # x [None, 784] y_true [None. 10]
    with tf.variable_scope("mnist_data"):
        x = tf.placeholder(tf.float32, [None, 784])
        y_true = tf.placeholder(tf.int32, [None, 10])

    y_predict = create_model(x)

    # 3、softmax回归以及交叉熵损失计算
    with tf.variable_scope("softmax_crossentropy"):
        # labels:真实值 [None, 10]  one_hot
        # logits:全脸层的输出[None,10]
        # 返回每个样本的损失组成的列表
        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.AdamOptimizer(0.001).minimize(loss)

    # 5、得出每次训练的准确率(通过真实值和预测值进行位置比较,每个样本都比较)
    with tf.variable_scope("accuracy"):
        equal_list = tf.equal(tf.argmax(y_true, 1), tf.argmax(y_predict, 1))
        accuracy = tf.reduce_mean(tf.cast(equal_list, tf.float32))

    # (2)收集要显示的变量
    # 先收集损失和准确率
    tf.summary.scalar("losses", loss)
    tf.summary.scalar("acc", accuracy)

    # 初始化变量op
    init_op = tf.global_variables_initializer()

    # (3)合并所有变量op
    merged = tf.summary.merge_all()

    # 创建模型保存和加载
    saver = tf.train.Saver()

    # 开启会话去训练
    with tf.Session() as sess:
        # 初始化变量
        sess.run(init_op)

        # (1)创建一个events文件实例
        file_writer = tf.summary.FileWriter("./tmp/summary/", graph=sess.graph)

        # 加载模型
        # if os.path.exists("./tmp/modelckpt/checkpoint"):
        #     saver.restore(sess, "./tmp/modelckpt/fc_nn_model")

        if FLAGS.is_train == 1:
            # 循环步数去训练
            for i in range(3000):
                # 获取数据,实时提供
                # 每步提供50个样本训练
                mnist_x, mnist_y = mnist.train.next_batch(50)
                # 运行训练op
                sess.run(train_op, feed_dict={x: mnist_x, y_true: mnist_y})
                print("训练第%d步的准确率为:%f, 损失为:%f " % (i+1,
                                     sess.run(accuracy, feed_dict={x: mnist_x, y_true: mnist_y}),
                                     sess.run(loss, feed_dict={x: mnist_x, y_true: mnist_y})
                                     )
                  )

                # 运行合变量op,写入事件文件当中
                summary = sess.run(merged, feed_dict={x: mnist_x, y_true: mnist_y})
                file_writer.add_summary(summary, i)
                # if i % 100 == 0:
                #     saver.save(sess, "./tmp/modelckpt/fc_nn_model")

        else:
            # 如果不是训练,我们就去进行预测测试集数据
            for i in range(100):
                # 每次拿一个样本预测
                mnist_x, mnist_y = mnist.test.next_batch(1)
                print("第%d个样本的真实值为:%d, 模型预测结果为:%d" % (
                                                      i+1,
                                                      tf.argmax(sess.run(y_true, feed_dict={x: mnist_x, y_true: mnist_y}), 1).eval(),
                                                      tf.argmax(sess.run(y_predict, feed_dict={x: mnist_x, y_true: mnist_y}), 1).eval()
                                                      )
                                                      )

    return None


if __name__ == "__main__":
    full_connected_mnist()

参考文章:卷积神经网络超详细介绍-CSDN博客

参考文章:卷积神经网络—感受野与特征图_特征图越大,对检测效果有什么影响-CSDN博客

参考文章:卷积神经网络中卷积层、池化层、全连接层的作用_池化层作用-CSDN博客

池化层图片来自:卷积神经网络概念与原理_卷积神经网络原理-CSDN博客

参考文章:CNN卷积神经网络(图解CNN)-CSDN博客

参考文章:CNN笔记:通俗理解卷积神经网络_cnn卷积神经网络-CSDN博客

参考文章:神经网络——最易懂最清晰的一篇文章-CSDN博客​​​​​​

参考文章:卷积神经网络(CNN)详细介绍及其原理详解-CSDN博客​​​​​​

参考文章:卷积神经网络CNN基本原理详解_cnn工作原理-CSDN博客​​​​​​

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/462084.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JavaScript 基础知识

一、初识 JavaScript 1、JS 初体验 JS 有3种书写位置&#xff0c;分别为行内、内部和外部。 示例&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"wid…

CASA模型在陆地生态系统碳循环研究中的应用探讨

植被&#xff0c;作为陆地生态系统的重要基石&#xff0c;对维护生态环境功能具有不可替代的作用。其中&#xff0c;植被净初级生产力&#xff08;NPP&#xff09;是衡量植被生态系统健康与功能的关键指标。它反映了单位面积上绿色植被通过光合作用生产的有机质总量在扣除自养呼…

软件测试面试都问了什么?中级软件测试岗面试(4面)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 一面&#xff08;…

瑞熙贝通实验室安全培训考试系统

一、系统概述 瑞熙贝通实验室安全培训考试系统是一种基于互联网和人工智能技术的在线考试平台&#xff0c;旨在旨在提供实验室安全教育和考核的全面解决方案。该系统可以帮助实现实验室安全培训考试的在线化、智能化和规范化&#xff0c;提高实验室安全意识和能力&#xff0c;…

Arduino平台软硬件原理及使用——色环电阻及贴片电阻的阻值识别

文章目录 一、四色环电阻及其阻值识别 二、五色环、六色环电阻及其阻值识别 三、三位数字及四位数字编码的贴片电阻及其阻值识别 四、E96编码的贴片电阻及其阻值识别 一、四色环电阻及其阻值识别 如上图为四色环电阻的实物图&#xff0c;图中左侧的三道环间距一致&#xff0c;第…

【List集合】List接口源码解读一(ArrayList)

目录 前言 1. List接口的基本信息 2. ArrayList 2.1.ArrayList 的基本信息 2.2. ArrayList 的构造方法 2.2.1 ArrayList 的构造方法一 2.2.2 ArrayList 的构造方法二 2.2.3 ArrayList 的构造方法三 2.3 ArrayList 的扩容方式 总结 前言 Java 语言由于其跨平台、社区良…

3.Redis命令

Redis命令 Redis 根据命令所操作对象的不同&#xff0c; 可以分为三大类&#xff1a; 对 Redis 进行基础性操作的命令&#xff0c;对 Key 的操作命令&#xff0c;对 Value 的操作命令。 1.1 Redis 首先通过 redis-cli 命令进入到 Redis 命令行客户端&#xff0c;然后再运行下…

Spring Web MVC入门(2)

学习Spring MVC Postman介绍 在软件工程中, 我们需要具有前后端分离的思想, 以降低耦合性. 但是在测试后端代码时,我们还得写前端代码测试,这是个令人头疼的问题. 那么我们如何测试自己的后端程序呢, 这就用到了一个工具: Postman. 界面介绍: 传参的介绍 1.普通传参, 也就…

世界环境绩效指数EPI数据集(2000-2022年)

环境绩效指数&#xff08;EPI&#xff09;是由耶鲁大学和哥伦比亚大学联合发布的一项综合指标&#xff0c;旨在衡量世界各国在可持续环境管理方面的表现。覆盖2000年至2022年&#xff0c;EPI通过分析各国在多个维度上的环境政策执行成效&#xff0c;包括空气质量、水资源管理、…

Fiddler工具 — Fiddler常用插件(Willow)

Fiddler已有的功能已经够我们日常工作中使用了&#xff0c;为了更好的扩展Fiddler&#xff0c;Fiddler也是支持一些插件的安装&#xff0c;也支持用户自己开发插件并安装。 Fiddler插件下载地址&#xff1a;https://www.telerik.com/fiddler/add-ons 1、Traific Difer插件 Tr…

计算机通识——01.进制转换

前言 学习资料来自 C训练以及CSDN各博主的博客整合而来&#xff0c;内容涵盖计算机通识内容&#xff1a;进制转换、信息单位、数据校验、多媒体基础参数、HTTP \ HTTPS协议、OSI七层模型、IP基础 \ IPv6、网络拓扑机构、域名解析、常用网络命令和端口、数据结构常识等内容&…

探讨TCP的可靠性以及三次握手的奥秘

&#x1f31f; 欢迎来到 我的博客&#xff01; &#x1f308; &#x1f4a1; 探索未知, 分享知识 !&#x1f4ab; 本文目录 1. TCP的可靠性机制1.2可靠性的基础上,尽可能得提高效率 2. TCP三次握手过程3. 为何不是四次握手&#xff1f; 在互联网的复杂世界中&#xff0c;TCP&am…

如何保存缓存和MySQL的双写一致呢?

如何保存缓存和MySQL的双写一致呢&#xff1f; 所谓的双写一致指的是&#xff0c;在同时使用缓存(如Redis)和数据库(如MySQL)的场景下,确保数据在缓存和数据库中的更新操作保持一致。当对数据进行修改的时候&#xff0c;无论是先修改缓存还是先修改数据库&#xff0c;最终都要保…

私域必备宝藏工具!让你轻松管理多个微信号

随着私域流量越来越受到重视&#xff0c;很多人手上都有着好几个微信&#xff0c;而一个手机最多只能登录两个微信&#xff0c;管理起来很是麻烦。 不过不用担心&#xff0c;微信管理系统可以帮助大家解决这个问题&#xff0c;让大家能够轻松管理多个微信号&#xff0c;提高私…

springCloudeAlibaba的使用

父pom文件&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.o…

学python新手如何安装pycharm;python小白如何安装pycharm

首先找到官网&#xff1a; Download PyCharm: The Python IDE for data science and web development by JetBrains 打开后选择下载&#xff0c;下图标红部分 点击exe程序&#xff0c;点击下一步&#xff01; 选择安装路径&#xff0c;下一步 弹出界面全选 选择默认 然后直接…

猜一猜“爵”在古代是哪种器具?2024年3月17日蚂蚁庄园今日答案

蚂蚁庄园是一款爱心公益游戏&#xff0c;用户可以通过喂养小鸡&#xff0c;产生鸡蛋&#xff0c;并通过捐赠鸡蛋参与公益项目。用户每日完成答题就可以领取鸡饲料&#xff0c;使用鸡饲料喂鸡之后&#xff0c;会可以获得鸡蛋&#xff0c;可以通过鸡蛋来进行爱心捐赠。其中&#…

CTF-希尔加解密

对于希尔加解密很多writeup都说用在线工具,所以研究了一下,写了一个方便的加解密python代码,根据给定的字母表及私钥字符串,尝试不同纬度不同重叠的加密矩阵输出加解密结果。运行效果如下: 代码文件Hill希尔加解密_final.py import numpy as np import string # 导入自定…

ArcGIS模型构建器Pro版_更多花活演示

相比较ArcMap的模型构建器&#xff0c;Pro里最主要的变化就是增加了一组逻辑工具&#xff1a; 逻辑工具用于控制模型中的流程流&#xff0c;它们返回的结果是true或false。 这个结果一般用于 if-else 分支逻辑&#xff0c;例如&#xff1a;如果某字段存在的时候&#xff0c;执…

从零开始学习编程:迈出你的编程之路

标题 《从零开始学习编程&#xff1a;迈出你的编程之路》摘要引言如何开始学习编程&#xff1f;1. **明确学习目标**2. **选择编程语言**3. **学习资源**4. **练习编程**5. **参与社区**6. **持之以恒**7. **探索更多** 总结参考资料 博主 默语带您 Go to New World. ✍ 个人主…