首页 > Udacity机器人软件工程师课程笔记(三十) - 语义分割与实例实现 - 使用keras实现语义分割

Udacity机器人软件工程师课程笔记(三十) - 语义分割与实例实现 - 使用keras实现语义分割

语义分割

1.语义分割介绍

计算机视觉与机器学习研究者对图像语义分割问题越来越感兴趣。越来越多的应用场景需要精确且高效的分割技术,如自动驾驶、室内导航、甚至虚拟现实与增强现实等。这个需求与视觉相关的各个领域及应用场景下的深度学习技术的发展相符合,包括语义分割及场景理解等…

更多可以参考语义分割概述.

在这个项目中,我们将训练一个深度神经网络,以从Quadcoptor模拟器生成的图像中识别目标人。拥有训练完成的网络后,我们可以通过推理使用它在新图像中找到目标。

在这里插入图片描述

在最终的Follow Me项目中,推理步骤必须在仿真中连续运行,就像直升机向其提供图像一样快。在本项目中引入了一些额外的代码抽象和性能增强,这些在进行仿真时是必需的,

  1. 环境设置
  2. TensorFlow中的Keras层
  3. 具有可分离卷积的编码器
  4. 批量归一化
  5. 具有双线性上采样的解码器
  6. 层级联

本实验使用来自模拟器的实际数据,最后,我们将拥有一个理论上可以正常运行的网络,可以将其整合到Follow Me项目中。我们将需要通过附加层,参数调整甚至收集更多数据来最大化网络性能。

(1)环境设置

在本实验中, 课程还是以jupternotebook的形式提供,为了方便我以后使用,我会再将来的内容更改成.py格式。

运行以下命令以克隆实验室存储库:

git clone https://github.com/udacity/RoboND-Segmentation-Lab.git
# Make sure your conda environment is activated!
jupyter notebook

或者进入https://github.com/udacity/RoboND-Segmentation-Lab.git去下载相应的压缩包解压到相应的路径中。其中包括储存库,训练数据和验证数据。

(2)Keras

Keras 是目前使用最为广泛的深度学习工具之一,它的底层可以支持Tensor Flow 、

MXNet、CNTK 和Theano 。如今, Keras 更是被直接引入了TensorFlow 的核心代码库,成为TensorFlow 官方提供的高层封装之一。

选择Keras的优点:

  • 训练例程已简化,并通过标准接口提供。
  • 不必自己管理tensorflow会话。
  • 数据生成器具有标准接口。
  • 这些层是具有语法层()(prev_layer)的类,而不是具有layer(prev_layer)的功能接口,层的命名约定在它们之间是相当标准的。
  • Keras有额外的层来处理诸如上采样和其他小的特性,而在tensorflow中这些是分散的。
  • 若想要向网络添加新功能,那么需要将功能包装在一个自定义层中,或者编写为lambda层。

(3)编码器

FCN是由编码器和解码器组成的。编码器部分是一个卷积网络,可简化为更深的1x1卷积层,而不是用于图像基本分类的平面全连接层。这种差异具有从图像中保留空间信息的效果。

这里介绍的可分离卷积是一种减少所需参数数量的技术,从而提高了编码器网络的效率。

可分离卷积

可分离卷积,也称为深度可分离卷积,由一个在输入层的每个通道上执行的卷积和一个1x1卷积组成,1x1卷积将前一步的输出通道合并成输出层。

这与我们之前介绍的常规卷积不同,主要是因为减少了参数的数量。让我们考虑一个简单的例子。

设输入形状是32x32x3。需要9个输出通道和形状为3x3x3的过滤器(内核)。在常规卷积中,9个内核遍历3个输入通道。这将导致总共933*3个特征(忽略偏置)。总共243个参数。

在可分卷积的情况下,通过3个输入通道,每个通道有一个内核。这给了我们27个参数(333)和3个特征图。在下一步中,这3个特征映射将被9个1x1卷积遍历。结果总共有27(9*3)个参数。总共有54(27 + 27)个参数!比我们上面得到的243个参数少得多。随着层或通道的大小的增加,这种差异将会更加明显。

参数的减少使得可分卷积在提高运行时性能的同时非常高效,因此对于移动应用程序也非常有用。由于参数较少,它们还具有在一定程度上减少过拟合的额外好处。

可分离卷积相关代码

在utils所提供的仓库的模块中提供了可分离卷积的优化版本。它基于tf.contrib.keras函数定义,可以实现如下:

output = SeparableConv2DKeras(filters, kernel_size, strides, padding, activation)(input)

其中,

input是输入层,

filters 是输出滤波器的数量(深度),

kernel_size是一个数字,指定内核的(宽度,高度),

padding 是“SAME”或“VALID”

activation是激活函数,例如“ relu”。

以下是如何使用上述功能的示例:

output = SeparableConv2DKeras(filters=32, kernel_size=3, strides=2,padding='same', activation='relu')(input)

(4)批处理归一化

批处理归一化是优化网络训练的另一种方法。

批量归一化基于以下思想:我们不仅将输入归一化到网络中,还将输入归一化到网络中的各个层。之所以称为“批处理”归一化,是因为在训练期间,我们使用当前迷你批处理中的值的均值和方差来归一化每一层的输入。

网络是一系列的层,其中一层的输出成为另一层的输入。这意味着我们可以把神经网络中的任何一层想象成更小网络的第一层。

例如,设想一个3层的网络。不要把它看作是一个具有输入、网络的层和输出的单一网络,而是把第1层的输出看作是一个两层网络的输入。这两层网络将由我们原来的网络中的第2层和第3层组成。

同样地,第2层的输出可以被认为是一个单层网络的输入,该网络只包含第3层。

当我们把它看作是一系列相互作用的神经网络时,就很容易想象把每一层的输入归一化会有多大帮助。这就像对任何其他神经网络的输入进行归一化一样,但是在每一层(子网络)都在这么做。

批归一化代码

在中tf.contrib.keras,可以使用以下函数定义来实现批量标准化:

from tensorflow.contrib.keras.python.keras import layers
output = layers.BatchNormalization()(input) 

separable_conv2d_batchnorm()函数在可分离卷积层之后添加批处理归一化层。引入批处理规范化层为我们提供了很多优势。

例如:

  • 网络训练速度更快 – 由于前向传递期间的额外计算,每个训练迭代实际上会更慢。但是,它的收敛速度应该快得多,所以总体上训练应该更快。
  • 允许更高的学习率 – 梯度下降法通常需要较小的学习速率才能使网络收敛。当网络越深,它们的梯度在反向传播时就越小,因此它们需要更多的迭代。使用批处理规范化允许我们使用更高的学习率,这进一步提高了网络训练的速度。
  • 简化了更深层网络的创建 – 由于上述原因,在使用批处理规范化时,更容易构建并且更快地训练更深层的神经网络。
  • 提供一些正则化 – 批处理归一化会给网络增加一些干扰。在某些情况下,例如在Inception模块中,批处理归一化已经被证明与dropout一样有效。

(5)解码器

在前面讲过转置卷积,作为将层向上采样到更高维度或分辨率的一种方法。实际上,有几种方法可以实现向上采样。在本节中,将介绍另一种方法,称为双线性上采样双线性插值

双线性上采样

双线性上采样是一种重采样技术,该技术利用与给定像素对角线的四个最接近的已知像素的加权平均值来估计新的像素强度值。加权平均值通常取决于距离。

让我们考虑这样一种情况:有4个已知像素值,因此本质上是2x2灰度图像。需要将此图像上采样为4x4图像。下图更好地说明了此过程。

在这里插入图片描述上面4x4插图中未标记的像素实际上是空白。双线性上采样方法将尝试通过插值来填充所有剩余的像素值。考虑P5P_5P5的情况来理解这个算法。

我们首先使用线性插值计算P12P_{12}P12P34P_{34}P34的像素值。

P12=P1+W1∗(P2−P1)/W2P_{12}= P_1 + W_1*(P_2 - P_1)/W_2P12=P1+W1(P2P1)/W2

P34=P3+W1∗(P4−P3)/W2P_{34}= P_3 + W_1*(P_4 - P_3)/W_2P34=P3+W1(P4P3)/W2

使用P12和P34,我们可以得到P5:

P5=P12+H1∗(P34−P12)/H2P_5 = P_{12}+ H_1*(P_{34}- P_{12})/H_2P5=P12+H1(P34P12)/H2

为了简单起见,我们假设H_2 = W_2 = 1

将P34和P12代入后,P5像素值的最终方程为:

P5=P1∗(1−W1)∗(1−H1)+P2∗W1∗(1−H1)+P3∗H1∗(1−W1)+P4∗W1∗H1P_5 = P_1 * (1 - W_1) * (1 - H_1) + P_2 * W_1 * (1 - H_1) + P_3 * H_1 * (1 - W_1) + P_4 * W_1* H_1P5=P1(1W1)(1H1)+P2W1(1H1)+P3H

更多相关:

  • 经常会有有人问到CMake的学习的问题,而且网上也有很多博客是介绍学习CMake 的用法,但是我觉的学习不用这样死板,用到了就顺便学习一下,也就是边做边学,由浅入深,慢慢的就会熟悉了,这个学习的过程中会遇到很多问题,以解决问题的方式驱动自己学习CMake,首先总结一下CMake 的好处,CMake是一个跨平台编译的工具,所以不再需要折...

  • 故事背景:有一天,强哥整了个动态渲染的列表代码如下 app.component.html

          //为什么不直接就用input,那是因为这样会覆盖checkbox和radio的样式,我们这里只需要清除输入框的谷歌样式 input[type="text"], input[type="password"], input[type="number"], input[type="tel"]{box-shadow:...