Skip to content

Latest commit

 

History

History
649 lines (331 loc) · 37.4 KB

面经.md

File metadata and controls

649 lines (331 loc) · 37.4 KB

算法题

  1. 什么是二叉树?

  2. 二叉排序树的时间复杂度是多少?

  3. 那三叉排序树、四叉排序树的时间复杂度呢?

  4. 数据结构中,什么是平衡二叉树?

  5. 平衡二叉树的应用都有哪些?

  6. 说一下B树和B+树的区别

  7. 数据结构中查找最快的算法是哪个?

  8. 分别说一下在数据量比较大的情况下最快的查找算法,和数据量比较小的情况下最快的查找算法。

  9. map的底层实现?红黑树

  10. 快排如何防止由于数组有序而带来的退化?

  11. 线段树?介绍了原理

  12. 查找HashMap中的一个数据的时间复杂度是多少?查找TreeMap中的一个数据的时间复杂度是多少?

  13. 给你一个很大的文件,文件里有很多行数据,每一行数据是一个用户的uid,表示这个用户点开过抖音,请你找出打开抖音次数最频繁的前10个用户。

面试官接着解释题目:假如抖音里面有5亿用户,那么每个用户打开一次抖音就有5亿条记录,如果每个用户打开两次抖音,就有10亿条记录。也就是说,用户每打开一次抖音,就记录一下他的uid。请找出打开抖音次数最频繁的前10个用户。

  1. 二分查找的时间复杂度是多少?

  2. 实现sqrt

  3. 两个栈实现队列

  4. 一个句子的逆序输出,I am a boy? boy a am I?

  5. 现在有一亿个样本,你如何找到单词最相似的?

  6. 假设现在有一万个数据,每个数据被取到的概率是不同的,1/2,1/3,1/100,现在如果是你,你会怎么取这一批数据?,数据有好有坏

  7. 十进制转2进制的最优化算法?

  8. two sum 有序数组

  9. 链表怎么判断有没有环,

  10. 无线长的数据流,找到第N时刻的第K大的数字

  11. 代码:连续子数组的最大和。

  12. 一个正整数组成的数组,分成连续的M段,问每段的数之和的最大值最小是多少?

例如:a=[10,6,2,7,3],M=2,答案为16,两段分为[10,6][2,7,3]。

  1. 给你一个无序数组,找出数组中的一个数,使得在数组中,这个数之前的所有数字之和等于这个数之后所有数字之和。

  2. 给你两个无序数组M、N,输出两个数组中和最大的前K个数。在求和时,一个数来自M、另一个数来自N。

  3. 给定一行字符串,求出这行字符串中出现频率最高的字符,字符串中含有标点符号,字符不区分大小写。如果出现频率相同时,输出先出现在字符串中的字符。(AC100%)

  4. 给你一个字符串,以这个字符串中字符出现的频率为权重,构造这个字符串的哈夫曼编码。(AC100%)

  5. 第一轮技术冒泡排序、二分查找

  6. 给定无序的数组,求出 连续相邻的子数组中最小值乘以长度 使得值最大的连续数组

  7. 输出二叉树每一行最左边的元素

  8. 二维直角坐标系上,给定N个点的坐标(float型),一个点C的坐标(float型),一个整数M。问:找一个正方形,它以C点为中心,且四条边分别与x轴和y轴平行,其内部至少包含N个点中的M个点(在边上也算),问这样的正方形边长最小是多少?

  9. 镜像二叉树 ......

  10. 滑动窗口

  11. 一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。(这道题我之前做过,面试的时候写了三种解法:递归、记忆化递归和动态规划,然后给面试官讲了一下每种解法的思路)

  12. 输入一个整型数组,数组里面有正数也有负数。数组中一个或连续的多个整数组成一个子数组。求所有子数组的和的最大值。

  13. 有一个单向链表,链表当中有可能出现“环”。如何用程序判断出这个链表是有环链表

  14. 给定一个整形数组,其中的第i个元素代表股票第i天的价格。在一开始,你手里有足够的钱,但没有股票。你仅有一次买股票和一次卖股票的机会(每次只能买/卖1股),或者不买不卖。输出你可能的最大盈利值。尽量降低程序的时间复杂度。

  15. 给定一个一维数组,将其中为0的元素删除掉,非零元素的相对位置保持不变,最终目标数组保留在原数组中,并且目标数组长度之外的元素全部置为0。(手写这个代码的时候,面试官还稍微表扬了一下我,说我代码写的很好!)

  16. 复杂链表复制。

  17. 给出两个升序数组A、B和长度m、n,求第k个大的

  18. 给出数组A,长度为n,数组中元素的值位于[0, n - 1]之间,求是否有重复元素

  19. 数组a,先单调地址再单调递减,输出数组中不同元素个数。

要求:O(1)空间复杂度,不能改变原数组

机器学习

大数据工具:

Hadoop、Spark 、ElasticSearch

归纳偏好

机器学习算法在学习过程中对某种类型假设的偏好,称为“归纳偏好”,或简称为“偏好”。

目标函数,损失函数,代价函数

目标函数是最终需要优化的函数,其中包括经验损失和结构损失。

$$obj=loss+Ω$$

经验损失(loss)就是传说中的损失函数或者代价函数。结构损失(Ω)就是正则项之类的来控制模型复杂程度的函数。

K均值算法中,初始类中心怎么确定(聚类算法,聚类怎么确定K值)

  1. 随机选择K个样本作为类中心,将样本随机划分成K个子集然后计算类中心

  2. 选择彼此距离尽可能远的K个点 :首先随机选择一个点作为第一个初始类簇中心点,然后选择距离该点最远的那个点作为第二个初始类簇中心点,然后再选择距离前两个点的最短距离最大的那个点作为第三个初始类簇的中心点,以此类推,直至选出K个初始类簇中心点。

  3. 先对数据用层次聚类算法或者Canopy算法进行聚类,得到K个簇之后,从每个类簇中选择一个点,该点可以是该类簇的中心点,或者是距离类簇中心点最近的那个点。

Kmeans和EM有什么关系,和GMM有什么关系?

k-means算法和GMM算法的E过程都是先固定模型参数然后对样本分类,M过程都是根据E过程中每个样本对应好的类,更新模型参数。

讲解一下线性回归的底层原理,比如说如何训练,如何得到参数,如何调整参数等?

真实样本和预测样本有误差,误差满足高斯分布(数据量大,中心极限定理),然后求最大似然函数,得到最小二乘法,对损失函数进行优化得到最优的W,和b。

说一下LR和SVM的区别,要详细,LR和数据分布有没有关系?

  1. LR是参数模型,SVM是非参数模型。

  2. 从目标函数来看,区别在于逻辑回归采用的是logistical loss,SVM采用的是hinge loss,这两个损失函数的目的都是增加对分类影响较大的数据点的权重,减少与分类关系较小的数据点的权重。

  3. 逻辑回归相对来说模型更简单,好理解,特别是大规模线性分类时比较方便。而SVM的理解和优化相对来说复杂一些,SVM转化为对偶问题后,分类只需要计算与少数几个支持向量的距离,这个在进行复杂核函数计算时优势很明显,能够大大简化模型和计算。

  4. SVM不直接依赖数据分布,而LR则依赖,因为SVM只与支持向量那几个点有关系,而LR和所有点都有关系。

  5. SVM依赖penalty系数,实验中需要做CV

  6. SVM本身是结构风险最小化模型,而LR是经验风险最小化模型

LR为什么要离散特征?

  1. 稀疏向量内积乘法运算速度快,计算结果方便存储,容易scalable(扩展)。

  2. 离散化后的特征对异常数据有很强的鲁棒性:比如一个特征是年龄>30是1,否则0。如果特征没有离散化,一个异常数据“年龄300岁”会给模型造成很大的干扰。

  3. 逻辑回归属于广义线性模型,表达能力受限;单变量离散化为N个后,每个变量有单独的权重,相当于为模型引入了非线性,能够提升模型表达能力,加大拟合。

  4. 离散化后可以进行特征交叉,由M+N个变量变为M*N个变量,进一步引入非线性,提升表达能力。

  5. 特征离散化后,模型会更稳定,比如如果对用户年龄离散化,20-30作为一个区间,不会因为一个用户年龄长了一岁就变成一个完全不同的人。当然处于区间相邻处的样本会刚好相反,所以怎么划分区间是门学问。

李沐少帅指出,模型是使用离散特征还是连续特征,其实是一个“海量离散特征+简单模型” 同 “少量连续特征+复杂模型”的权衡。既可以离散化用线性模型,也可以用连续特征加深度学习。就看是喜欢折腾特征还是折腾模型了。通常来说,前者容易,而且可以n个人一起并行做,有成功经验;后者目前看很赞,能走多远还须拭目以待。

大概的理解:

1)计算简单

2)简化模型

3)增强模型的泛化能力,不易受噪声的影响

线性回归为什么用均方差

  1. 它简单。

  2. 它提供了具有很好性质的相似度的度量。例如:

    1)它是非负的;

    2)唯一确定性。只有 x=y 的时候,d(x,y)=0;

    3)它是对称的,即 d(x,y)=d(y,x);

    4)符合三角性质。即 d(x,z)<=d(x,y)+d(y,z).

  3. 物理性质明确,在不同的表示域变换后特性不变,例如帕萨瓦尔等式。

  4. 便于计算。通常所推导得到的问题是凸问题,具有对称性,可导性。通常具有解析解,此外便于通过迭代的方式求解。

  5. 和统计和估计理论具有关联。在某些假设下,统计意义上是最优的。

解决GBDT过拟合

  1. 控制树的棵数,即迭代次数M

  2. 控制shrink,Empirically it has been found that using small learning rates (such as ) yields dramatic improvements in model’s generalization ability over gradient boosting without shrinking ().

  3. 随机采样迭代。类bagging方法。经验来说随机采样率f在0.5<=f<=0.8比较合适。即可以帮助避免过拟合又可以提高训练速度。

  4. 控制叶子节点中的最少样本个数。

  5. 惩罚树的复杂性(复杂性定义为叶子数占树所有节点的比例),用一个后验剪枝算法来对loss和树的复杂度进行联合优化,该方法为去掉那些降低loss幅度小于指定阈值的分支。

  6. 加入正则,譬如特征的正向正则或者负向正则(譬如,在分裂的时候,除了满足最小平方差之外,要保证左子树的lable平均值小于右子树的lable平均值,反之为负向正则)

为什么梯度提升方法倾向于选择决策树(通常是CART树)作为基学习器呢?

  1. 这与决策树算法自身的优点有很大的关系。决策树可以认为是if-then规则的集合,易于理解,可解释性强,预测速度快。

  2. 决策树算法相比于其他的算法需要更少的特征工程,比如可以不用做特征标准化,可以很好的处理字段缺失的数据,也可以不用关心特征间是否相互依赖等。决策树能够自动组合多个特征,它可以毫无压力地处理特征间的交互关系并且是非参数化的,因此你不必担心异常值或者数据是否线性可分

  3. 单独使用决策树算法时,有容易过拟合缺点。所幸的是,通过各种方法,抑制决策树的复杂性,降低单颗决策树的拟合能力,再通过梯度提升的方法集成多个决策树,最终能够很好的解决过拟合的问题。由此可见,梯度提升方法和决策树学习算法可以互相取长补短,是一对完美的搭档。

xgboost为什么用二阶导

xgboost使用了一阶和二阶偏导, 二阶导数有利于梯度下降的更快更准. 使用泰勒展开取得函数做自变量的二阶导数形式, 可以在不选定损失函数具体形式的情况下, 仅仅依靠输入数据的值就可以进行叶子分裂优化计算, 本质上也就把损失函数的选取和模型算法优化/参数选择分开了. 这种去耦合增加了xgboost的适用性, 使得它按需选取损失函数, 可以用于分类, 也可以用于回归。

无监督学习中存在过拟合吗?

存在。我们可以使用无监督学习的某些指标或人为地去评估模型性能,以此来判断是否过拟合。

随机梯度下降法,在每次迭代时能保证目标函数值一定下降吗?为什么?

不能,每次迭代时目标函数不一样

梯度下降法,为什么需要设置一个学习率?

梯度只是方向,学习率是步长

使得迭代之后的值在上次值的邻域内,保证可以忽略泰勒展开中的二次及二次以上的项

解释梯度下降法中动量项的作用

利用之前迭代时的梯度值,减小震荡

用梯度下降训练神经网络的参数,为什么参数有时会被训练为nan值?

输入数据本身存在nan值,或者梯度爆炸了(可以降低学习率、或者设置梯度的阈值)

利用梯度下降法训练神经网络,发现模型loss不变,可能有哪些问题?怎么解决?

很有可能是梯度消失了,它表示神经网络迭代更新时,有些权值不更新的现象。改变激活函数,改变权值的初始化等。

多标签分类怎么解决,从损失函数角度考虑

多标签分类 sigmoid函数 二分类交叉熵损失函数(binary_crossentropy)

零样本分类问题。如果测试时出现一个图片是训练时没有的类别,怎么做

zero-shot learning(零样本学习)的一个重要理论基础就是利用高维语义特征代替样本的低维特征,使得训练出来的模型具有迁移性 。

PCA和LDA有什么异同?

从过程来看,他们有着很大的相似性,最后其实都是求某一个矩阵的特征值,投影矩阵即为该特征值对应的特征向量。但是其原理的不同如下:

  1. PCA为非监督降维,LDA为有监督降维

  2. PCA希望投影后的数据方差尽可能的大(最大可分性),因为其假设方差越多,则所包含的信息越多;而LDA则希望投影后相同类别的组内方差小,而组间方差大。LDA能合理运用标签信息,使得投影后的维度具有判别性,不同类别的数据尽可能的分开。

  3. LDA降维最低可以降维到(类别数-1),而PCA没有限制

  4. LDA还可以进行分类

什么是k折交叉验证?

将原始数据集划分为k个子集,将其中一个子集作为验证集,其余k-1个子集作为训练集,如此训练和验证一轮称为一次交叉验证。交叉验证重复k次,每个子集都做一次验证集,得到k个模型,加权平均k个模型的结果作为评估整体模型的依据。

关于k折交叉验证,需要注意什么?

k越大,不一定效果越好,而且越大的k会加大训练时间;在选择k时,需要考虑最小化数据集之间的方差,比如对于2分类任务,采用2折交叉验证,即将原始数据集对半分,若此时训练集中都是A类别,验证集中都是B类别,则交叉验证效果会非常差。

需要用归一化的模型有哪些

线性回归、logistic回归、KNN、SVM、神经网络等模型。但树形模型不需要归一化,因为它们不关心变量的值,而是关心变量的分布和变量之间的条件概率,

对于一个二分类问题,我们定义超过阈值t的判定为正例,否则判定为负例。现在若将t增大,则准确率和召回率会如何变化?

准确率 = TP / (TP + FP),召回率 = TP / (TP + FN),其中TP表示将正例正确分类为正例的数量,FP表示将负例错误分类为正例的数量,FN表示将正例错误分类为负例的数量。

准确率可以理解为在所有分类为正例的样品中,分类正确的样本所占比例;召回率可以理解为在所有原始数据集中的正例样品中,正确挑出的正例样本的比例。

因此若增大阈值t,更多不确定(分类概率较小)的样本将会被分为负例,剩余确定(分类概率较大)的样本所占比例将会增大(或不变),即正确率会增大(或不变);若增大阈值t,则可能将部分不确定(分类概率较小)的正例样品误分类为负例,即召回率会减小(或不变)。

泰勒展开公式在机器学习、深度学习中都有哪些应用?

利用泰勒级数让熵近似转化为基尼指数 xgboot 梯度下降

计算机视觉

残差网络为什么能做到很深层?

神经网络在反向传播过程中要不断地传播梯度,而当网络层数加深时,梯度在逐层传播过程中会逐渐衰减,导致无法对前面网络层的权重进行有效的调整。残差网络中,加入了short connections,为梯度带来了一个直接向前面层的传播通道,缓解了梯度的减小问题。

解决小物体检测有哪些思路?

Oversampling Augmentation 特征融合 利用上下文信息,或者目标之间建立联系 提升图像分辨率

擅长的深度学习框架,tensorflow原理,keras和它的区别,Pytorch

  1. pytorch是一个动态的框架,而TensorFlow是一个静态的框架。

何为静态的框架呢?

我们需要先构建一个TensorFlow的计算图,构建好了之后,这样一个计算图是不能够变的了,再传入不同的数据进去,进行计算。

keras简单来讲是tensorflow的再封装,keras底层可以选tensorflow,易用,但灵活性不高。

两种框架都在张量上运行,把任何模型都看作一个有向非循环图(DAG),但对于如何定义它们,PyTorch 和 TensorFlow 区别很大。

TensorFlow 遵循“数据即是代码,代码就是数据”的理念。在 TensorFlow 中,在跑模型之前会静态的定义图形。和外界的所有联系都是通过 tf.Session 对象和 tf.Placeholder,它们都是会在模型运行被外部数据取代的张量。

在 PyTorch 中,会更动态一些:你可以随着进展定义、更改和执行节点,没有特殊的会话界面或占位符。整体来看,PyTorch 和 Python 结合的更紧凑些,多数时候会感觉更原生。而在 TensorFlow 里写东西时,有时你会觉得你的模型好像躲在一堵墙后面一样,就通过墙上的几个洞洞跟你交流。当然了,这也看每个人的喜好和品味。

不过,不单单是在软件工程方面有区别,一些动态神经网络架构可以从这种动态方法种受益。回想一下循环神经网络:有静态图形,输入序列长度会保持不变。这意味着如果你开发一个应用于英语句子的情绪分析模型,就必须将序列长度修正为某些最大值,用 0 填补所有较小的序列。这比较麻烦吧。在递归循环神经网络和树形循环神经网络方面,你会遇到更多问题。

目前,TensorFlow 对于动态输入的支持比较有限,而 PyTorch 则是默认的支持动态输入。

  1. 调试

由于 PyTorch 的计算图是在运行时定义,因此可以用 pdb,ipdb,PyCharm 这些 Python 调试工具或者以前的可靠的打印语句也行。

TensorFlow 则不同,你可以选择用一个叫 tfdbg 的特殊工具,它能让你在运行时评估 TensorFlow 表达式,浏览所有张量,在会话范围中操作。当然,无法用它调试 Python 代码,因此无需单独使用 pdb。

  1. 可视化

在可视化方面,TensorFlow 的 Tensorboard 是个非常棒的功能。它内置在 TensorFlow 中,在调试和比较不同的训练状况时非常有用。例如,假设你训练了一个模型,然后调整一些超参数后又训练一次。而在 Tensorboard 上可以将这两次模型运行状况同时展现出来,从而看出两次的差异。Tensorboard 可以:

展示模型图形

绘制标量变量

可视化分布和直方图

可视化图形

播放音频

Tensorboard 可以展示多种总结,通过 tf.summary 模块就可以收集到。我们可以为前面的指数例子定义总结操作,用 tf.summary.FileWriter 将它们保存到桌面。

执行 tensorboard --logdir=./tensorboard 就可启动 Tensorboard。由于它是 web 应用,因此可以很方便的用在云实例上。

目前 PyTorch 并没有可以和 Tensorboard 匹敌的工具,不过倒是存在一些集成功能。虽然也能用一些绘图工具比如 matplotlib 和 seaborn,但在可视化这方面,PyTorch 要逊于 TensorFlow。

  1. 部署

在部署这方面,TensorFlow 很明显目前略胜一筹:其内置框架 TensorFlow Serving 能让你在特制的 gPRC 服务器上部署你的模型。也同样支持移动端。

在 PyTorch 上,我们就需要用 Flask 或其它工具在模型上编写一个 REST API。在使用 TensorFlow 的时候,如果 gPRC 不是很适用,我们同样可以这么做。不过,如果考虑性能的话,TensorFlow Serving 会是更好的选择。

TensorFlow 同样支持分布式训练,这点 PyTorch 目前尚不具备。

  1. 数据并行

PyTorch 不同于 TensorFlow 的最大特性之一就是声明式数据并行:你可以用 torch.nn.DataParellel 封装任何模型,而且模型能在批处理维度上实现并行。这样你就可以毫不费力的使用多个 GPU。

另一方面,TensorFlow 能让你调试在具体设备上运行的所有操作。不过,数据并行不仅需要手动调整,还需要深思熟虑。我们看看在 TensorFlow 中实现数据并行的代码:

def make_parallel(fn, num_gpus, **kwargs):
    in_splits = {}
    for k, v in kwargs.items():
        in_splits[k] = tf.split(v, num_gpus)
out_split = []
    for i in range(num_gpus):
        with tf.device(tf.DeviceSpec(device_type="GPU", device_index=i)):
            with tf.variable_scope(tf.get_variable_scope(), reuse=tf.AUTO_REUSE):
                out_split.append(fn(**{k : v[i] for k, v in in_splits.items()}))
return tf.concat(out_split, axis=0)
def model(a, b):
    return a + b
c = make_parallel(model, 2, a=a, b=b)

我们可以看到,用 TensorFlow 也能实现用 PyTorch 做到的所有操作,但是要麻烦的多(不过相应会有更多的控制权)。

此外值得一提的是,两个框架都支持分布式执行,提供用于定义集群的高水平界面。

  1. 一个更像框架,一个更像库

我们搭建一个分类手写数字的 CNN 分类器。PyTorch 开始会看起来很像一个框架。回想一下,编程框架会在特定领域为我们提供有用的抽象,用它们可以很方便的解决具体问题。而这是框架和库的的本质区别之处。

这里我们引入 datasets 模块,它包含的封装器适用于众多用于基准测试深度学习架构的常见数据集。此外,nn.Module 用于搭建自定义 CNN 分类器,就好比 PyTorch 中的程序块(building block),能让我们创建复杂的深度学习架构。在 torch.nn 包中有很多现成可用的模块,可以作为我们模型的基础。PyTorch 用面向对象的方法来定义基本的程序块,在通过子类化拓展功能的同时,也给了我们一些“通道”继续前行。

相比之下,TensorFlow 给人的感觉更像是一个库,而非一个框架:所有的操作都为低阶操作,你需要写很多样板代码,即便你可能并不想写(比如,一遍又一遍的定义方差和权重···)。随着时间推移,也渐渐出现了一批围绕 TensorFlow 的高级封装器,都是为了简化我们使用 TensorFlow 的方式。它们大部分目前都在 tensorflow.contrib 模块中(很多人并不将它看做一个稳定的 API),有些也迁移到了主库中(见 tf.layers)。

所以,你在如何使用 TensorFlow 上有很大的自由度,同样也能自由选择使用最匹配任务的框架:TFLearn,tf.contrib.learn,Sonnet,Keras,plain tf.layers 等等。说实话,仅 Keras 这一个框架,就能单独写一篇文章讨论。不过这已超出本文讨论范围,暂且不表。

因此,TensorFlow 和 PyTorch 都能提供有用的抽象,减少样板代码的数量,加快模型的部署速度。这两者的主要不同之处是 PyTorch 感觉更有“Python 味”一些,采用面向对象的方法,而 TensorFlow 有多种供你选择的选项。

简单的介绍一下CNN,及它的发展和应用?好处是什么?CNN为什么对图像work的特别好?

宏观解释 首先从宏观的角度理解CNN为什么work?

从统计角度:卷积抓住了问题的局部相关性和空间不变性 从正则化的角度:由于权值共享,降低了模型参数数量,控制了模型复杂度 从神经科学角度:卷积神经网络受生物视觉系统的启发 局部相关性 CNN不仅应用于图像领域,同时应用于语音和自然语言处理领域,这些数据的共同特点是具有局部相关性。什么是局部相关性?具体来说,图像是由一个个像素点组成,每个像素点与其周围的像素点是有关联的,如果把像素点打乱,图片会完全变掉,语音和自然语言也是同理,我们不能随意打乱这些数据,因为它们都具有局部相关性。

空间不变性 CNN浅层网络提取低层次的特征,比如边缘,曲线等,随着网络深度加深,低层次的特征经过组合组成高层次的特征,并且能够保持特征的空间不变性。

强大的非线性拟合能力,结构化数据操作。

为什么现在倾向于用小尺寸的卷积核?

用多个小卷积核串联可以有大卷积核同样的能力,而且参数更少,另外有更多次的激活函数作用,增强非线性

1x1卷积有什么用途?

通道降维,保证卷积神经网络可以接受任何尺寸的输入数据

卷积神经网络为什么会具有平移等不变性?**

MaxPooling能保证卷积神经网络在一定范围内平移特征能得到同样的激励,具有平移不变形。

介绍deeplabv3,画出backbone,它与其他state of art的模型对比,deeplab的亮点是什么,你认为deeplab还可以做哪些改进?deeplabv3的损失函数

我答了并联更好,串联会产生Griding Efect。

如何避免Griding Efect

将dilation rate设计成锯齿结构, 如 [1, 2, 5, 1, 2, 5] 循环结构.

CRF后处理的目的

利用crf修饰分割所得的图像边缘

深度学习中batch size的大小对训练过程的影响是什么样的?

batch size过小,花费时间多,同时梯度震荡严重,不利于收敛;batch size过大,不同batch的梯度方向没有任何变化,容易陷入局部极小值。(有些时候不可避免地要用超大batch,比如人脸识别,可能每个batch要有几万甚至几十万张人脸图像,训练过程中超大batch有什么优缺点,如何尽可能地避免超大batch带来的负面影响?

在不考虑Batch Normalization的情况下(这种情况我们之后会在bn的文章里专门探讨),先给个自己当时回答的答案吧(相对来说学究一点):

(1) 不考虑bn的情况下,batch size的大小决定了深度学习训练过程中的完成每个epoch所需的时间和每次迭代(iteration)之间梯度的平滑程度。(感谢评论区的韩飞同学提醒,batchsize只能说影响完成每个epoch所需要的时间,决定也算不上吧。根本原因还是CPU,GPU算力吧。瓶颈如果在CPU,例如随机数据增强,batch size越大有时候计算的越慢。)

对于一个大小为N的训练集,如果每个epoch中mini-batch的采样方法采用最常规的N个样本每个都采样一次,设mini-batch大小为b,那么每个epoch所需的迭代次数(正向+反向), 因此完成每个epoch所需的时间大致也随着迭代次数的增加而增加。

由于目前主流深度学习框架处理mini-batch的反向传播时,默认都是先将每个mini-batch中每个instance得到的loss平均化之后再反求梯度,也就是说每次反向传播的梯度是对mini-batch中每个instance的梯度平均之后的结果,所以b的大小决定了相邻迭代之间的梯度平滑程度,b太小,相邻mini-batch间的差异相对过大,那么相邻两次迭代的梯度震荡情况会比较严重,不利于收敛;b越大,相邻mini-batch间的差异相对越小,虽然梯度震荡情况会比较小,一定程度上利于模型收敛,但如果b极端大,相邻mini-batch间的差异过小,相邻两个mini-batch的梯度没有区别了,整个训练过程就是沿着一个方向蹭蹭蹭往下走,很容易陷入到局部最小值出不来。

)

(2)(存疑,只是突发奇想)如果硬件资源允许,想要追求训练速度使用超大batch,可以采用一次正向+多次反向的方法,避免模型陷入局部最小值。即使用超大epoch做正向传播,在反向传播的时候,分批次做多次反向转播,比如将一个batch size为64的batch,一次正向传播得到结果,instance级别求loss(先不平均),得到64个loss结果;反向传播的过程中,分四次进行反向传播,每次取16个instance的loss求平均,然后进行反向传播,这样可以做到在节约一定的训练时间,利用起硬件资源的优势的情况下,避免模型训练陷入局部最小值。

设计了什么网络结构?为什么用Densenet?关键问题有可能涉及到Densenet的缺点,你有做过改进吗,还能不能研究这个网络?

为什么Densenet会比resnet要好?resnet不好在哪里?Densenet不好在哪里,吃显存嘛?(这个问题我没有回答好,因为在实际运用中,没有关注过显存过载的情况,实际是非常耗费显存的)

你有没有想过可以先将crop patch后然后用原图去分割预测?(就是分割网络使用256*256的patch大小,预测的时候用512*512)斩钉截铁的回答,不行,虽然原因我没有回答的到点上,因为感受野和语义的提取层次不一样。实际是如果放大会有很多的锯齿存在。然后又说了stacking Unet的方法

解释GoogLeNet的Inception模块的原理

对输入图像用多个不同尺寸的卷积核、池化操作进行同时处理,然后将输出结果按照通道拼接起来

如何提高小型网络的精度?

(1)模型蒸馏技术(https://arxiv.org/abs/1503.02531)

(2)利用AutoML进行网络结构的优化,可将网络计算复杂度作为约束条件之一,得到更优的结构。(https://arxiv.org/abs/1807.11626)

卷积神经网络中im2col是如何实现的?

使用im2col的方法将划窗卷积转为两个大的矩阵相乘

对于多分类问题,为什么神经网络一般使用交叉熵而不用欧氏距离损失?

神经网络中如果预测值与实际值的误差越大,那么在反向传播训练的过程中,各种参数调整的幅度就要更大,从而使训练更快收敛,如果预测值与实际值的误差小,各种参数调整的幅度就要小,从而减少震荡。 使用平方误差损失函数,误差增大参数的梯度会增大,但是当误差很大时,参数的梯度就会又减小了。 使用交叉熵损失是函数,误差越大参数的梯度也越大,能够快速收敛。

$$ \frac{e^x_i}{e^x_i} $$ 有指数存在,这个直接等于0了 而交叉熵因为有log,所以不会存在这个问题

什么是鞍点问题?

梯度为0,Hessian矩阵不定的点,不是极值点

贝叶斯搜索

通过不断地添加样本点来更新目标函数的后验分布(高斯过程,直到后验分布基本贴合于真实分布。简单的说,就是考虑了上一次参数的信息,从而更好的调整当前的参数。

贝叶斯优化与常规的网格搜索或者随机搜索的区别是:

  1. 贝叶斯调参采用高斯过程,考虑之前的参数信息,不断地更新先验;网格搜索未考虑之前的参数信息。

  2. 贝叶斯调参迭代次数少,速度快;网格搜索速度慢,参数多时易导致维度爆炸。

  3. 贝叶斯调参针对非凸问题依然稳健;网格搜索针对非凸问题易得到局部优最。

传统图像算法

分水岭算法

图像的灰度空间很像地球表面的整个地理结构,每个像素的灰度值代表高度。其中的灰度值较大的像素连成的线可以看做山脊,也就是分水岭。其中的水就是用于二值化的gray threshold level,二值化阈值可以理解为水平面,比水平面低的区域会被淹没,刚开始用水填充每个孤立的山谷(局部最小值)。

当水平面上升到一定高度时,水就会溢出当前山谷,可以通过在分水岭上修大坝,从而避免两个山谷的水汇集,这样图像就被分成2个像素集,一个是被水淹没的山谷像素集,一个是分水岭线像素集。最终这些大坝形成的线就对整个图像进行了分区,实现对图像的分割。

把梯度图像中的所有像素按照灰度值进行分类,并设定一个测地距离阈值。

找到灰度值最小的像素点(默认标记为灰度值最低点),让threshold从最小值开始增长,这些点为起始点。

水平面在增长的过程中,会碰到周围的邻域像素,测量这些像素到起始点(灰度值最低点)的测地距离,如果小于设定阈值,则将这些像素淹没,否则在这些像素上设置大坝,这样就对这些邻域像素进行了分类。

随着水平面越来越高,会设置更多更高的大坝,直到灰度值的最大值,所有区域都在分水岭线上相遇,这些大坝就对整个图像像素的进行了分区。

Laplacian算子

Laplacian算子其实就是使用二阶微分的算子,更通俗来说就是梯度的散度。

二阶微分:

$$\nabla^{2} f=\frac{\partial^{2} f}{\partial x^{2}}+\frac{\partial^{2} f}{\partial y^{2}}$$

$$\begin{array}{l} \frac{\partial^{2} f}{\partial x^{2}}=f(x, y+1)-2 f(x, y)+f(x, y-1) \\ \frac{\partial^{2} f}{\partial y^{2}}=f(x+1, y)-2 f(x, y)+f(x-1, y) \end{array}$$

然后带入卷积模板:

$$\nabla^{2} f \approx\left(\begin{array}{ccc} 0 & 1 & 0 \\ 1 & -4 & 1 \\ 0 & 1 & 0 \end{array}\right)$$

由于Laplacian算子法对噪声比较敏感,所以很少用该算子检测边缘,而是用来判断边缘像素视为与图像的明区还是暗区。拉普拉斯高斯算子是一种二阶导数算子,将在边缘处产生一个陡峭的零交叉, Laplacian算子是各向同性的,能对任何走向的界线和线条进行锐化,无方向性。这是拉普拉斯算子区别于其他算法的最大优点。

sobel算子

$$s_{x}=\left[\begin{array}{ccc} -1 & 0 & 1 \\ -2 & 0 & 2 \\ -1 & 0 & 1 \end{array}\right], s_{y}=\left[\begin{array}{ccc} 1 & 2 & 1 \\ 0 & 0 & 0 \\ -1 & -2 & -1 \end{array}\right]$$

Canny算子

canny算子的计算步骤如下:

1.高斯滤波器平滑图像。去除噪声

2.一阶差分偏导计算梯度值和方向。通过sobel算子计算的。

3.对梯度值不是极大值的地方进行抑制。把不是极值的点,全部置0,去掉了大部分弱的边缘。所以图像边缘会变细。

4.用双阈值连接图上的联通点。设置双阈值 t1, t2, 是这样的,t1 <= t2 大于 t2 的点肯定是边缘;小于 t1 的点肯定不是边缘;在 t1, t2 之间的点,通过已确定的边缘点,发起8领域方向的搜索(广搜),图中可达的是边缘,不可达的点不是边缘。最后得出 canny 边缘图。
  1. 好的检测 --算法能够尽可能多地标示出图像中的实际边缘

  2. 好的定位 --标识出的边缘要与实际图像中的实际边缘尽可能接近

  3. 最小响应 --图像中的边缘只能标识一次,并且可能存在的图像噪声不应该标识为边缘

photoshop里面抠图是什么原理?怎么实现的

ps通道抠图的原理是是每一个通道中对应的颜色比例都是用黑白灰进行显示的。当通道图像显示为黑色时,那么这个通道对应的颜色比例为0,也就是完全没有当前通道的颜色。

当通道图像显示为白色时,那么这个通道对应的颜色比例为100%;中间的都是不同级别的灰度值,对应不同的通道颜色占比。

自己项目问题

项目中这么做的创新点为什么有效?日常你还做过哪些问题驱动的创新?

在训练深度神经网络的过程中,遇到过哪些问题,怎么解决的?

不收敛,收敛太慢,泛化能力差。调整网络结构,调整样本,调整学习率,调整参数初始化策略

对于自己的论文可以这么讲:

1)之前别人是怎么做这个领域的。

2)别人做这个领域达到的精度和方法的缺点。

3)你做的这个模型和别人做的模型有什么差别。(这里重点讲一下自己的创新点。)

4)你达到了一个怎么样的精度,效果如何。

5)论文是自己的亮点,面试官感兴趣,应该仔细讲讲的。

6)其次,论文里面用到的细节,一定要非常清楚并能讲清楚,并且讲论文的时候,要有铺垫。

红外图像特点:

热红外图像是灰度图像,没有色彩或阴影,图像分辨率低,图像缺乏层次感;

由于景物热平衡、传输距离和大气衰减等原因,造成热红外图像空间相关性强、对比度低、视觉效果模糊;

外界环境的随机干扰和红外成像系统的不完善,给热红外图像带来多种多样的噪声,这些分布复杂的噪声使得热红外图像的信噪比低不利于后续环节如图像融合、目标识别的处理。

热红外图像中普遍存在着目标边缘轮廓模糊,背景对比度差等缺点,如果红外传感器较远,再加之受大气恶劣条件的影响,此时获得的热红外图像信噪比和对比度将更低,图像质量很差