知识点:神经网络模型的序列和层

这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战

1. 为什么要有神经网络模型?

编程源于生活而高于生活。

生活中,有一只狗叫旺财。编程中也有类和对象的概念:wangcai = Dog()。

之所以这么搞,就是为了符合人类的思维习惯,便于人们理解和编程。

深度学习中,有一个神经网络模型的概念。它接收输入,经过一系列操作,最终产出输出。

比如建立了一个手写识别的模型,输入手写的图片或者轨迹,它可以输出识别后的数字是“6”。

你可以理解它是一套流水线设备。 那么,流水线上是怎么样的呢?

首先有输入,就是把原材料放进去。

原材料.gif

然后按照次序,经过多道工序,层层处理。

流水线.gif

每一层处理都有自己的独特的工作。

打标记.gif

最后是输出,生成最终产物。

产出.gif

2. 模型序列中那些常用的层

一个神经网络模型和流水线很类似,也有一套多层的处理设备,能将输入转化为输出。

2.1 Sequential 序列

通过序列Sequential构建模型有如下两种方式:

# 方式一:一站式
model = tf.keras.models.Sequential([
    keras.layers.Flatten(),
    keras.layers.Dense(),
    keras.layers.Dropout(),
    keras.layers.Dense()
])
复制代码
# 方式二:分步式
model = tf.keras.models.Sequential()
model.add(layers.Embedding())
model.add(layers.Bidirectional())
model.add(layers.Dense())
复制代码

两种方式的共同点都是通过Sequential构建模型,一个模型都会设置多个层。

我们拿手写数字识别的序列举个例子:

model = tf.keras.models.Sequential([
    tf.keras.layers.Flatten(input_shape=(28,28)),
    tf.keras.layers.Dense(128, activation='relu'),
    tf.keras.layers.Dense(10, activation='softmax')
])

model.summary()
复制代码

这个序列里面依次包含了三个层,每个层是有顺序的,这也是为什么叫序列的原因。

可以调用model.summary()打印出来结构:

Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
flatten (Flatten)            (None, 784)               0         
_________________________________________________________________
dense (Dense)                (None, 128)               100480    
_________________________________________________________________
dense_1 (Dense)              (None, 10)                1290      
_________________________________________________________________
复制代码
  1. 第一层输入28x28的二维数据,输出784大小的一维数据。
  2. 第二层将第一层的输出作为输入,输出128大小的一维数据。
  3. 第三层将第二层的输出作为输入,输出10大小的一维数据。

其实28x28的二维数据就是图片像素值的宽高矩阵。

image.png

其转化的流程如下图所示:

graph TD
A[第一层-28x28图片] --计算出784个像素数据--> B[第二层-处理像素数值] --总结成128项指标--> C[第三层-评判指标]
C--概率 1%-->R1[0]
C--概率 1%-->R2[1]
C--概率 0-->R5[...]
C--概率 98%-->R6[6]
C--概率 0-->R7[...]
C--概率 0-->R9[9]

第一层转为784大小的一维数组,经过第二层变为128大小,到第三层时转化成10的大小,这10个代表0~9个数字的分类,其中数字“6”的分类占比最高,所以识别结果就是“6”。

那么,这些个都有哪些,他们都起什么作用呢?

看代码都是tf.keras.layers开头的,说明他们是一类,下面就说几个常见的层。

2.2 Dense 全连接层

2021-11-22_231223.jpg

Dense层又称全连接层,是神经网络中最常见的一个层,它既能当输入层,又能当输出层,还能当中间层。

Dense的中文翻译是:稠密的,笨拙的。看它上面的结构图就很稠密,密密麻麻。

说到笨拙,其实它确实也不聪明,它就是固定的计算,逻辑上等价于一个函数:out=Activation(Wx+bias)。

  • W:m*n的矩阵,权重,结构是提前定义的,但是数值是训练出来的。
  • x:n维向量,是输入。
  • Activation:激活函数,为线性变换再套一层变换,解决非线性问题。
  • bias:偏置项,也是训练出来的。
  • out:最终输出m维向量。

最终变化就是一个线性变化加一个非线性变化产生输出。

从效果看是:输入的n维数据,最后输出m维数据。

2021-11-24_062137.jpg

就好比手写数字识别中,输入是28x28的二维向量,经过层层变化,最终输出10个分类。

全连接层的定义举例:Dense(10, activation='softmax')

  • 该层有10个节点的输出,也是下一个节点的输入。
  • 激活函数使用softmax。

2.3 Conv2D 卷积层

卷积层一般用于图像处理,用于寻找图像的局部特征。

假如,我们要识别一张图片是不是老鹰,我们依靠两点进行判断:鹰嘴、鹰爪。如果有这两个特点,我们就说这是老鹰。

老鹰.jpg

要判断是否包含这两类特征,我们就需要有一个小方块在图片上移动,这个小方块是带着有色眼镜的,会专门寻找鹰爪的那个勾,遇到带勾的区域就特别兴奋地标记为1,遇不到就没有感觉地标记为0。

这个小方块就是卷积核,卷积核在整幅图像上挨个标记的操作就叫卷积操作。

卷积.gif

上图就是模拟了一个卷积操作。

用一个3x3的卷积核,在5x5的图像上标记,每次移动一个格子,最后生成了最右边2x2的图像。

如果我们定义卷积值大于600就是鹰爪的话,那么原图经过扫描之后,发现有2个鹰爪。

卷积可以重复卷,可以卷完了再卷,很恐怖。

卷积的定义举例:Conv2D(64, (3,3), activation='relu')

  • 卷积层的卷积核大小为3x3。
  • 有64类卷积方块去进行扫描。
  • 激活函数使用relu。

2.4 Flatten 压平层

这个层最容易理解。就是把多维压平成一维。

relu5.gif

一般情况下,它作为从卷积层到全连接层的过渡。因为图片一般是二维的,但是分类是一维的,需要中间某个时机进行转化。

……
model.add(layers.Conv2D(64, (3,3), activation='relu'))
model.add(layers.Flatten())
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(10))
……
复制代码

上面的例子就是图片经过卷积多次之后,经过Flatten拉平,然后加两个全连接层最终达到图片变为分类的效果。

2.5 MaxPooling2D 池化层

池化层,可以简单理解成压缩。

对于人工智能,一旦训练起来可能是几天甚至几个月。如果能节省时间,那就太好了,可以快速试错和验证新想法。

那么,如何节省时间呢?除了砸钱增加设备配置之外,降低数据计算量也是一个有效的办法。

我们看下面这张图,左边和右边虽然大小不一样,但是他俩的特征却是一样的,是同一类图像。

2021-11-24_222650.jpg

这时候,计算尺寸小的图片就比较合算了,能减少成倍的计算量。

所以,我们看很多图片数据集,都是非常小且模糊,精简到你勉强认识。

fashion-mnist-sprite.png

但是,实际上我们生活中的图片却非常大。

output_N1loMlbYHeiJ_0.png

因此,将高清图在保留特征的情况下尽量压缩,以减少数据复杂度,这就是池化层的作用。

池化有很多种方式,比如最大池化,也就是在一定区域内只要最大值。

2021-11-24_224041.jpg

其他还有平均池化,就是取平均值。

池化层的定义很简单,和卷积层很像,需要定义池化矩阵。例如MaxPooling2D((2,2))就是定义了一个2x2的池化矩阵。

看下面一个卷积后池化的例子。

model = models.Sequential()
model.add(layers.Conv2D(32,(3,3), activation='relu', input_shape=(32,32,1)))
model.add(layers.MaxPooling2D((2,2)))
model.summary()
复制代码

通过打印结果发现,32x32的图片,经过3x3的卷积核以每次移动1个单位处理后,变成30x30的图片,再通过2x2的池化,让30x30变成了15x15。

conv2d (Conv2D)              (None, 30, 30, 32)        320       
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 15, 15, 32)        0         
_________________________________________________________________
复制代码

上面就是神经网络序列中经常出现的几种层。

おすすめ

転載: juejin.im/post/7034156187100643364