神经网络基础算法题解

1. 请你说说dropout的作用

什么是dropout:
典型的神经网络训练过程是将输入通过网络进行正向传导,然后将误差进行反向传播,dropout在这个过程中,网络中的节点以概率p被随机丢弃,本次训练中,被丢弃的节点不再起作用,但是接下来的训练中,之前的“丢弃”节点可能继续被“丢弃”,也可能加入训练。
(p一般设置为0.5,也可以根据模型的过拟合风险情况调整,加大或者减小)

dropout原理:

图1

dropout训练类似于bagging训练中的“投票”,对于全连接神经网络而言,用相同的数据集训练n个不同的神经网络可能会得到多个不同的结果,然后利用“投票”机制决定胜出者,从而提升网络性能。同理,对于单个神经网络而言,如果将其分批,虽然不同的网络可能会产生不同程度的过拟合,但是将其共用一个损失函数,相当于同步优化取平均,避免过拟合;

dropout训练减少了神经网络结点之间的共适应性,当隐藏层节点被随机删除后,是的网络具有了一定的稀疏性,从而有效的减轻了不同特征间的协同效应。也就是说,某些特征可能会依赖于固定关系的隐藏节点的共同作用,而通过dropout,迫使一个网络节点和随机挑选出来的其他节点共同工作,达到更好的网络泛化能力。

针对于实际应用场景中,dropout的工作方式或优化版本:

  1. 标准dropout在神经网络训练的工作方式
    在神经网络每轮训练迭代中,网络中的每个神经元以概率p被丢弃。当训练完成后,尽管神经元的输出要乘以该神经元被丢弃的概率 p,整体的网络架构还是会被使用。这样做可以理解为在训练时可能出现的网络上取平均。每一层的 dropout 概率可能不尽相同,发明人建议输入层的 p=0.2,而隐藏层的 p=0.5。输出层中的神经元不会被丢弃。

  2. dropout connect方法
    网络训练时,每个神经元的权重或偏置以一定的概率被设置为 0,而不是将神经元的输出设置为 0。即在训练时,某个网络层的输出可以被写作:

而网络单元结构如图:

dropconnect网络结构单元图

与Dropout不同的是,它不是随机将隐含层节点的输出清0,而是将节点中的每个与其相
连的输入权值以1-p的概率清0。DropConnect只能用于全连接的网络层,如果网络中用
到了卷积,则用patch卷积时的隐层节点是不使用DropConnect的。

  1. 循环神经网络与dropout
    在对循环神经网络使用 Dropout时,只存在于相邻层的循环体单元之间,而同一层的循环体结构之间不会使用Dropout。如图所示,以t-3时刻的输入x(t-3)得到t+1时刻的输出 o(t+I)为例,x(t-3)经过两层 LSTM 循环体结构 得到这一时刻的输出o(t-3)的过程需要发v vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv vvvv 看 用到 Dropout,但是这两层 LSTM 循环体结构在将状态传递到下一时刻相应的 LSTM 循环体结构时没有使用 Dropout。在这之后的时刻,循环体结构的执行以及是否使用 Dropout 也可以参考这一时刻的情况。
LSTM -- dropout

2. 请你说说深度学习你都知道哪些模型?

我主要是做 CV 的,就按照学术界的发展进程,讲讲 CV 相关的深度学习模型吧

  • 图像分类(该阶段主要是参加ILSVRC-ImageNet比赛,提高 ImageNet 数据集的结果,以下模型基本都是历年比赛的冠军模型)
    • LeNet 手写数字识别,开山之作;结构很简单,就是卷积池化、卷积池化,最后是全连接
    • AlexNet 因为受限于显存大小,作为副产品,提出了分组卷积;网络结构更深,使用了relu 激活函数、使用max pooling 替代 mean pooling,使用了 dropout
    • VGGNet 使用 3x3、1x1 的卷积核,取代之前网络的大卷积核(如 7x7); 网络深度达到 19 层
    • Inception and GoogLeNet 谷歌提出的模型,致敬 LeNet; 之前模型都是往深度考虑,inception 网络则是往宽度考虑
    • ResNet 何凯明大佬的经典论文,残差思想很棒;残差可以缓解梯度消失和梯度爆炸,网络深度达到 152 层
    • 等等
  • 目标检测(以下模型主要是基于 VOC 数据集、COCO 数据集)
    • FasterRCNN rgb 大神很经典的文章,至今仍在沿用
    • MaskRCNN 也是何凯明大佬优化的,还实现了语义分割
    • YOLO 一系列
    • SSD 单阶段网络
    • Center Net 网络
  • 针对移动端优化的模型
    • MobileNet 一系列
    • ShuffleNet 一系列
    • GhostNet
    • SqueezeNet
  • 等等

延伸考点

本题很开放,但需要注意不要给自己挖坑,那些自己只知道名字,没有仔细看过的模型最好不要说。
因为面试官很容易打断你,比如“你刚刚提到了 MobileNet 一系列,具体讲讲这些模型的区别吧”。
如果答不上来就很减分,所以只挑自己熟悉的回答。

3. Adam优化器,BN的作用,为什么能加快收敛速度

Adam 优化器的作用
我们优化机器学习或者深度学习模型的关键是梯度下降,典型步骤为:

  1. 给定一组训练样本x和对应的标签y
  2. 对于若干个x运用此时的参数求出预测值y'
  3. 计算y'与这些x对应的真实值y的差值(即损失函数),该函数也是优化器的目标函数
  4. 计算目标函数的梯度(以及动量)
  5. 使用反向传播更新参数
  6. 直到达到终止条件(如误差小于一定阈值)
    Adam就是在第四步起作用,跟adam 对应的基础概念是 SGD,即随机梯度下降: 沿着梯度的方向不断减小模型参数,从而最小化目标函数。
    但 SGD 有一个问题,即容易陷入局部最优解,也可能在鞍点中跳不出,影响模型性能。
    所以研究人员引入了物理学中的动量思想,除了 SGD 中的一阶梯度,还使用梯度一阶矩(指数加权)的估计,使得模型对超参数较为鲁棒。简单来说,可以理解为惯性,相当于模型沿着原来的优化方向,有一个惯性,还有继续往前冲的趋势,从而加快了收敛速度。
    Adam是一个结合了Momentum与Adagrad的产物,它既考虑到了利用动量项来加速训练过程,又考虑到对于学习率的约束。利用梯度的一阶矩估计和二阶矩估计动态调整每个参数的学习率。

Adam的优点主要在于经过偏置校正后,每一次迭代学习率都有个确定范围,使得参数比较平稳。

Adam 算法伪代码

图片说明
从伪代码可以看出:

  • 该算法首先更新梯度的指数移动均值(mt)平方梯度(vt)
  • 参数beta1、beta2 ∈ [0, 1) 控制了这些移动均值指数衰减率
  • 移动均值本身使用梯度的一阶矩(均值)和二阶原始矩(有偏方差)进行估计
  • 然而因为这些移动均值初始化为0 向量,所以矩估计值会偏差向0,因此我们可以得到偏差修正(bias-corrected)的估计mt hatvt hat
  • 最后更新我们想要的梯度。

Ps: 上述伪代码不需要掌握,面试官可能也没掌握那么深

Adam 默认参数

  • lr=0.001 (adam 对初始学习率比较鲁棒)
  • beta1=0.9,
  • beta2=0.999,
  • epislon=1e-8

Adam代码示例

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Data    : 2021/6/24 12:47 上午
# @Author  : 不要求掌握,仅用于帮助理解
# @Site    : 
# @File    : Adam优化器.py
# @Software: PyCharm
import math

# 定义 adam 优化器的参数
alpha = 0.01
beta_1 = 0.9
beta_2 = 0.999
epsilon = 1e-8

# 目标函数 解方程(该函数的解是 2)
def func(x):
    return x * x - 4 * x + 4

# 上述目标函数的梯度
def grad_func(x):
    return 2 * x - 4

def main():
    # 初始化
    theta_0 = 0  # 假定我们从 0 开始优化
    m_t = 0
    v_t = 0
    t = 0  # step

    while True:
        t += 1
        g_t = grad_func(theta_0)  # 计算当前梯度
        m_t = beta_1 * m_t + (1 - beta_1) * g_t  # 使用滑动平均法更新一阶梯度
        v_t = beta_2 * v_t + (1 - beta_2) * (g_t * g_t)  # 使用滑动平均法更新二阶梯度
        m_cap = m_t / (1 - (beta_1 ** t))  # 计算偏置校正的估计
        v_cap = v_t / (1 - (beta_2 ** t))  # 计算偏置校正的估计
        theta_0_prev = theta_0
        theta_0 = theta_0 - (alpha * m_cap) / (math.sqrt(v_cap) + epsilon)  # 更新参数
        print("step: {}, cur_val: {}".format(t, theta_0))
        if (theta_0 == theta_0_prev):  # 检查是否收敛
            break


if __name__ == '__main__':
    main()

BN 的作用

训练过程中,同一个 batch 中的样本差别很大,如果直接训练的话,每次送入网络训练的数据分布来回波动,不利于模型收敛,很容易震荡。

因此,BN 要做的第一件事就是“减均值、除以方差”的归一化操作(对应图片的前三步)。

但对样本做归一化会改变样本的分布,即训练数据和测试数据可能并不符合归一化之后的正态分布,因此图片中的第四步也非常关键,即 scale and shift操作,通过一个线性变换y=scale*x+shift,可以恢复数据的原本分布,从而保证了模型的学习能力。

延伸考点

不要求掌握 adam 的具体公式,只需要了解其思想就行,类似的还有AdaGrad算法,RMSProp算法,Adam算法以及AdaDelta算法,稍微了解即可,不用深究。

4. 解释一下BN,在训练集和测试集上有什么不同

Batch Normalization 出自 15年谷歌发表的论文,主要为了解决深度神经网络调参复杂、优化困难、收敛过程较长的问题,实现方法也很简单:

图片出自论文

考虑到训练过程中,同一个 batch 中的样本差别都可能很大,如果不做归一化的话,每次送入网络训练的数据分布来回波动,不利于模型收敛。

因此,BN 要做的第一件事就是“减均值、除以方差”的归一化操作(对应图片的前三步)。

但对样本做归一化会改变样本的分布,即训练数据和测试数据可能并不符合归一化之后的正态分布,因此图片中的第四步也非常关键,即 scale and shift操作,通过一个线性变换y=scale*x+shift,可以恢复数据的原本分布,从而保证了模型的学习能力。

第二个问题,BN 中的参数。

训练时,我们可以对每一批的训练数据进行归一化,计算每一批数据的均值和方差。

但在测试时,比如进行一个样本的预测,就并没有batch的概念,因此,这个时候用的均值和方差是全量训练数据的均值和方差:使用了 BN 的网络,在训练完成之后,我们会保存全量数据的均值和方差,每个隐层神经元也有对应训练好的Scaling参数和Shift参数。

延伸考点

还知道其他的归一化方法吗?

提示,考察知识面的广度,比如BN、GN、LN、IN一系列的区别, Sync BN等

5. BN的gama labada意义是什么

BN简单来说就是“减均值、除以方差”的归一化操作,但对样本做归一化会改变样本的分布,即训练数据和测试数据可能并不符合归一化之后的正态分布。
因此BN中的gama labada参数,即对应了尺度缩放( scale and shift )操作:通过一个线性变换y=gama*x+labada,可以恢复数据的原本分布,从而保证了模型的学习能力。

延伸考点

训练和测试中, BN 的参数一样吗?

提示:不一样,训练中从数据中计算,测试时使用训练集保存下来的参数

6. 简单介绍一下激活函数有哪些

激活函数是深度学习中很基础,但又非常关键的小组件,其两个特性是:
1. 给模型引入非线性
2. 可导(用于计算梯度、反向传播)

常见的激活函数包括:

序号 激活函数 公式 图像 简介
1 Sigmoid 图片说明 大家熟知的 S 型函数,范围在 [0, 1]
2 tanh 图片说明 可以由 sigmoid 函数变换而来,范围在[-1, 1]
3 ReLU 图片说明 大于 0 的保留,小于 0 的置为 0,斜率为 1,范围在[0, 正无穷]
4 Leaky ReLU 图片说明 针对 relu 做的优化,小于 0 的信息小比例保留(y=ax, a是个小于 1 的常数), 范围在[负无穷,正无穷]
5 PReLU 图片说明 类似于 leaky relu,但y=ax 中的斜率 a 不是固定的常数,而是一个可以学习、调整的参数,提高泛化性
6 ReLU6 图片说明 relu 函数在大于 0 的部分,范围可以到无穷大,但 relu6 做了一个阶段,使结果最大不超过 6(经验值),主要用在嵌入式设备的模型上,如 MobileNet 等

延伸考点

本题很简单,考察深度学习最基本的知识点。
面试官还可能挑一个让你具体介绍,比如写出 sigmoid 的公式、求导公式等等,这些都不难,不能丢分。
还需要了解激活函数的两个特性:给模型引入非线性,可导(用于计算梯度、反向传播)。

7. 请你说说各个激活函数的优缺点,sigmoid relu leakly relu tanh,以及解释下梯度消失

这些都是常见的激活函数,关键作用都是给模型引入非线性。

Sigmoid
优点
Sigmoid 函数的输出范围是 0 到 1,所有可以理解为它对每个神经元的输出进行了归一化,也即有了概率的意义。(很适合分类模型)

缺点

  • 在输出值过大或者过小的情况下,容易梯度消失;
  • 不是以0为中心,导致收敛速度下降;
  • Sigmoid 函数执行指数运算,计算机运行得较慢。

ReLU
优点

  • 当输入为正时,不存在梯度饱和问题。
  • ReLU 函数中只存在线性关系,因此它的计算速度比 sigmoid 和 tanh 更快。
    缺点
  • 如果输入负数,则梯度将完全为零,导致无法反向传播、更新节点,导致该神经元失效。

Tanh
优点
tanh 是一个双曲正切函数,可以由 sigmoid 函数变换而来,优点如下:

  • 值域从[0, 1] 转换成[-1, 1], 以 0 为中心,加快了收敛速度。

关于零中心收敛更快,可以参阅谈谈激活函数以零为中心的问题

可视化做个对比:
图片说明

缺点
跟 sigmoid 类似

  • 在输出值过大或者过小的情况下,容易梯度消失;
  • tanh 函数执行指数运算,计算机运行得较慢。

Leakly ReLU
优点

  • 具有Relu函数的优点
  • 解决了Relu的神经元死亡问题问,在负区域具有小的正斜率,因此即使对于负输入值,它也可以进行反向传播

缺点

  • 斜率需要手动根据经验调整

梯度消失与梯度爆炸
梯度消失与梯度爆炸原理类似,可以一起说。
两种情况下梯度消失经常出现,原因主要是,在比较深的网络中,采用了不合适的损失函数,比如sigmoid,而梯度爆炸一般出现在深层网络和权值初始化值太大的情况下。
通过链式求导法则反向更新梯度的时候,就容易出现这些问题。举个简单的例子,就很容易理解:

图片说明

延伸考点
解决梯度消失或者梯度爆炸的常用思路?
提示,把 sigmoid 激活函数替换成 leaky relu、引入 batch normalization、残差结构、梯度正则化等

8. Sigmoid函数

公式(必须记住)

可视化示例及代码
图片说明

# 可视化 sigmoid 函数代码
import numpy as np
import matplotlib.pyplot as plt


def sigmoid(x):
    return 1. / (1. + np.exp(-x))


def plot_sigmoid():
    x = np.arange(-10, 10, 0.1)
    y = sigmoid(x)
    plt.plot(x, y, label="sigmoid")
    plt.legend()
    plt.title("nowcoder: offer+1")
    plt.show()


def main():
    plot_sigmoid()

if __name__ == '__main__':
    main()

9. Sigmoid求导是什么?

Sigmoid 函数公式
求导过程(结论必须记住)
可视化

def sigmoid(x):
    return 1. / (1. + np.exp(-x))

# 可视化sigmoid 和 它的导数
def plot_sigmoid_and_derivative():
    x = np.arange(-10, 10, 0.1)
    y = sigmoid(x)
    plt.plot(x, y, label="sigmoid")

    y2 = sigmoid(x) * (1 - sigmoid(x))
    plt.plot(x, y2, label="derivative sigmoid")
    plt.legend()
    plt.title("nowcoder: offer+1")
    plt.show()

图片说明

延伸考点
求导是基础的高数知识,sigmoid 函数的公式和导数公式需要熟记。
类似的考点还有交叉熵函数:
其中 n 是训练数据的总数,求和是在所有的训练输⼊ x 上进⾏的, y 是对应的⽬标输出。

10. 请你说说神经网络的过拟合

神经网络参数量巨大,理论上可以拟合任何函数,但正因为神经网络如此强大的学习能力,而现实生活中的数据通常是包含噪声的,这也导致经常出现过拟合的问题:

当模型试着预测噪声较多的数据的趋势时,由于模型参数过多、过于复杂,就会导致过拟合。过拟合的模型通常是不精确的,因为这样的预测趋势并不会反映数据的真实情况。

也就是说,我们训练出的模型在已知的数据(训练集)中有好的预测结果,但在未知的数据(测试集)中表现较差。

下面这个图片可以直观地说明过拟合出现的现象:
图片说明

横坐标是模型复杂度,纵坐标是模型性能,可以看到,随着模型复杂度的增加,训练准确度越来越高(蓝色);然而,在评估集的性能却会先提高再降低。

这就说明模型出现了过拟合:训练集上很准确,但测试集上效果很差,这是需要避免的。

可视化代码

# 演示过拟合
import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 1, 1000)
y1 = -(x - 0.5) ** 2
y2 = y1 - 0.33 + np.exp(x - 1)
fig, ax = plt.subplots()
ax.plot(x, y2, lw=10, alpha=0.5, color='blue')
ax.plot(x, y1, lw=10, alpha=0.5, color='red')
ax.text(0.15, 0.2, "training score", rotation=45, size=16, color='blue')
ax.text(0.2, -0.05, "validation score", rotation=20, size=16, color='red')
ax.text(0.02, 0.1, r'$\longleftarrow$ High Bias', size=18, rotation=90, va='center')
ax.text(0.98, 0.1, r'$\longleftarrow$ High Variance $\longrightarrow$', size=18, rotation=90, ha='right', va='center')
ax.text(0.48, -0.12, 'Best$\\longrightarrow$\nModel', size=18, rotation=90, va='center')
ax.set_xlim(0, 1)
ax.set_ylim(-0.3, 0.5)
ax.set_xlabel(r'model complexity $\longrightarrow$', size=14)
ax.set_ylabel(r'model score $\longrightarrow$', size=14)
ax.xaxis.set_major_formatter(plt.NullFormatter())
ax.yaxis.set_major_formatter(plt.NullFormatter())
ax.set_title("Validation Curve Schematic", size=16)
# fig.savefig('validation-curve.png')
plt.show()

延伸考点
如何避免过拟合?

提示:参见上文《过拟合有哪些,你会从哪方面调节》

11. 用过哪些神经网络?如何调参?

我学习的方向比较多,做了不少项目,比如

  • 最开始是图像分类任务开始学习的,包括 LeNet、AlexNet、VGGNet,再到ResNet等等;
  • 然后是目标检测,包括FasterRCNN、MaskRCNN、Center Net等等;
  • 后面接触了视频动作识别,主要是SlowFast、TSN 等;

调参的时候也不能无章法的乱调,试试这个参数行不行,那个参数行不行,效率太低,调一次要跑很久才能出结果,也不一定能搜到好结果。

比较科学的方法是GridSearch,即网格搜索,在所有候选的参数选择中,通过循环遍历,尝试每一种可能性,表现最好的参数就是最终的结果。其原理就像是在数组里找最大值。

Ps: 为什么叫网格搜索?以有两个参数的模型为例,参数a有3种可能,参数b有4种可能,把所有可能性列出来,可以表示成一个3*4的表格,其中每个cell就是一个网格,循环过程就像是在每个网格里遍历、搜索,所以叫grid search)

下面给出一个示例:

from sklearn.datasets import load_iris 
from sklearn.svm import SVC 
from sklearn.model_selection 
import train_test_split 

# 加载数据
iris = load_iris() 
X_train,X_test,y_train,y_test = train_test_split(iris.data,iris.target,random_state=0) 
print("Size of training set:{} size of testing set:{}".format(X_train.shape[0],X_test.shape[0])) 

# 开始网格搜索
best_score = 0
for gamma in [0.001,0.01,0.1,1,10,100]:
    for C in [0.001,0.01,0.1,1,10,100]:
        svm = SVC(gamma=gamma,C=C) #对于每种参数可能的组合,进行一次训练
        svm.fit(X_train,y_train)
        score = svm.score(X_test,y_test)
        if score > best_score: #找到表现最好的参数
            best_score = score
            best_parameters = {'gamma':gamma,'C':C}

print("Best score:{:.2f}".format(best_score))
print("Best parameters:{}".format(best_parameters))

另外,调参还需要结合具体任务。
比如,我们想用通用目标检测网络 FasterRCNN实现表格单元格的检测,那么就可以针对表格单元格的特点(通常是细长的长条),调整 anchor ratio(即宽高比),提高模型效果。

延伸考点
面试官很可能会让你举个具体例子,遇到了什么问题,怎么解决的。

需要结合你简历项目,给出例子,更有说服力。

12. 卷积神经网络和全连接网络的根本不同之处在哪里

卷积神经网络至少包含一个卷积层,且最后一层通常是全连接层;
全连接网络没有卷积层,只使用全连接层(以及非线性层)。
所以关键是理解卷积层和全连接层的区别。
##全连接层
全连接,顾名思义,上一层的所有神经元要和下一层的每个神经元都链接,比如上一层有 4096 个神经元,下一层有 10 个神经元,那么计算方式如下:

图片说明

所以全连接层有三个特点:

  1. 关注全局信息(每个点都和前后层的所有点链接)
  2. 参数量巨大,计算耗时
  3. 输入维度需要匹配(因为是矩阵运算,维度不一致无法计算)

卷积层
这个卷积和信号系统中的卷积不太一样,其实就是一个简单的乘加运算,比如cs231 课程给出这样一个示例:
图片说明
黄色区域表示卷积的感受野(3x3 大小),黄色区中的红色数字,是该卷积核的参数,黑色数字是图像当前感受野的特征值,那么卷积运算的结果就是:

从这个例子中,我们可以看出卷积层的两个特性:

  1. 局部链接:当前层的神经元只和下一层神经元的局部链接(并不是全连接层的全局链接)
  2. 权重共享:神经元的参数(如上图的 3*3 卷积核),在整个特征图上都是共享的,而不是每个滑动窗口都不同
    图片说明
    也正是因为这两个特性,所以卷积层相比于全连接层有如下优点:
  • 需要学习的参数更少,从而降低了过度拟合的可能性,因为该模型不如完全连接的网络复杂。
  • 只需要考虑中的上下文/共享信息。这个未来在许多应用中非常重要,例如图像、视频、文本和语音处理/挖掘,因为相邻输入(例如像素、帧、单词等)通常携带相关信息。

但需要注意的是,无论是全连接层,还是卷积层,都是线性层,只能拟合线性函数,所以都需要通过ReLU 等引入非线性,以增加模型的表达能力。比如ReLU 函数接受一个输入 x,并返回 {0, x} 的最大值。ReLU(x) = argmax(x, 0)。

延伸考点
需要熟悉卷积层的特性,比如局部连接和权重共享。

13. 说一说关于点云处理以及深度学习的点云语义分割

(1)点云处理
概念:点云(Point Cloud)技术是利用三维激光扫描设备等通过自动化的方式直接或者间接采集物体表面大量点的三维信息,然后输出为特定的存储格式,点云数据是指空间参考系下某一物体在空间中坐标位置以及集合特征、纹理特征等的散乱点集合。
点云数据获取方式:基于视差原理、使用深度相机、利用激光雷达
点云数据存储格式:点云是表示对象或空间的数据集。点的坐标表示原始采样表面上单个点的x,y,z几何坐标。点云是将许多单个空间测量值规整到一个可以表示整体的数据集,常见格式包括:ply、las和pcd等。
点云处理方式:原始点云的处理主要是点云滤波(直通滤波、体素滤波、统计滤波、半径滤波)、点云分割(基于区域生长的分割、最小图割的分割、多视图卷积神经网络分割、3DMAX-Net分割)、点云聚类、点云识别(基于对称函数解决点的无序性问题的PointNet网络、使用卷积对点云数据进行加权排序的PointCNN)以及点云配准,包括传统法和基于深度学习的方法。
(2)点云语义分割
在计算机视觉中,语义分割的任务是分割图像或者点云,区分出不同的分割物。当使用语义分割时,将图像或者点云划分为语义上有意义的部分,然后在语义上将每个部分标记为预定义的类之一。
从点云中学习2D表示以实现快速有效的3D LIDAR语义分割(
IEEE Robotics and Automation Letters .2020): 结合2D和3D学习层的LIDAR语义分割,首先通过滑动框搜索球形投影后的像素点学习2D表示,再从3D数据中抽取局部和全局信息。该表示被输入到一个2D全卷积神经网络(FCNN),可产生2D语义分割。获得的2D语义标签被重新投影回3D空间,最后进行后处理,所有3D点都将基于K近邻(KNN)获得新的语义标签,选择K个最近点的标准不是基于相对的欧式距离,而是基于相对深度值。
图片说明

大规模点云分割RandLA-Net (CVPR 2020):受限于昂贵的采样方法和复杂的处理步骤(点云采样方法计算量大、内存占用高;点云局部特征学习器依赖于图构建,速度慢,感受野不足),导致现有的方案都只能处理小规模尺度的点云分割场景。RandLA-Net采用随机采样算法,并结合局部特征聚合模块,通过逐步增加每个点的感受野来更好的学习和保留大场景点云中复杂的几何结构,最后采用基于attention的点云特征池化方法,获得了更高的池化精度。

图片说明

14. 介绍下pointnet

(1)概念
Pointnet是在2017年由斯坦福的研究人员提出,该网络架构可以用于直接处理原始三维点云数据,可落地与分类、语义分割和目标识别等多种认知任务场景。不同于基于体素的方法或基于多视角图片的方法,pointnet网络不需要对点云数据预处理再使用,可以直接使用原始三维点云数据进行训练,最大程度的保留并利用了原始点云信息。网络结果如下图所示:
图片说明

(2)主要流程

  • 输入为一个全部点云数据的集合,将其表示为一个N*3的2D张量,其中N代表点云数量,3对应( x, y, z)三维坐标
  • 输入的点云数据先和一个由对齐网络T-Net学习到的旋转矩阵相乘,将输入数据旋转到一个适合进行分类/分割的角度,保证了pointnet对物体空间转换的不变性
  • 通过多个MLP卷积层提取各点特征,再用一个特征对齐网络T-Net对提取到的高维特征进行对齐
  • 在特征的各个维度上执行最大池化Max Pooling操作来得到输入点云数据的全局特征
  • 对于分类任务,将全局特征通过MLP来预测最后的分类分数
  • 对于分割任务,将全局特征和之前学习到的各点的特征进行串联,将组合后的特征通过MLP得到各点的分类结果。

(3)算法贡献
Pointnet最主要的贡献是解决了如何在点云数据上直接应用深度学习方法的问题,通过使用对称函数Max Pooling解决了点云数据的无序性问题,同时,通过训练对齐函数来学习点云的旋转,然后对不同角度输入的点云进行空间变换,解决了点云姿态变换的类别不变性问题。基于以上的设计,使得pointnet能够直接处理原始点云数据,为点云数据的分类、分割和目标检测等应用提供了统一的体系结构。

15. 介绍下pointnet++

(1)概念
Pointnet++的提出源于pointnet的缺点:缺失局部特征,从以往的实验来看,pointnet对于场景的分割效果比较一般,因为其网络直接暴力地将所有点最大池化为了一个全局特征,因此局部点与点之间的联系并没有被网络学习到。在分类和物体的局部分割中,这样的问题可以通过中心化物体的坐标轴部分地解决,但在场景分割中,就导致效果十分一般了。
(2)网络结构
Pointnet++采用了分层提取点云特征的策略,把每一个层级的操作叫做一次set abstraction,包括采样、分组和特征提取,首先通过最远点采样法(FPS)在点云上采样一些点,然后以这些点为中心点在某一范围内寻找k个邻近点组成局部子点云,接着对每个子点云使用pointnet进行特征提取和池化操作,继续进行下一个set abstraction,这样每一层采样的中心点都是上一层中心点的子集,随着层数的增加,中心点的个数越来越少,但是点的特征中编码了输入点云从局部到全局的特征信息,克服了pointnet的缺点。

图片说明

(3)分组策略
对于输入点云数据各局部区域密度不同的问题,在固定的邻近范围内选取固定数量的邻近点是不合适的,pointnet++提出两种方案:

  • 多尺度分组,即在分组时对每个中心点都采用多种尺度来确定邻域范围,并把每个尺度下分组得到的点进行特征提取后联接起来,得到一个多尺度的点云特征。因为对于每个中心点都需要进行多次分组和特征提取,所以这个方案的计算成本非常高。
  • 多分辨率分组,该方案每个分组区域的布局点云特征都是由两部分联接得到的,第一部分是上一层通过set abstraction操作后得到的特征,第二部分是直接对当前局部区域包含的所有原始点云数据中的点进行特征提取得到的特征,避免了多尺度分组中计算成本高的问题,并且可以根据当前局部区域点的密度来给与两部分特征不同的权重。

16. 你了解多模态处理吗?

多模态信息处理是在文本、图像、音频等现有单媒体信息处理的基础上发展起来的,现有单媒体数据的处理方法是多模态数据处理的基础。如在特征提取层面,针对文本、图像、音频等单模态数据,往往直接利用成熟的特征提取方法。多模态信息处理特有的研究内容主要关注于多模态信息的建模、获取、融合、语义度量等方面。
多模态信息建模:
构建一个单模态的分类体系,在该分类体系中,各单模态类别之间满足完整性、正交性、关联性和直观性的要求。
多模态数据构建:
对于多模态处理而言,对象数据需要特殊处理才能获得,途径包括数据的采集、解析、数据集构建。采集,社交媒体可以通过智能终端;针对车联网,可以通过车载传感器;针对监控网,可以采集红外、震动等。
多模态数据的解析就是将原始混合状态的多模态数据,分解为单模态数据,例如视频数据分解为动态图像、音频语言、文本语言等三种单模态数据。
多模态语义分析:
指的是在同一个媒体对象的多个模态数据上,同时并行或协同进行语义分析,并最终通过融合得到分析结果的语义分析方法。
多模态信息检索:
一种是对多媒体数据不同模态的语义关系进行统一建模,以实现跨媒体检索;另一种是利用共生或共现的多模态信息作为语义桥梁,来实现跨媒体检索(后者为典型的多模态信息检索,前者为跨模态信息检索)。

17. 目前有大量调参侠,对此有什么看法

由来:当前很多做人工智能方向的工程师,被戏称为“调参侠”,指的是日常工作当中并没有对于领域相关的问题本身进行复杂的设计或重构,只是基于现有开源库或者现成模型进行参数调优看结果。
参数究竟是什么:
(1)模型参数,由模型通过训练学习得到的变量,比如权重w和偏置b,这部分通常不可调,由模型自己学习获得。
(2)超参数,模型训练之前设置的参数,常见的有学习率,迭代次数,隐藏层数量,每层神经单元个数等等。通常情况需要对超参数进行调试,以期望提高学习的性能和效果。
问题所在:
(1)多半是刚入门的算法工程师做的事情,不是很懂神经网络结构、数据分布等,只能通过调整超参数,获得好的结果;
(2)目前有非常多的开源模型,并附带了预训练参数,如常用的检测、分割、分类等,这些方法大部分直接调用即可,然后根据自己的训练数据稍加修改。工作中只要结果,不要求创新,所以大多数调参即可。
如何改进和提升(避免成为或脱离该问题):
不需要刻意带给开发者不必要的压力,因为该问题可以算是技术成长的必经之路,先成为调包侠,然后在工程应用中借解决实际问题的机会深入学习,了解始末,逐步建立完善的知识网络,提升自己。
大公司或学者在设计各种库和模型的时候往往遵循一定的设计理念,而藉由这些设计理念使用这些工具往往能够帮助少走很多弯路,具体的库或者包的集合往往是为了解决某个问额提或者某个系统性的问题存在的,在实际应用的过程中,会观察到问题冒出来和被解决的过程,遇到真正没有被框架和包解决的问题才是真正学习和成长的机会。

18. 请你说说Attention Model

人类视觉系统可以有选择地将注意力集中在较为显著的区域,以更好地捕捉时空间语意结构。注意力机制不仅能告诉人们何时何地关注,还能提高关注区域的表现力。
自然语言处理领域(NLP)最先引入被称为self-attention的注意力机制《Attention is all you need》 ,通过transformer模块捕捉长距离依赖特征,取得很大进展。随后注意力机制也在图像修复、超分辨率、风格迁移等计算机视觉领域得到广泛应用,常用的策略包括空间注意力、通道注意力等。
视频动作识别领域同样受益于该机制,主要可以分为spatial-wise和channel-wise两种模式。其中空间注意力模块以Non-Local为代表,主要关注不同位置特征的关系,捕获两个不同空间位置、时间位置的依赖关系。
通道级别的注意力,目的是增强最有用的通道的响应,削弱影响较小的通道的响应。考虑到直接进行对时空两个特征图进行拼接有些唐突(忽视了2D与3D之间信息的不同和相互关系)研究人员于是设计了一个新型的channel fusion和attention mechanism,来强调通道内部的相互关系,同时实现channel fuse 和 attention,即引入了通道融合和注意力机制。
对于计算机视觉领域任务,我们也可以通过Grad-CAM 等方法将注意力图可视化出来,如图所示
图片说明
左边是原图,右边可视化的注意力图,颜色越深的地方,表示模型越关注的地方。

代码示例
下面给出了两个常用的注意力模块的代码实现

# 通道注意力
class ChannelAttention(nn.Module):
    def __init__(self,channel,reduction=16):
        super().__init__()
        self.maxpool=nn.AdaptiveMaxPool2d(1)
        self.avgpool=nn.AdaptiveAvgPool2d(1)
        self.se=nn.Sequential(
            nn.Conv2d(channel,channel//reduction,1,bias=False),
            nn.ReLU(),
            nn.Conv2d(channel//reduction,channel,1,bias=False)
        )
        self.sigmoid=nn.Sigmoid()

    def forward(self, x) :
        max_result=self.maxpool(x)
        avg_result=self.avgpool(x)
        max_out=self.se(max_result)
        avg_out=self.se(avg_result)
        output=self.sigmoid(max_out+avg_out)
        return output

# 空间注意力
class SpatialAttention(nn.Module):
    def __init__(self,kernel_size=7):
        super().__init__()
        self.conv=nn.Conv2d(2,1,kernel_size=kernel_size,padding=kernel_size//2)
        self.sigmoid=nn.Sigmoid()

    def forward(self, x) :
        max_result,_=torch.max(x,dim=1,keepdim=True)
        avg_result=torch.mean(x,dim=1,keepdim=True)
        result=torch.cat([max_result,avg_result],1)
        output=self.conv(result)
        output=self.sigmoid(output)
        return output

延伸考点

你知道哪些注意力模型?

提示:self-attention, non-local, cbam等等

19. 当你选择模型考虑哪些因素

  1. 首先是保证模型效果,选择学术界广受认可的新模型;
  2. 然后是计算量,因为在实际部署的时候,我们需要考虑端上模型和云上模型不同的计算条件,需要在保证准确率的前提下,尽可能减少计算量、内存占用等开销;
  3. 后续再想办法继续优化,尝试最新的 plugins、各种技巧等。

20. 你用tensorflow做过什么?

大三的时候开始接触的深度学习,那时候主流的框架是 caffe,TensorFlow 刚刚出 0.x 的版本。
做本科毕设的时候,用的就是 TensorFlow,实现了移动机器人的地形图像分类问题:

  1. 采集水泥地、柏油路、沙地、水面、草地等 10 中地形图像,制作 6万张左右的数据集
  2. 使用 TensorFlow,参照lenet,设计了 5 层卷积池化的特征提取网络,已经两层全连接层的分类 head
  3. 最终分类准确率达到 99.6%
    提示:以上回答按照自己的项目或接触来回答
全部评论

相关推荐

被加薪的哈里很优秀:应该继续招人,不会给你留岗位的
点赞 评论 收藏
分享
喜欢飞来飞去的雪碧在刷代码:可以试一试字节
点赞 评论 收藏
分享
评论
点赞
3
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务