bytedance 面筋集合
z

提前批的,面试拖了好久,今天刚面完交叉面,虽然还没有意向书,也先发下面经,回馈下牛友

面的是上海的ailab

一面

1、上来直接问论文,他基本上没有问啥细节,主要是我在讲

2、一道算法题

稀疏向量的点乘 要求:尽量高效地实现,需要同时考虑时空复杂度。

代码是当时写的,不一定bug free

1
`#include <iostream>``using` `namespace` `std;``struct` `Node{``    ``int` `index;``    ``int` `value;``};` `int` `func(Node[] v1, Node[] v2){``    ``int` `p1 = 0, p2 = 0;``    ``int` `ret = 0;``    ``int` `len1 = ``sizeof``(v1) / ``sizeof``(Node);``    ``int` `len2 = ``sizeof``(v2) / ``sizeof``(Node);``    ``while``(p1<len1 && p2<len2){``        ``int` `index1 = v1[p1].index, index2 = v2[p2].index;``        ``if``(index1 == index2){``            ``ret += v1[p1].value * v2[p2].value;``            ``p1++;``            ``p2++;``        ``}``else` `if` `(index1 < index2){``            ``p1++;``        ``}``else``{``            ``p2++;``        ``}``    ``}``    ``return` `ret;``}` `int` `main() {``    ``cout << ``"Hello World!"` `<< endl;``}`

二面

1、先问项目的一些细节

2、深度学些基础

smoothL1
$$
\operatorname{smooth}{L{1}}(x)=\left{\begin{array}{ll}{0.5 x^{2}} & {\text { if }|x|<1} \ {|x|-0.5} & {\text { otherwise }}\end{array}\right.
$$

  • 相比于L1损失函数,可以收敛得更快。
  • 相比于L2损失函数,对离群点、异常值不敏感,梯度变化相对更小,训练时不容易跑飞。

image-20190829165140414

image-20190829165206975

fpn的结构

特征金字塔是处理多尺度物体检测问题的一个基础组成部分。然而,最近基于深度学习的物体检测算法考虑到计算量和内存限制都尽量避免采用特征金字塔的方式。在这篇文章中,利用深度卷积网络本身固有的多尺度、层次结构来构造特征金字塔,它的好处是只会带来极小的额外消耗。具体的,本文构造了一种自顶向下、带有侧向连接的层次结构来构建各个尺度的高层语义特征。这种方法称之为Feature Pyramid Network (FPN)。FPN可以作为一种通用的特征提取器,并且在多个任务上带来了显著的性能提升。将FPN应用于Faster RCNN,在COCO上达到了最佳的单模型性能。另外,FPN的推理速度在GPU上可以达到5FPS,因此是一种检测性能高,同时推理速度能达到实际使用的方法。

image-20190829170208782

roi pooling和roi align的区别

image-20190829201728367

image-20190829201749609

image-20190829201835211
image-20190829201857655

3、数据结构基础

链表判断是否有环

归并排序描述

二叉排序树时间复杂度

如果二叉排序树是平衡的,则n个节点的二叉排序树的高度为Log2n+1,其查找效率为O(Log2n),近似于折半查找。如果二叉排序树完全不平衡,则其深度可达到n,查找效率为O(n),退化为顺序查找。一般的,二叉排序树的查找性能在O(Log2n)到O(n)之间。因此,为了获得较好的查找性能,就要构造一棵平衡的二叉排序树。

4、算法题

leetcode958 判断是否是完全二叉树

三面

1、问比赛,主要是我在介绍

2、介绍下cascade rcnn

3、算法题

leetcode3 最长不重复子串

交叉面

1、论文讲下,没有提问题

2、RPN介绍一下

![image-20190829204113463](/Users/xiongz/Library/Application Support/typora-user-images/image-20190829204113463.png)

![image-20190829204039728](/Users/xiongz/Library/Application Support/typora-user-images/image-20190829204039728.png)

3、inception介绍一下

4、depthwise 卷积

5、shufflenet


image-20190829135948996


  • 对分类,分割检测,视频理解哪方面比较熟悉?

答:对分类,分割比较熟悉

  • 那我们问一下检测方面的问题吧(我:???),你了解faster rcnn吗,大致介绍一下

  • 再问一个分割检测方面的,了解nms吗,大致介绍一下

  • 同一个人可能有好几个框(每一个框都带有一个分类器得分)

    image-20190830090937922

    而我们的目标是一个人只保留一个最优的框:

    于是我们就要用到非极大值抑制,来抑制那些冗余的框: 抑制的过程是一个迭代-遍历-消除的过程。

    (1)将所有框的得分排序,选中最高分及其对应的框:

    image-20190830091004665

    (2)遍历其余的框,如果和当前最高分框的重叠面积(IOU)大于一定阈值,我们就将框删除。

    image-20190830091023734

    (3)从未处理的框中继续选一个得分最高的,重复上述过程。

    image-20190830091042736

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    import numpy as np

    def py_cpu_nms(dets, thresh):
    """Pure Python NMS baseline."""
    x1 = dets[:, 0]
    y1 = dets[:, 1]
    x2 = dets[:, 2]
    y2 = dets[:, 3]
    scores = dets[:, 4]

    areas = (x2 - x1 + 1) * (y2 - y1 + 1)
    order = scores.argsort()[::-1]

    keep = []
    while order.size > 0:
    i = order[0]
    keep.append(i)
    xx1 = np.maximum(x1[i], x1[order[1:]])
    yy1 = np.maximum(y1[i], y1[order[1:]])
    xx2 = np.minimum(x2[i], x2[order[1:]])
    yy2 = np.minimum(y2[i], y2[order[1:]])

    w = np.maximum(0.0, xx2 - xx1 + 1)
    h = np.maximum(0.0, yy2 - yy1 + 1)
    inter = w * h
    ovr = inter / (areas[i] + areas[order[1:]] - inter)

    inds = np.where(ovr <= thresh)[0]
    order = order[inds + 1]

    return keep
  • 模型训练过拟合怎么办

  1. 数据角度: 数据增强、增大数据量
  2. 模型角度:换简单的网络,更换backbone,添加dropout,添加BN
  3. 损失角度:添加正则项、加大正则项的权重
  • BN为什么防止过拟合呢?

大概意思是:在训练中,BN的使用使得一个mini-batch中的所有样本都被关联在了一起,因此网络不会从某一个训练样本中生成确定的结果。

意思就是同样一个样本的输出不再仅仅取决于样本本身,也取决于跟这个样本属于同一个mini-batch的其它样本。同一个样本跟不同的样本组成一个mini-batch,它们的输出是不同的(仅限于训练阶段,在inference阶段是没有这种情况的)。我把这个理解成一种数据增强:同样一个样本在超平面上被拉扯,每次拉扯的方向的大小均有不同。不同于数据增强的是,这种拉扯是贯穿数据流过神经网络的整个过程的,意味着神经网络每一层的输入都被数据增强处理了。

但是我回答的是BN为啥work的原因

包括BN原论文解释的改善ICS现象,但是今年年初MIT的一篇论文《How Does Batch Normalizetion Help Optimization》推翻了这个结论,该论文认为

  1. BN带来的性能提升与ICS的减少无关。 并且在一定程度上认为BN并不能减少 ICS。
  2. 发现了BN使得优化问题的曲面更加平滑,这使得梯度更容易预测以及允许更大范围的学习率和更快的网络vonvergence。证明了BN提升了模型的LOSS的Lipschitzness和梯度的Lipschitzness(β-smoothness)。换个说法:引入了 BN 后,损失函数相对于激活函数值的梯度幅值更小,也即损失函数更加利普希兹。损失函数相对于激活函数值的二阶项幅值更小,也即损失函数更加贝塔平滑。同理,损失函数相对于权重的梯度幅值也更小。 权重的最优解与初始解的距离也更小,也即神经网络更快就可以训练到最佳表现。(参考:https://www.zhihu.com/collection/226366658?page=4)
  3. 提出了除了BN外,还有其他方式同样可以达到类似平滑效应,有些甚至效果更好。

算法题:判断一棵树是不是完全二叉树

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#File Name : 是否为完全二叉树.py
class Node(object):
def __init__(self,val=None):
self.val = val
self.left = None
self.right = None

def isCBT(head):
if not head:
return True
isLeaf = False
queue = [head]
while queue:
head = queue.pop(0)
left = head.left
right = head.right
if (not left and right) or (isLeaf and (left or right)):
# (not left) and right 右边存在 左边不存在
# 或者是进入到全是叶节点状态后 有左或者右
# 这两种情况都会返回F
return False
if left:
queue.append(left)
if right:
queue.append(right)
if not left or not right:
isLeaf = True
return True

问:AI lab业务偏多还是research偏多 面试官说:都会做,比较好的一点就是公司大中台战略,本身公司的业务场景就很多,所以有很多落地的工作可以做

问:AI lab的扩招情况,发展态势?AI lab的规模?

  • 你投的哪个城市,我是目前在上海工作,如果你有兴趣的话可以到上海来

二面 视频面(60min)2019/7/17

自我介绍

实习的工作是如何改进的

为什么不用L1而用L2loss监督

sobel算子介绍一下

sobel核的参数为什么里面-1 -2,改变了参数后会发生什么事情?

面试官本身是想让我回答不同的参数就能实现不同的功能效果,例如高斯模糊,腐蚀,锐化,膨胀等等

讲一下Focal loss,它解决了一个什么东西?如何解决的?

解决正负样本不均衡的问题:

Focal Loss:

在onestage的网络中,正负样本达到1:1000,这就会出现两个问题:1.样本不平衡 2.负样本主导loss。虽然负样本的loss小(因为大量的负样本是easy example,大量负样本是准确率很高的第0类),但个数众多,加起来的loss甚至大于了正样本的loss
$$
\mathrm{FL}\left(p_{\mathrm{t}}\right)=-\alpha_{\mathrm{t}}\left(1-p_{\mathrm{t}}\right)^{\gamma} \log \left(p_{\mathrm{t}}\right)
$$

focal loss先解决了样本不平衡的问题,即在CE上加权重,当class为1的时候,乘以权重$\alpha$,当class为0的时候,乘以权重$1-\alpha$,这是最基本的解决样本不平衡的方法,也就是在loss计算时乘以权重。注意下面的图:$\alpha$下面有个坐标t,也就是说$\alpha$针对不同类别,值并不一样

实际上就是在CE前加了一个$(1-p_t)^\gamma$,也就是说,如果你的准确率越高,$\gamma$ 次方的值越小,整个loss的值也就越小。也就是说,$\gamma $ 次方就是用来衰减的,准确率越高的样本衰减越多,越低的衰减的越少,这样整个loss就是由准确率较低的样本主导了。对于onestage的网络,loss由负样本主导,但这些负样本大多是准确率很高的,经过focal loss后就变成了正负样本共同主导,或者说是概率低的主导。这一点和ohem很像,ohem是让loss大的进行训练。

OHEM:

image-20190830100938528

从图中可以看出,本文的亮点在于在每次迭代中,较少训练样本下,如何hard negative mining,来提升效果。即针对Fast-RCNN框架,在每次minibatch(1张或者2张)训练时加入在线筛选hard region的策略,达到新的SoA。需要注意的是,这个OHEM适合于batch size(images)较少,但每张image的examples很多的情况。(thousands of candidate examples,这里的example可以理解为instance、region或者proposal) 这是一次ML经典算法bootstrapping在DL中的完美“嵌入”。

具体来说:

1 将Fast RCNN分成两个components:ConvNet和RoINet. ConvNet为共享的底层卷积层,RoINet为RoI Pooling后的层,包括全连接层;

2 对于每张输入图像,经前向传播,用ConvNet获得feature maps(这里为RoI Pooling层的输入);

3 将事先计算好的proposals,经RoI Pooling层投影到feature maps上,获取固定的特征输出作为全连接层的输入;需要注意的是,论文说,为了减少显存以及后向传播的时间,这里的RoINet是有两个的,它们共享权重,RoINet1是只读(只进行forward),RoINet2进行forward和backward:
a 将原图的所有props扔到RoINet1,计算它们的loss(这里有两个loss:cls和det);
b 根据loss从高到低排序,以及利用NMS,来选出前K个props(K由论文里的N和B参数决定)
为什么要用NMS? 显然对于那些高度overlap的props经RoI的投影后,
其在feature maps上的位置和大小是差不多一样的,容易导致loss double counting问题
c 将选出的K个props(可以理解成hard examples)扔到RoINet2,
这时的RoINet2和Fast RCNN的RoINet一样,计算K个props的loss,并回传梯度/残差给ConvNet,来更新整个网络
论文提及到可以用一种简单的方式来完成hard mining:
在原有的Fast-RCNN里的loss layer里面对所有的props计算其loss,根据loss对其进行排序,(这里可以选用NMS),选出K个hard examples(即props),反向传播时,只对这K个props的梯度/残差回传,而其他的props的梯度/残差设为0即可。由于这样做,容易导致显存显著增加,迭代时间增加,这对显卡容量少的童鞋来说,简直是噩梦。
为什么说是online?
论文的任务是region-based object detection,其examples是对props来说的,即使每次迭代的图像数为1,它的props还是会很多,即使hard mining后
为什么要hard mining:
1 减少fg和bg的ratio,而且不需要人为设计这个ratio;
2 加速收敛,减少显存需要这些硬件的条件依赖;
3 hard mining已经证实了是一种booststrapping的方式, 尤其当数据集较大而且较难的时候;
4 eliminates several heuristics and hyperparameters in common use by automatically selecting hard examples, thus simplifying training。
放宽了定义negative example的bg_lo threshold,即从[0.1, 0.5)变化到[0, 0.5)。
取消了正负样本在mini-batch里的ratio(原Fast-RCNN的ratio为1:3)?

  • 和难例挖掘OHEM有什么区别

3:1是负样本比上正样本

img

  • 讲一下你熟悉的优化器,说一下区别或发展史

答:只简单讲了adam和SGD,没复习到

具体参考https://www.cnblogs.com/ljygoodgoodstudydaydayup/p/7294671.html

  • 算法题:一个整数数组A,求Ai-Aj的最大值Max,i<j,

c++的解法及思路: https://blog.csdn.net/fkyyly/article/details/83930343

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def f(arr):
if len(arr)==0 or len(arr)==1:
return 0
if len(arr)==2:
return arr[0]-arr[1]
p1 = 0
p2 = 1
max = arr[p1]-arr[p2]
n = len(arr)
while p2<n:
while p2<n and arr[p2]<arr[p1]:
if arr[p1]-arr[p2]>max:
max = arr[p1]-arr[p2]
p2 += 1

p1 = p2
p2 += 1
return max
  • 时间复杂度空间复杂度是多少

答:O(n),O(1)

  • 一个图片中心逆时针旋转30度后,求最小外接矩形长和宽,说一下有哪些解决方法

答:第一种初中数学,几何知识;第二种,求解仿射变换矩阵(2x3),然后和原图相乘,就得到变换后的图片,也就知道了最小外接矩形的长和宽

具体参考https://blog.csdn.net/flyyufenfei/article/details/80208361

  • 有什么想问的

问:这个提前批的面试流程,有几面

答:至少三面,没面过的不影响正式秋招

问:老师您在公司做的什么方面呢

答:广告方面的图像,cv-ad

三面 主管面 视频面 (30min)2019/7/23

  • 自我介绍

  • 介绍一下简历上比赛经历

  • 介绍一下简历上最有含金量的工作

  • 1x1卷积的作用

    用来降维或者升维 (GoogLeNet、mobileNet)

    增加非线性

  • 经典分类网络backbone

  • 讲一下inception系列

  • 经典分割网络

  • 没有提问环节(感觉凉了呀)


编程题:

1.非递减数组中查询某个目标值出现个数。解法:二分查找左右边界。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
def find(nums, target):
if not nums:
return 0
left = 0
right = len(nums)-1
while left < right:
mid = (left+right)//2
if nums[mid] >= target:
right = mid
else
left = mid+1
if right == 0 and nums[0] != target:
return 0
a = left

left, right = 0, len(nums)-1
while left < right:
mid = (left+right+1)//2
if nums[mid] <= target:
left = mid
else:
right = mid-1
return left-a+1

2.leetcode 124 二叉树最大路径和

1
2
3
4
5
6
7
8
9
10
11
def maxpath(root):
def h(root):
if not root:
return 0
left = h(root.left)
right = h(root.right)
self.ans = max(self.ans, root.val+left+right)
return max(0, root.val + max(left, right))
self.ans = -float('inf')
h(root)
return self.ans

概率题:一个圆上三个点,组成锐角三角形概率。现场没算出来。

1/4

  1. 逻辑回归是什么?sigmoid的作用是什么?解释最大似然。先验概率与后验概率。

    对于回归问题,可以使用一个线性回归模型来做$y = wx+b$,对于分类问题,就可以用一个函数将事数值的 $y$ 转换成成离散值1/0。sigmoid函数就可以实现将其转换为一个概率数值。
    $$
    sigmoid(z) = \frac{1}{1+e^{-z}}
    $$

    $$
    p(Y=1|x) = \frac{1}{1+e^{-wx+b}} \
    p(Y=0|x) = 1 - p(Y=1|x)
    $$

    最大似然估计

    模型的参数是未知的,但是是客观存在的一个定值。MLE是通过采样来估计概率分布参数的方法。

    假设有训练集合D,$D_c$ 是这个训练集合中的c个样本组成的集合。那么参数$\theta_c$对于数据集合$D_c$ 的似然是

    $P(D_c|\theta_c) = \Pi_{x\in D_c} P(x|\theta_c)$

    简单的来讲,极大似然估计就是在所有的$\theta$中找到使得所有可能出现的值出现的可能性最大。

    先验

    $p(c|x)$

    $p(c)$ 先验

    $p(x|c)$ 后验概率

  2. 决策树分裂节点的标准与对应的算法。gbdt的gb是什么意思,如何体现。bagging与boosting的区别。gbdt里如何知道每个特征的重要性。

    ID3 –> 信息增益

    C4.5 –> 信息增益比

    GB 梯度提升

    GBDT(Gradient Boosting Decison Tree)中的树都是回归树,GBDT用来做回归预测,调整后也可以用于分类(设定阈值,大于阈值为正例,反之为负例),可以发现多种有区分性的特征以及特征组合。GBDT是把所有树的结论累加起来做最终结论的,GBDT的核心就在于,每一棵树学的是之前所有树结论和的残差(负梯度),这个残差就是一个加预测值后能得真实值的累加量。比如A的真实年龄是18岁,但第一棵树的预测年龄是12岁,差了6岁,即残差为6岁。那么在第二棵树里我们把A的年龄设为6岁去学习,如果第二棵树真的能把A分到6岁的叶子节点,那累加两棵树的结论就是A的真实年龄;如果第二棵树的结论是5岁,则A仍然存在1岁的残差,第三棵树里A的年龄就变成1岁,继续学。 Boosting的最大好处在于,每一步的残差计算其实变相地增大了分错instance的权重,而已经分对的instance则都趋向于0。这样后面的树就能越来越专注那些前面被分错的instance。

    缺点:Boost是一个串行过程,不好并行化,而且计算复杂度高,同时不太适合高维稀疏特征

    image-20190830162016665

    取样方式(样本权重)

    Bagging是均匀选取,样本的权重相等

    Boosting根据错误率取样,错误率越大则权重越大

    Bagging随机选择训练集,训练集之间相互独立

    Boosting的各轮训练集的选择与前面各轮的学习结果有关

    Bagging各个预测函数没有权重,可以并行生成,

    Boosting有权重,顺序生成

    Bagging是减少variance

    Boosting是减少bias

    Bagging 是 Bootstrap Aggregating的简称,意思就是再取样 (Bootstrap) 然后在每个样本上训练出来的模型取平均,所以是降低模型的 variance.
    Boosting 则是迭代算法,每一次迭代都根据上一次迭代的预测结果对样本进行加权,所以随着迭代不不断进行,误差会越来越小,所以模型的 bias 会不不断降低。这种算法无法并行。

  3. 为什么svm的loss不能直接用梯度下降要用对偶?说说你知道的优化算法。

    核技巧应用到支持向量机,其基本想法就是通过一个非线性变换将输入空间

    (欧氏空间 R n 或离散集合)对应于一个特征空间(希尔伯特空间  ),使得在输 入空间 R n 中的超曲面模型对应于特征空间  中的超平面模型(支持向量机).这 样,分类问题的学习任务通过在特征空间中求解线性支持向量机就可以完成

    核函数K(x,z)给定的条件下,可以利用解线性分类问题的方法 求解非线性分类问题的支持向量机.学习是隐式地在特征空间进行的,不需要显 式地定义特征空间和映射函数.这样的技巧称为核技巧,它是巧妙地利用线性分 类学习方法与核函数解决非线性问题的技术.在实际应用中,往往依赖领域知识 直接选择核函数,核函数选择的有效性需要通过实验验证

  4. 优化方法

    1、梯度下降法

    梯度下降法是最早最简单的,也是最为常用的最优化算法。梯度下降法实现简单,当目标函数是凸函数时,梯度下降法的解是全局解。一般情况下,其解不保证是全局最优解,梯度下降法的速度未必是最快的。梯度下降法的优化思想是用当前位置负梯度方向作为搜索方向,因为该方向为当前位置的最快下降方向,所以也被称为“最速下降法”。最速下降法越接近目标值,步长越小,前进越慢。

    在机器学习中,基于基本的梯度下降法发展了两种梯度下降方法,分别为随即梯度下降法和批量梯度下降法。

    批量梯度下降:最小化所有训练样本的损失函数,使得最终求解的是全局的最优解,即求解的参数是使得风险函数最小,但是对于大规模样本问题效率低下。

    随机梯度下降法:最小化每条样本的损失函数,虽然不是每次迭代得到的损失函数都向着全局最优方向,但是大的整体的方向是向着全局最优解,最终的结果往往是在全局最优解附近,使用于大规模训练样本情况。

    2、牛顿和拟牛顿法

    从本质上去看,牛顿法是二阶收敛,梯度下降是一阶收敛,所以牛顿法更快。如果更通俗得到说的话,比如你想找一条最短的路径走到一个盆地的最底部,梯度下降法每次只从你当前的位置选一个坡度最大的方向走一步,牛牛顿法在选择方向时,不仅会考虑坡度是否足够大,还会考虑你走了一步之后,坡度是否会变得更大。所以,可以说是牛顿法比梯度下降法看的更远一点,能更快地走到最底部。

    优点:二阶收敛,收敛速度更快;

    缺点:牛顿法是一种迭代算法,每一步都需要求解目标函数的hessian矩阵的逆矩阵,计算比较复杂。

    拟牛顿法

    拟牛顿法的基本思想是改善牛顿法每次需要求解复杂的Hessian矩阵的逆矩阵的缺点,它使用正定矩阵来近似Hessian矩阵的逆,从而简化了运算的复杂度。拟牛顿法和最速下降法一样只要每一步迭代时知道目标函数的梯度。通过测量梯度的变化,构造一个目标函数的模型使之足以产生超线性收敛性。这类方法大大优与最速下降法,尤其对于困难的问题,另外,因为拟牛顿法不需要二阶倒数的信息,所以有时比牛顿法更为有效。如今,优化软件中包含了大量的拟牛顿算法用来解决无约束,约束,和大规模的优化问题。

    3、共轭梯度法

    共轭梯度法是介于最速下降法与牛顿法之间的一个方法,它仅需利用一阶导数信息,但克服了最速下降法收敛慢的缺点,又避免了牛顿法需要存储和计算Hesse矩阵并求逆的缺点,共轭梯度法不仅是解决大型线性方程组最有用的方法之一,也是解决大型非线性最优化最有效的算法之一。在各种优化算法中,共轭梯度法是非常重要的一种。其优点是所需存储量小,具有步收敛性,稳定性高,而且不需要任何外来参数。

    4、启发式优化方法

    启发式方法是指人在解决优化问题时所采取的一种根据经验规则进行发现的方法。其特点是在解决问题时,利用过去的经验,选择已经行之有效的方法,而不是系统地、以确定的步骤去寻求答案。启发式优化方法种类繁多,包括经典的模拟退火方法,遗传算法、蚁群算法以及粒子群算法等等。

    还有一种特殊的优化算法被称之多目标优化算法,它主要针对同时优化多个目标(两个及两个以上)的优化问题,这方面比较经典的算法有NSGAII算法、MOEA/D算法以及人工免疫算法等。

    5、EM算法

    EM算法是一类算法的总称。EM算法分为E-step和M-step两步。EM算法的应用范围很广,基本机器学习需要迭代优化参数的模型在优化时都可以使用EM算法。

    EM算法的思想和过程

    E-step:E的全称是Exception,即期望的意思。E-step也是获取期望的过程。根据现有的模型,计算各个观测数据输入到模型中的结果。这个过程称为期望值计算过程,即E过程。

    M-step:M的全称是Maximization,即最大化的意思。M-step也是期望最大化的过程。得到一轮期望值以后,重新计算模型参数,以最大化期望值。这个过程为最大化过程,即M过程。

    最大化的意思是我们在使用这个模型时希望我们定义的函数能使得到的结果最大化,而结果越大越接近我们希望得到的结果。我们优化的目标也就是这些能得到最大值的函数。

    常见的EM算法有:隐含马尔科夫模型的训练方法Baum-Welch算法;最大熵模型的训练方法GIS算法等。

    EM算法结果

    EM算法不一定能保证获得全局最优解,但如果我们优化的目标函数是一个凸函数,那么一定能保证得到全局最优解。否则可能获得局部最优解。因为如果优化的目标函数有多个峰值点,则如果优化到某个不是最高的峰值点处,则会无法再继续下去,这样获得的是局部最优解。

    总结

    EM算法只需要输入一些训练数据,同时定义一个最大化函数,接下来经过若干次迭代,就可以蓄念出我们需要的模型了

  5. PCA和LDA的区别

    https://www.jianshu.com/p/982c8f6760de

    PCA**

    总结一下,我们就可以梳理出整一个PCA降维的流程,归纳如下,
    (1)样本去中心化
    (2)计算样本的协方差矩阵$XX^{T}$
    (3)对协方差矩阵做特征值分解
    (4)取最大的$d’$ 个特征值所对应的特征向量
    (5)计算投影矩阵

    LDA

    从降维的层面考虑,其也是在寻找一个投影矩阵,使得投影之后数据样本,同类的接近,而不同类的远离。

    LDA的中心思想就是最大化类间距离以及最小化类内距离

    image-20190830160519429

    总结一下,我们就可以梳理出整一个LDA用于降维的流程,归纳如下,
    (1)计算每个类别的均值$\mu_i$,全局样本均值$\mu$
    (2)计算类内散度矩阵$S_w$,全局散度矩阵$S_t$,类间散度矩阵$S_b$
    (3)对矩阵$S_w^{-1}S_b$做特征值分解
    (4)取最大的$d^{‘}$个特征值所对应的特征向量
    (5)计算投影矩阵

    比较

    1. PCA为非监督降维,LDA为有监督降维
    2. PCA希望投影后的数据方差尽可能的大(最大可分性),因为其假设方差越多,则所包含的信息越多;而LDA则希望投影后相同类别的组内方差小,而组间方差大。LDA能合理运用标签信息,使得投影后的维度具有判别性,不同类别的数据尽可能的分开。
    3. 举个简单的例子,在语音识别领域,如果单纯用PCA降维,则可能功能仅仅是过滤掉了噪声,还是无法很好的区别人声,但如果有标签识别,用LDA进行降维,则降维后的数据会使得每个人的声音都具有可分性,同样的原理也适用于脸部特征识别。所以,可以归纳总结为有标签就尽可能的利用标签的数据(LDA),而对于纯粹的非监督任务,则还是得用PCA进行数据降维。

二面:

编程题:正则表达式匹配。剑指offer和leetcode都有。

.可以匹配任意个前面的字符

+可以匹配任意一个字符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def isMatch(s, p):
dp = [[False] * (len(s)+1) for _ in range(len(p)+1)]
dp[0][0] = True

for i in range(1, len(p)+1):
if p[i-1] == '*' and dp[i-2][0]:
dp[i] = True

for i in range(len(p)+1):
for j in range(len(s)+1):
if p[i-1] == s[j-1] or p[i-1] == '.':
dp[i][j] = dp[i-1][j-1]
elif p[i-1] == '*':
if p[i-2] == '.' or p[i-2] == s[j-1]:
dp[i][j] = dp[i-2][j] or dp[i-1][j-1] or dp[i][j-1]
else:
dp[i][j] = dp[i-2][j]
return dp[-1][-1]

概率题:真硬币m个,假币n个。假币只有正面。真币投掷正面概率为p。其中某硬币投掷k次都是正面,求它为真币概率。

知识点:

1.pooling是什么,有哪些作用。

2.梯度爆炸与消失产生原理与解决方法。

3.解决过拟合的方法有哪些。

4.输入特征归一化有哪些方式,有什么好处。svm需不需要?决策树需不需要?

1,避免训练得到的模型权重过小,引起数值计算不稳定;

2,使参数优化时能以较快的速度收敛.

归一化时可以采用对应维度均值与方差.

5.1x1卷积的作用。

1x1 卷积在图像处理的角度,乍一看好像没什么意义,但在 CNN 网络中,能实现降维,减少 weights 参数数量,能够实现升维,来拓宽 feature maps,在不改变 feature maps 的 size 的前提下,实现各通道之间的线性组合,实际上是通道像素之间的线性组合,后接非线性的激活函数,增加更多样的非线性特征。这就是为什么 GoogLeNet 用 1x1 卷积来降维,减少了计算量,但模型效果却没有降低,此外网络深度更深。可以说 1x1 卷积很 nice.

6.什么是特征向量与特征值。怎么理解它们代表的意义。

image-20190901003535332

特征值表示的是这个特征到底有多重要,而特征向量表示这个特征是什么,可以将每一个特征向量理解为一个线性的子空间

7.知道什么是k-means?k-means是否一定收敛。

k-means一定收敛

8.tcp三次握手。

进程线程区别

根本区别:进程是操作系统资源分配的基本单位,而线程是任务调度和执行的基本单位

在开销方面:每个进程都有独立的代码和数据空间(程序上下文),程序之间的切换会有较大的开销;线程可以看做轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小。

所处环境:在操作系统中能同时运行多个进程(程序);而在同一个进程(程序)中有多个线程同时执行(通过CPU调度,在每个时间片中只有一个线程执行)

内存分配方面:系统在运行的时候会为每个进程分配不同的内存空间;而对线程而言,除了CPU外,系统不会为线程分配内存(线程所使用的资源来自其所属进程的资源),线程组之间只能共享资源。

包含关系:没有线程的进程可以看做是单线程的,如果一个进程内有多个线程,则执行过程不是一条线的,而是多条线(线程)共同完成的;线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程。
进程是资源分配最小单位,线程是程序执行的最小单位;

进程有自己独立的地址空间,每启动一个进程,系统都会为其分配地址空间,建立数据表来维护代码段、堆栈段和数据段,线程没有独立的地址空间,它使用相同的地址空间共享数据;

CPU切换一个线程比切换进程花费小;

创建一个线程比进程开销小;

线程占用的资源要⽐进程少很多。

线程之间通信更方便,同一个进程下,线程共享全局变量,静态变量等数据,进程之间的通信需要以通信的方式(IPC)进行;(但多线程程序处理好同步与互斥是个难点)

多进程程序更安全,生命力更强,一个进程死掉不会对另一个进程造成影响(源于有独立的地址空间),多线程程序更不易维护,一个线程死掉,整个进程就死掉了(因为共享地址空间);

进程对资源保护要求高,开销大,效率相对较低,线程资源保护要求不高,但开销小,效率高,可频繁切换;


先简短的自我介绍

​ 1.数据不平衡问题的解决方法

​ 2.如何修改根据样本的不均衡确定Loss的权重

​ 3.介绍过采样和下采样的方法以及会遇到哪些潜在的问题

​ 4.画出ROC曲线和PR曲线,并介绍二者的区别和应用场景

​ 5.天平平衡问题(先放置一个质量为m的砝码,在从[1,2,4,8,16…,2^(n-1)]的砝码里挑选,使天平平衡)

2 –> 10

3 –> 11

​ 6.IoU代码

二面:

​ 面试官依旧很nice,人很好

​ 自我介绍

​ 1.介绍自己做过的项目,数据有没有进行预处理,用到哪些模型,什么框架,做了什么改进和提升(讲了2个)

​ 2.Momentum、Adagrad、Adam、SGD、RMSPROP的原理和公式,以及各自的好处

​ 3.卷积层、池化层相关原理和反向传播的过程

​ 4.BatchNorm层的相关原理及好处

​ 5.编程实现梯度下降逼近根号x,设计损失函数,模拟梯度下降的过程。

$y = \sqrt{x}$

​ 6.TF、pytorch框架相关

​ 7.Mysql相关 答得不好。。 也没细问

三面:

​ 自我介绍

​ 1.重点介绍一个项目,是问的最细的(比如涉及到opencv 透视转换的原理,指出透视转换矩阵的作用),细到怀疑人生

​ 2.写出Yolov3的损失函数

​ 3.二元交叉熵如何解决多分类问题

​ 4.写出Softmax、Sigmoid公式和交叉熵损失函数公式

​ 5.ResNet为何设计残差结构以及如何解决梯度消失问题,需写公式证明

image-20190901002609443

​ 6.编程:编辑距离 leetcode原题

​ 7.有没有想问面试官的问题


面试内容:
1.kaggle比赛:
标签相关性分析,数据增强,特征融合不同方式及其优缺点,attention(channel和pixel
两种方式的具体实现),2D CNN全套,损失函数该如何设计,fine grained有哪些解决方法
2.常规目标检测
发展过来的前世今生,yolo全套,ssd,faster rcnn具体细节,代码实现,工程中需要考虑的实际问题
3.非常规目标检测
RRPN,R2CNN(感觉面试官不是很了解这个方向,所以一直是我在说),还有我自己的框架
4.anchor free框架
基本思想,不同网络的具体对比,hourglass结构的好处,损失函数,我自己的框架具体结构,和sota比性能如何(map更高速度更快),新的损失函数为什么这么设计
5.3D卷积
和2D卷积的区别,主要存在问题,如何加速运算,视频理解的sota方法,还有什么方向可以改进
6.某大型项目
实施细节(面试官对这个很感兴趣),公然po到网上担心引起问题,故不详细展开
7.算法题
每一次面试都是我讲完论文项目实习,就快一个小时了,所以算法题也没怎么做比较难的,很快写完了。

总结:
1.注重对sota方法的了解程度,需要大量看最新顶级的论文
2.注重对具体问题的分析与解决,有的方法实际上项目的时候并不适用(考虑清楚为什么)
3.注重原理的理解而不是方法看起来有多fancy,原理至上,所以一定要理解透彻。


一面

项目

一个数字序列重排找比它大的下一个

两个智力题:抛硬币上下面概率不等,怎么制定规则使他公平

1000瓶药水 一瓶有毒 小白鼠喝了有毒的会有反应 十个小白鼠 怎么找到有毒的那瓶

题目:1000 瓶无色无味的药水,其中有一瓶毒药,10只小白鼠拿过来做实验。喝了无毒的药水第二天没事儿,喝了有毒的药水后第二天会死亡。如何在一天之内(第二天)找出这瓶有毒的药水?

第一次看这个问题完全没思路,应该有很巧妙的解法吧,后来还是百度一下,才明白怎么回事。

思路就是用二进制,2^10=1024,也就是10只小白鼠最多能验出1024瓶药水,哪个有毒。小白鼠编号,1-10。瓶子也编号,1-1000,然后把瓶子的编号转变为二进制数。如果第几位是1,就把这瓶水给第几个小白鼠喝。最后大概每个小白鼠喝500瓶药水的混合液。如果还不懂,下面列几个数字解释一下。

瓶子编号 二进制数 第几个小白鼠喝

1 0000000001 1

2 0000000010 2

3 0000000011 1,2

4 0000000100 3

5 0000000101 1,3

大概就是这意思,再反过来,假如1号和3号小白鼠死了,死的小白鼠用1表示,再写成2进制数:0000000101,转化为十进制数是5,从上面列出来的也可以看出1,3都喝了5号瓶的水,所以就是第五瓶水有毒。

解决方案
1)我们将1000瓶液体编号11000,然后将编号转化为10位二进制,如1号就是0000000001;
2)将十只小白鼠编号1
10;
3)将液体的二进制编号上为1的位数给对应的小白鼠喝,如液体编号为 1111100000,那就是15号小白鼠不喝这瓶液体,610号小白鼠喝这瓶液体;
4)一星期后观察小白鼠的死亡情况,如果15号小白鼠死亡,610号小白鼠存活,那么有毒的那瓶液体对应的二进制编码为 0000011111;
5)将第四步得到的二进制编码转化为十进制,这里是31号,因此我们可以推断出编号为31的液体是被污染的。

问我有什么想问他的

我说你为什么不问我知识点

他说看以前记录问过了……就考察别的

原来头条会存档面试记录…

二面

项目 根据项目问了一些epoll 消息类型有哪几种

事件触发回掉函数是在tcp协议哪一步里(没懂

代码:五子棋 没棋子0 白棋1 黑旗-1 判断黑旗赢了没

三面

代码题

无序数组找中位数(用了部分快排 但是没调对


一面:

\1. 讲实习做的检测的项目,讲ocr比赛的项目, 针对项目提了些问题

\3. BN层作用, dropout作用

\3. nms伪代码

\4. iou代码

\5. 最大不重复字串

\6. 单链表排序

二面:

\1. 讲实习做的检测的项目,Faster RCNN, RetinaNet, Yolo-v3在检测超小物体遇到的问题

\2. Yolov1-Yolov3改进区别,问的很细

\2. 元学习图像分类的过程,问为什么用validation的梯度更新模型就可以见效泛化误差,

这个没有细想过,答的不太好

\3. SGD的动量的作用,问为什么可以减小震荡,为什么震荡小就更容易收敛,

这个也答的不太好

\4. Adam说一下,估计梯度的一阶和二阶,然后用二阶估计来缩放每个位置的学习率,

问为什么可以对学习率缩放,从数值的角度答了一下

\5. 编程题: 从左到右增,从上到下增的矩阵查找,忘了考虑多个值的情况

三面:

\1. 讲元学习基于优化的方法是怎么做的,大概说了下自己做的工作

\2. 实习做的检测的项目,Retinanet和yolov3 anchor box的区别,yolo3里train有没有iout_thresh

\3. 01矩阵中1的最大连通面积

\4. 有多个高维向量,再新给一个如何快速查找相似的, 答了类原型,先哈希再比较

\5. 如何等概率产生半径为1的圆内坐标(x,y), 就是拒绝采样

今天问hr, 说方向不太match,基本是挂了。

出的编程题都不难,基本10分钟内就写完了。感觉可能还是理解不够深入,原理性的东西答的不太好。

渣硕一个,之前看了些别人的面经,今天也写一个回馈一下社区。。。

感觉太难了,半个月前面了旷视研究员两面也没消息了,我决定秋招完2年内就转行,不干程序员了,立帖为证。


作者:天才儿童
https://www.nowcoder.com/discuss/215883?type=post&order=time&pos=&page=2&subType=2来源:牛客网

1、算法题:n个人之间存在m个关系对,关系具有传递性,假如A关注B,B关注C,那么A就间接关注了C。如果一个人被除他之外的所有人都直接或间接关注,那么这个人就是抖音红人,求抖音红人的总数。

2、介绍一个你的项目。

3、特征选择有哪些方法(介绍项目时涉及到了特征相关性分析,因此问了这个)。

4、FM是否也能起到自动特征选择的作用,为什么。

5、GBDT的原理,和随机森林等算法做比较。

二面:

1、svm损失函数推导。

2、朴素贝叶斯写公式。

3、算法题:两个单链表找到第一个公共结点。

4、算法题:由0和1组成的二维矩阵,找出1的最大连通域,计算其面积。

三面:

1、算法题:长度为n的字符串中包含m个不同的字符,找出包含这m个不同字符的最小子串。

2、如果实现c++中的vector,只需push_back和查找两个功能,底层如何实现。

3、如果用数组实现,数组初始容量为n,每次push到容量上限之后都扩容到原来的两倍,现在push进去m个数,m远大于n,求相比于m的时间复杂度。

4、A和B比赛,A、B获胜的概率分别是0.6、0.4,如果你是A,3局2胜和5局3胜你会选择哪个。

5、如果A和B比赛无数局,A获胜的概率是多少。

6、有两张表,第一张表有n个专有名词,比如今日头条、抖音等,第二张表有m条query,比如今日头条是怎样的应用、有多少人喜欢刷抖音等,如何统计表1中所有名词在表2中出现的频次。

7、一个用户在搜索框输入query之后,如何知道他是否是在找视频。

8、如何计算一个微博账户的权威分数。

9、介绍一下xgboost有哪些特点。

10、xgboost和GBDT的分裂方式你认为哪个好。

四面:

1、c++中指针和引用的区别。

2、如何从用户态进入内核态。

3、非线性分类算法有哪些。

4、如何判断一个算法是线性的还是非线性的。

5、算法题:下一个全排列。

6、算法题:长度为n的数组中有一个数字出现了n/2次,快速找到这个数。

7、介绍一个你参加的比赛。

每一面之后都是在第二天就接到的下一面的预约电话。

前两面的算法题需要写出代码,但是不用过测试用例,三四面只用说思路。

28号下午第四面,今天晚上快7点的时候接到了offer call,通完电话后加了hr小姐姐微信之后给我发了意向书。(一开始是qq邮箱,结果qq邮箱居然把我的意向书拒收了,然后发了网易邮箱。。。)

当时在牛客上面找的前辈内推,记得推的是广告系统,今天告诉我给我分配到了搜索团队,四面的面试官就是我的leader。(在这里非常感谢牛客内推的前辈🙏)

明天回家,今天收到意向书,真的难掩心中的激动和喜悦😭虽然是计算机科班,但并不是机器学习科班,基础可以说是非常薄弱,字节offer对于我来说真的太难得。

明天网易笔试的时候我正好在回家的飞机上,本来感觉挺遗憾,现在感觉无所谓了😂


作者:南风哥哥
https://www.nowcoder.com/discuss/207092?type=post&order=time&pos=&page=1&subType=2来源:牛客网

一面:

怎么推测抖音用户是男性还是女性?怎么确认判断结果的靠谱程度?

分类问题的指标?准确度、召回率、PR曲线

相关系数怎么计算?讲一讲协方差和它的意义?

详细介绍一下实习经历?有没有场景落地?

特征选择的方法?Lasso回归、相关系数等

为什么要用正则化?解释了奥卡姆剃刀

L1正则化与L2正则化的区别?解释了参数先验和拉格朗日乘子法

手撕代码:

求股票的最大利润,例如[1, 3, 1, 8, 10, 3],只能买卖一次,计算最大收益

能买卖无数次,计算最大收益

只能买卖两次,计算最大收益

二面:

一定要走算法岗吗?还是大数据也OK?

简单说一下最有成就感的项目案例?介绍了比赛经历

简单说一下对假设检验的理解?没答上来。。。

抽样一般有哪些方法?答偏了,讲了欠采样、过采样

解释MCMC采样?讲了马尔可夫链、蒙特卡洛方法,改进版的M-H采样、吉布斯采样

与计算机相关的课程有哪些?数据结构、计算机网络、操作系统。。。嗯。。。都没学过

说几个常用排序算法的时间复杂度、空间复杂度、稳定性?

Linux系统的常用命令?

SQL如何取出成绩表中各科的前三名?

1
2
3
4
select * from 
( select subject,name,score,ROW_NUMBER() over(PARTITION by subject order by score desc) as num from #score
) T
where T.num <= 3 order by subject

对什么语言比较熟?C++、Python

手撕代码:

排序数组中绝对值不同的个数

字符串转整数

三面:

前面两面聊的怎么样?

为什么想做算法?

讲一下实习经历?大概用了什么方法?

抛一个不均匀硬币五次,两次正三次反,下一次正的概率p1是多少?

抛一个不均匀硬币五十次,二十次正三十次反,下一次正的概率p2是多少?

为什么概率是0.4?解释极大似然估计,求导计算出p1=p2=0.4

如果真实的概率是p,为什么你会觉得p2更接近p?

机器学习训练中,数据分为几份?

验证集和测试集的区别?

训练集用于训练模型参数,测试集用于估计模型对样本的泛化误差,验证集用于“训练”模型的超参数。

手撕代码:

1,2,…,N中,字符1出现的次数

判断a+b>c?要考虑溢出

感受:一面问的是基础题,基本都答上来了。二面开始被虐,计算机基础太薄弱,统计学知识也很欠缺,面试官的评价是“虽然都有了解,但不系统”。三面感觉面试官是个大佬,简单的问题会一直深挖,着重对知识的理解程度。

总结:欠缺的地方还有很多,一点一点补吧


作者:Neymarkim
https://www.nowcoder.com/discuss/192689?type=post&order=time&pos=&page=2&subType=2来源:牛客网

2.lightgbm GBDT xgb,问的超级细,可能持续了7 8分钟,XGB残差怎么用一次和二次梯度求,分裂点怎么求,思想原理是什么。XGB实际使用中重要的超参数,你们比赛中用的目标函数是什么,为什么lightgbm速度更快,其并行计算如何实现(这点没回答上)

3.bagging boosting 的区别,谁是更关注方差 ,谁是更关注偏差

4.如何防止过拟合,项目中用过哪些手段

5.W2V 的原理 ,两种生成方式,W2V的思想到底是什么,为什么要这样做,W2V的缺点,W2V中所用的softmax 比起普通softmax有何区别,为什么能减少计算量(我并不是搞自然语言的,这一波问的我有点捉襟见肘,只是勉强回答了,面试官很好,我没回答清楚地就给我讲,引导我)

6.embeding的方法 FM FFM deep FM

7.attention (毕竟是 attention is all you need 基本都会问)

8.给他讲做的CTR比赛,主要问怎么做特征,onehot 特征多了会有什么问题,为什么有时会导致效果下降(我回答的是onehot 特征占用维度太高,可能会湮没其他一些重要的特征)

可能还有一些问题记不起来了,反正真的就是抓住一个点,不停地深入

9.模型的容量问题

10.编程,比较简单的二分法

一面 1H35min 可真是太恐怖了,但整体体验很好,面试官会给你讨论,给你讲

来源:牛客网

1.开门见山,一道概率题,真的懵了,先问我bagging boosting 的区别,我愉快的回答了,然后题就来了,bagging 中随机有放回采样,假如一共有N个样本 采样了N次,得到N个采样数据,去重后有X个数据 求E(X),我只列出了暴力计算的方法,是有简单的我没想出来,各位大神知道的可以讲讲

  1. resnet VGG介绍 主要特色

  2. 1*1的卷积核 有什么用

  3. max pooling 梯度传导

  4. 5.如何防止梯度消失,为什么会有梯度消失

  5. 6.又是做题,数据结构的,找出一颗完全二叉树最后一个节点,时间复杂度要求 logN的平方

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def f(root):
left = getdepth(root.left)
right = getdepth(root.right)
while left < right:
cur = cur.left
left = getdepth(root.left)
right = getdepth(root.right)
if left == right:
cur = right:
while cur.right:
cur = cur.right
return cur
return cur

HR面 5.21

二面10分钟后就是HR面,问问基本情况,但问的还是很多,从实习的时间,工作的兴趣和期望,自我感觉的优缺点,曾经面临的困难,抗压能力等等吧

HR小姐姐一来就说她们不会刷人,只要我确定能去就能发OFFER,当时比较激动,连小姐姐声音好不好听都记不得了,我想肯定是很好听的。


作者:Ococococ
https://www.nowcoder.com/discuss/212382?type=post&order=time&pos=&page=1&subType=2来源:牛客网

2.这个项目要是你应该怎么做?

Oneclass模型?你知道哪些?普通svm能做oneclass吗?为什么?应该怎么才能做?

用过抖音么?怎么分析新老用户活跃度差异?

你会c++?讲几个关键字?

C++的异常?

水库抽样,我虽然听说过但还是不会,卒。

1-5的随机数发生器怎么生成1-7的?当时脑子抽了,明明想了一个正确的答案不敢说。

肯定是凉了,给我机会我不中用啊。

希望下午的拼多多能有个面试机会吧。


作者:不瘦20.5斤不改名
https://www.nowcoder.com/discuss/215858?type=post&order=time&pos=&page=1&subType=2来源:牛客网

1进程和线程

2编译原理,什么鬼,不懂

3队列和栈

4pytorch和tensorflow的区别

5项目里的问题,比价常规

6缓解过拟合的方法

7代码题,手撕实现图像的resize和rotate90度

二面:

1.项目

2.代码:找出数组里的任意峰值,需要优化到O(logn),

最长不重复字符串

三面:

1实习经历

2小目标检测有哪些trick

3smoothl1的好处

4代码题

有一个1000w的视频库,每个视频3-5分钟。 新来一个视频,我们需要去这1000w的视频库里查询,是否存在相同视频。 1 选择使用什么样的特征 。 2 设计一个好的index,使得查询尽可能快 (这1000w视频可以离线处理)

写一个函数,输入是N个文件,每个文件中是很多float的数值,文件内部无序。输出是一个有序的大文件,内存约束2个G,磁盘可以随便用,具体怎么实现比较高效

一面面的比较烂,没想到自己能进二面,后面两面比较顺,等了一个周今天总算收到意向书,希望大家早日拿到心仪的offer


作者:水煮鱼201906300703978
https://www.nowcoder.com/discuss/209478?type=post&order=time&pos=&page=1&subType=2来源:牛客网

整体面试一面二面二面,每轮都会写写代码,但是都维持在leetcode上easy和medium的难度,基本上刷个200来道,都不会有太大问题。我面试之前也去刷了牛客网上的题。

细节上,设计到机器学校的一些知识,我的复习策略就是疯狂看面经,看技术博客。

印象深的问题有:

1.给你M个正样本,N个负样本,以及他们的预测值P,求AUC。(写完之后接问:AUC究竟在衡量模型什么能力?如果现在所有预测值都*1.2,AUC是否会变化?)

这一题印象深刻是因为平时在计算auc的时候,很多同学都知道是roc曲线的面积,但是对auc具体的含义了解不多。

2.Attention

考虑到最近Attention的火爆和字节跳动的主要技术优势,attention这一个技术热点是一定要复习的(然而我没仔细看,非常后悔,面完之后从头到尾看了一遍)。

3.BatchNorm
这一个问题其实我有用过,我也知道原理,但是当面试问具体公示的时候,还是愣了一下,但是BN无疑是一个很火的应用,必须要会。

其他的例如softmax与cross entropy的推导,过拟合与正则化,BiLSTM,Gradient Explosion,Top N,特征选择都是常规问题就不仔细说了。

整体面试体验真的非常好,面试官很nice,一面二面的面试官,问得很仔细,我对问题理解错了给我纠正之后让我再思考,因为是视频面,反而不紧张。三面的姐姐问的最详细,但是很和善。大家面试的时候放松心态,做足准备就好,谋事在人,成事在天,不必太过紧张。如果面试中遇到思路卡壳可以一点一点解释,不用着急。

最终hr面之后拿到了offer,字节跳动data部,然后跟技术人员又聊了聊技术。跟家里谈了谈之后,决定接受offer。

有一个问题想问问大家,字节跳动data部是一个怎么样的部门呢?算是核心部门吗?

希望大家都能获得自己理想的offer!秋招加油!


作者:越陵殇
https://www.nowcoder.com/discuss/211174?type=post&order=time&pos=&page=1&subType=2来源:牛客网

还问了人像分割比赛中的设计思路和改进策略,训练方式之类的,面试官比较懂这一块,聊得挺融洽的。

深度学习相关

loss(x,y)=max(x,y),求该函数分别对x和y的偏导怎么计算?(参照max pooliing的求梯度解释);

BN的实现?

BN的作用?

BN训练期间和测试期间的区别?

BN中的batch怎么选择?https://zhuanlan.zhihu.com/p/61725100

img

普通卷的参数量如何计算?

img

如果换成depthwise conv呢?

大小为3*3,padding=0,stride=1的卷积核在经过2次计算后感受野为多少?参考:https://zhuanlan.zhihu.com/p/31004121

img

减小过拟合的方法有哪些?

YOLO v3的loss函数(讲错了,当时一紧张就讲成了Faster RCNN的loss函数,脑子发热了,难受~)

KL散度有了解吗?

smooth L1函数的作用为什么效果更好?

一些发散性的题目

不规则图形的面积如何计算?

算法:

给定一个二维数组,其中包含元素为0~9,要求矩阵中所有元素为0的行和列,并将所有0元素所在的行和列也全部更新为0。


1、自我介绍,聊相关内容,主要是一篇小论文以及相关领域内的其他论文

2、聊项目,yolo检测相关

3、问检测中能提升速度但不损失性能的操作有哪些,用过的没用过都行

4、编程题:稀疏向量的点乘。先要我自定义存储的结构体,然后写函数头,再编程,本来要我用template但我不会就算了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Node():
def __init__(self, x, y, val):
self.x = x
self.y = y
self.val = val
def matrixDotMult(m1, m2, m, n):
ans = 0
i, j = 0, 0
while i < len(m1) and j < len(m2):
if m1[i].x == m2.[j].x and m1[i].y == m2[j].y:
ans += m1[i].val * m2[j].val
i += 1
j += 1
elif m1[i].x <= m2[j].x and m1[i].y < m2[j].y:
i += 1
else:
j += 1
return ans

二面:

1、自我介绍,还是聊论文,但问的点和一面的不一样。

2、一道数学题,A、B两人投硬币,谁先投到正面谁就赢,求先投的人赢的概率 2/3

3、LR、SVM的公式推导

4、特征点的匹配机制有哪些

5、深度学习中评价指标的解释,mAP、PR曲线、AUC

image-20190831174947458

image-20190831175010353

6、编程题:链表反转,迭代+递归两种都要写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def reverse(head):
if not head or head.next:
return head
t = reverse(head.next)
head.next.next, head.next = head, None
return t

def reverse(head):
p = head
prev = None
while p:
t = p.next
p.next = prev
prev = p
p = t
return prev

三面:(居然还有三面!二面的时候感觉凉透了)

全程问项目,不问很深的技术,只是让你讲项目细节、效果如何,感觉是来验证简历真假的,问完就结束了

没有编程题

7.25更新,收到了感谢信,已凉


一面:

二叉树镜像

LRU Cache

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
class Node():
def __init__(self, key=None, val=None):
self.val = val
self.key = key
self.next = None
self.prev = None

class LRUCache(object):

def __init__(self, capacity):
"""
:type capacity: int
"""
self.head = Node()
self.tail = Node()
self.head.next = self.tail
self.tail.prev = self.head
self.dic = {}
self.cnt = capacity


def move2tail(self, node):

node.next.prev = node.prev
node.prev.next = node.next

node.next = self.tail
node.prev = self.tail.prev
node.next.prev = node
node.prev.next = node


def get(self, key):
"""
:type key: int
:rtype: int
"""
if key not in self.dic:
return -1
val = self.dic[key].val
self.move2tail(self.dic[key])
return val


def put(self, key, value):
"""
:type key: int
:type value: int
:rtype: None
"""
if key in self.dic:
self.dic[key].val = value
self.move2tail(self.dic[key])
else:
if len(self.dic) == self.cnt:
self.dic.pop(self.head.next.val)
self.head.next = self.head.next.next
self.head.next.prev = self.head

t = Node(key, value)
self.dic[key] = t


t.next = self.tail
t.prev = self.tail.prev
t.next.prev = t
t.prev.next = t

全排列稍微变形了一下

二面:

LFU Cache

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class LFUCache:

def __init__(self, capacity: int):
self.capacity = capacity
self.cache = {}
self.freq_key = {}

def get(self, key: int, new=False) -> int:
if key not in self.cache:
return -1

# 找出当前key的频率并加1
for freq in self.freq_key:
if key in self.freq_key[freq]:
self.freq_key[freq].remove(key)
if not self.freq_key[freq]:
self.freq_key.pop(freq)
self.freq_key.setdefault(freq+1, []).append(key)
break

return self.cache.get(key)

def put(self, key: int, value: int) -> None:
if self.capacity <= 0:
return
if key not in self.cache:
if len(self.cache) == self.capacity:

# 弹出频率最小的第一个元素,并移除
pop_key = self.freq_key[min(self.freq_key)].pop(0)
self.cache.pop(pop_key)

self.cache[key] = value
self.freq_key.setdefault(1, []).append(key)
else:
self.cache[key] = value
self.get(key)

三面:

一个圆形的时钟,一个点从12点出发,每秒可以顺时针走一步也可以逆时针走一步,问N秒后回到12点有多少种走法

1
2
3
4
5
6
7
8
def ways(n):
dp = [[0]*60 for _ in range(n+1)]
dp[0][0] = 1

for i in range(1, n+1):
for j in range(60):
dp[i][j] = dp[i-1][(j-1+n)%60] + dp[i-1][(j+1)%60]
return dp[n][0]

N个人,有2N只手,彼此握手,问形成的环的期望数(一个人可以左手握右手形成一个环,两个人交叉握手和正对着握手,都可以形成一个环)。

记绳子数为$N$时,环的个数为随机变量$X_N$,期望为$\mu_N=E{X_N}$。显然,$X_N$可能的取值为$1, 2, \dots, N$。直接的想法是计算$X_N$的概率分布$P{X_N=m}$然后再求期望,但显然过于复杂。考虑如下的思路:先随机选取两个绳头系在一起,有且只有两种结果:a. 这两个绳头属于一根绳子,于是形成了一个环,而剩下的$N-1$根绳子归结为规模为$N-1$的问题;b. 这两个绳头属于不同的绳子,于是这两根绳子形成了一根绳子,和剩下$N-2$共同构成了规模为$N-1$的问题。记a、b发生的概率分别为$P{a}, P{b}$,则有
$$
\mu_{N}=\left(\mu_{N-1}+1\right) P{a}+\mu_{N-1} P{b}
$$
下面计算a、b发生的概率。选这两个绳头时,第一个可以任选。而从剩下$2N-1$个绳头中选择第二个时,只有一种选择会产生情况a,即选中和第一个绳头属于同一根绳子的绳头;剩下$2N-2$种选择将产生情况b。于是:
$$
\begin{aligned} P{a} &=\frac{1}{2 N-1} \ \ P{b} &=\frac{2 N-2}{2 N-1} \end{aligned}
$$

$$
\mu_{N}=\frac{1}{2 N-1}\left(\mu_{N-1}+1\right)+\frac{2 N-2}{2 N-1} \mu_{N-1}
$$

$$
\mu_{N}=\mu_{N-1}+\frac{1}{2 N-1}
$$

$$
\mu_{N}=\sum_{n=1}^{N} \frac{1}{2 n-1}
$$


TCP 四次挥手,滑动窗口

滑动窗口协议(Sliding Window Protocol),属于TCP协议的一种应用,用于网络数据传输时的流量控制,以避免拥塞的发生。该协议允许发送方在停止并等待确认前发送多个数据分组。由于发送方不必每发一个分组就停下来等待确认,因此该协议可以加速数据的传输,提高网络吞吐量。

TCP通过滑动窗口的概念来进行流量控制。设想在发送端发送数据的速度很快而接收端接收速度却很慢的情况下,为了保证数据不丢失,显然需要进行流量控制, 协调好通信双方的工作节奏。所谓滑动窗口,可以理解成接收端所能提供的缓冲区大小。TCP利用一个滑动的窗口来告诉发送端对它所发送的数据能提供多大的缓 冲区。由于窗口由16位bit所定义,所以接收端TCP 能最大提供65535个字节的缓冲。由此,可以利用窗口大小和第一个数据的序列号计算出最大可接收的数据序列号。

Python GIL

Guido van Rossum(吉多·范罗苏姆)创建python时就只考虑到单核cpu,解决多线程之间数据完整性和状态同步的最简单方法自然就是加锁, 于是有了GIL这把超级大锁。因为cpython解析只允许拥有GIL全局解析器锁才能运行程序,这样就保证了保证同一个时刻只允许一个线程可以使用cpu。由于大量的程序开发者接收了这套机制,现在代码量越来越多,已经不容易通过c代码去解决这个问题。
————————————————
即全局解释器所(global interpreter lock),每个线程在执行时候都需要先获取GIL,保证同一时刻只有一个线程可以执行代码,即同一时刻只有一个线程使用CPU,也就是说多线程并不是真正意义上的同时执行

问题1: 什么时候会释放Gil锁,
答 :
1 遇到像 i/o操作这种 会有时间空闲情况 造成cpu闲置的情况会释放Gil
2 会有一个专门ticks进行计数 一旦ticks数值达到100 这个时候释放Gil锁 线程之间开始竞争Gil锁(说明:
ticks这个数值可以进行设置来延长或者缩减获得Gil锁的线程使用cpu的时间)

Gil锁 : 保证同一时刻只有一个线程能使用到cpu
互斥锁 : 多线程时,保证修改共享数据时有序的修改,不会产生数据修改混

2轮:

C++和python里的future是分别是干啥的

要直接把代码升级到3.x是比较冒进的,因为有大量的改动需要测试。相反,可以在2.7版本中先在一部分代码中测试一些3.x的特性,如果没有问题,再移植到3.x不迟。

Python提供了__future__模块,把下一个新版本的特性导入到当前版本,于是我们就可以在当前版本中测试一些新版本的特性。举例说明如下:

3轮:

看你做过爬虫,知道有哪些反爬虫的机制 = = (这个问题问的贼多,跟面试官探讨了很久,提了好几个方案都看他不是很满意)

  • 通过UA 识别爬虫 有些爬虫的UA是特殊的,与正常浏览器的不一样,可通过识别特征UA,直接封掉爬虫请求
  • 设置IP访问频率,如果超过一定频率,弹出验证码 如果输入正确的验证码,则放行,如果没有输入,则拉入禁止一段时间,如果超过禁爬时间,再次出发验证码,则拉入黑名单。当然根据具体的业务,为不同场景设置不同阈值,比如登陆用户和非登陆用户,请求是否含有refer。
  • 通过并发识别爬虫 有些爬虫的并发是很高的,统计并发最高的IP,加入黑名单(或者直接封掉爬虫IP所在C段)
  • 请求的时间窗口过滤统计 爬虫爬取网页的频率都是比较固定的,不像人去访问网页,中间的间隔时间比较无规则,所以我们可以给每个IP地址建立一个时间窗口,记录IP地址最近12次访问时间,每记录一次就滑动一次窗口,比较最近访问时间和当前时间,如果间隔时间很长判断不是爬虫,清除时间窗口,如果间隔不长,就回溯计算指定时间段的访问频率,如果访问频率超过阀值,就转向验证码页面让用户填写验证码
  • 限制单个ip/api token的访问量 比如15分钟限制访问页面180次,具体标准可参考一些大型网站的公开api,如twitter api,对于抓取用户公开信息的爬虫要格外敏感
  • 识别出合法爬虫 对http头agent进行验证,是否标记为、百度的spider,严格一点的话应该判别来源IP是否为、baidu的爬虫IP,这些IP在网上都可以找到。校验出来IP不在白名单就可以阻止访问内容。
  • 蜜罐资源 爬虫解析离不开正则匹配,适当在页面添加一些正常浏览器浏览访问不到的资源,一旦有ip访问,过滤下头部是不是搜素引擎的蜘蛛,不是就可以直接封了。比如说隐式链接。
  • 策略1设置下载延迟,比如数字设置为5秒,越大越安全
  • 策略2禁止Cookie,某些网站会通过Cookie识别用户身份,禁用后使得服务器无法识别爬虫轨迹
  • 策略3使用user agent池。也就是每次发送的时候随机从池中选择不一样的浏览器头信息,防止暴露爬虫身份
  • 策略4使用IP池,这个需要大量的IP资源,可以通过抓取网上免费公开的IP建成自有的IP代理池。
  • 策略5分布式爬取,这个是针对大型爬虫系统的,实现一个分布式的爬虫,主要为以下几个步骤: 1、基本的http抓取工具,如scrapy; 2、避免重复抓取网页,如Bloom Filter; 3、维护一个所有集群机器能够有效分享的分布式队列; 4、将分布式队列和Scrapy的结合; 5、后续处理,网页析取(如python-goose),存储(如Mongodb)。
  • 策略6:模拟登录—浏览器登录的爬取 设置一个cookie处理对象,它负责将cookie添加到http请求中,并能从http响应中得到cookie,向网站登录页面发送一个请求Request, 包括登录url,POST请求的数据,Http header利用urllib2.urlopen发送请求,接收WEB服务器的Response。

第一题,不能用系统自带的除法,要求用算法自己implement一个除法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
if __name__ == '__main__':
def div(a, b):
ans = 0
while a >= b:
x = b
y = 1
while a >= (x<<1):
x <<= 1
y <<= 1
ans += y
a -= x
return ans

print(div(3, 2))

第二题,用O(n)的方法找到一个无序数组的中位数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
def findmid(nums):
def swap(nums, i, j):
nums[i], nums[j] = nums[j], nums[i]

def quickFind(nums, target, left, right):
pivot = left
swap(nums, pivot, right)
l = left
r = right - 1
i = l
while i <= r:
if nums[i] < nums[right - 1]:
swap(nums, i, l)
l += 1
else:
swap(nums, i, r)
r -= 1
swap(nums, i, right)
if i == target:
return nums[i]
elif i < target:
return quickFind(nums, target - i, i + 1, right)
return quickFind(nums, target, left, i - 1)

if not nums:
return None
n = len(nums)
if n % 2:
return quickFind(nums, n // 2, 0, n - 1)
else:
return (quickFind(nums, n // 2, 0, n - 1) + quickFind(nums, n // 2 - 1, 0, n - 1)) / 2

if __name__ == '__main__':
l = [[], [1], [1, 2], [1,2,3], [2,1,3]]
for i in l:
print(findmid(i))

梯度爆炸梯度消失

L1范数L2范数原,公式

L1

image-20190831104429967
$$
J=J_{0}+\alpha \sum_{w}|w|
$$
L2

image-20190831104529551
$$
J=J_{0}+\alpha \sum_{w}w^2
$$

  • 为什么能够处理过拟合
    • 奥卡姆剃刀原理,模型越简单越好
    • 相当于是对模型的解空间进行约束

L1会趋向于产生少量的特征,而其它特征都是0。L2会选择更多的特征,这些特征都会趋近于0。L1在特征选择时非常有用,而L2只是一种防止过拟合的方法。在所有特征中只有少数特征起重要作用的情况下,选择L1范数比较合适,因为它能自动选择特征。而如果所有特征中,大部分特征都能起作用,而且起的作用很平均,那么使用L2范数也许更合适。

过拟合

训练过程中的损失减小,准确度提升,但是在测试的时候loss会增大,准确度减小。

模型太过于复杂造成的,解决方法包括:

数据方面:数据增广、减少数据的维度

模型方面:用较简单的模型、使用BN、Dropout

损失方面:添加增则项、加大增则项的权重、换一个损失

训练方面:提前终止

Yolo ssd fast系列区别

包括yolo 1-3(对于yolo的细节提问)

ssd 各种变体

判断链表有环

1
2
3
4
5
6
7
8
9
10
def exisitCircle(head):
if not head:
return False
slow, fast = head, head
while fast and fast.next:
fast = fast.next.next
slow = slow.next
if fast == slow:
return True
return False

二叉树中序遍历

1
2
3
4
5
6
7
8
9
10
11
12
13
def inorder(root):
l = []
cur = root
ans = []
while l or cur:
if cur:
l.append(cur)
cur = cur.left
else:
cur = l.pop()
ans.append(cur.val)
cur = cur.right
return ans