面试一个公司记录

哎!今天面试一个公司,惨不忍睹。把流程记录下来:

1、自我介绍

主要介绍简历中的一个比赛和一个项目自我介绍之后面试官问了些简历的内容。

2、决策树

决策树是一种常见的机器学习方法,我们希望从给定的训练集中学得一个模型用以对新的数据进行分类。决策树是基于树结构进行决策的,按照节点一步步进行判断。每一个节点作为一个决策条件(分类),如果当前节点无法实现分类,则进一步进行节点裂变,生成多个节点继续进行决策,是一个递归的过程。
重要概念:
(1)信息增益
信息熵是度量样本集合纯度最常用的一种指标(也可以理解为数据的混乱程度,参考化学中的熵增情况)。信息熵越小,代表数据纯度越高(整洁的房间熵要比混乱的房间熵小)。当信息增益越大时,代表当前的属性划分的越合理。于是对每一个属性划分的原则就取决于谁的信息增益大(本质便是谁的分类误差更小,只是这里分类无法不太好衡量,用信息增益进行计算)。(以上是ID3决策树学习算法)。
(2)增益率
望文生义,代表信息熵增益的比率。按照上述信息增益进行节点生成,会导致很多子节点,划分的太详细会导致过拟合的问题。因此,提出增益率,每次选择增益高于均值的里面最高的。(以上是C4.5决策树算法)
(3)基尼指数
CART决策树使用基尼指数(Gini index)选择划分属性。基尼指数反映数据集中任意两个样本不一致的概率。Gini越小,数据纯度越高。在每次决策中,选择Gini指数最小的属性作为最优划分属性。
(4)减枝处理
上述方法中生成决策树节点过多,会导致过拟合,因此对决策树进行减枝处理。
A、预减枝
生成节点之后就进行减枝。在每次生成决策节点之前,先用验证集进行测试,看下准确率如=如何,如果提升,则保留,如果降低则舍弃;
B、后减枝
生成决策树之后,再进行减枝。在验证集上用子树进行测试,如果准确率提升则保留,如果降低,则舍弃。

找到一个决策树的通俗讲解。不过要想弄懂,还是看看西瓜书吧《机器学习》周志华。P73-93

3、随机森林

随机森林属于集成学习的内容。所谓集成学习,就是通过构建并结合多个学习器来完成学习任务,有时也叫做多分类器系统。通俗来说,就是训练多个不同的分类器(假如针对分类任务可以用决策树、神经网络等),然后多个分类器都预测,最后对多个预测结果进行投票或者取均值的方式完成学习。优点在于可以降低噪声的影响,提高学习的鲁棒性。
集成学习中有两种经典的算法,Bagging随机森林
Bagging是在训练集中进行多次有放回的随机抽取操作,多次提取训练集的一部分数据训练多个分类器,最后融合多个测试结果。这样多个分类器中的训练集有一定的差异,保证了不同分类器学习到的知识不同。
随机森林是在Bagging的基础上,进行多次有放回的随机抽取样本操作,训练多个分类器,并且随机抽取属性的子集用于训练。区别在于Bagging是在所有的属性中选择最优属性作为节点,而随机森林是取属性的子集。这样随机森林相比Bagging具有速度快、鲁棒性高等优点。

4、KNN

KNN(K-Nearest Neighbor)即K近邻。其不需要训练,模型表示即为训练集和度量方式和K的取值;测试时统计测试数据周围的最近的K个样本,根据这K个样本的情况判断测试数据的类别。
优点:不需要训练,效果挺好;
缺点:测试时需要的计算量太大,对K的取值比较敏感。

5、你用过什么机器学习方法?

答:SVM、K-means

6、介绍SVM,有哪些核函数,作用是什么?

SVM (Support Vector Machine,支持向量机)
SVM是一种二分类模型,它的目的是寻找一个超平面来对样本进行分割,分割的原则是边界最大化,最终转化为一个凸二次规划问题来求解
(1)当训练样本线性可分时:通过硬间隔最大化(hard margin),学习一个线性分类器,即线性可分支持向量机(即在N维空间中,找到N-1维的分类面,使得边界数据距离分类面最大化);
(2)当训练数据近似线性可分时:引入松弛变量,通过软间隔最大化(soft margin),学习一个线性分类器,即线性支持向量机(优化目标是在最大化分类间隔的同时,不满足约束的样本尽可能的少);
(3)当训练数据线性不可分时:通过使用核技巧及软间隔最大化,学习非线性支持向量机(结合使用拉格朗日乘子法(Lagrange Multiplier)和KKT(Karush Kuhn Tucker)条件,以及核函数可以生成非线性分类器。
核函数
核函数的作用是将原坐标系里线性不可分的数据用核函数Kernel投影到另一个高维特征空间中,尽量使得数据在新的空间里线性可分。
经典的有线性核、多项式核、高斯核等。
(1)核函数的引入避免了“维数灾难”,大大减小了计算量。而输入空间的维数n对核函数矩阵无影响。因此,核函数方法可以有效处理高维输入。
(2)无需知道非线性变换函数Φ的形式和参数。
(3)核函数的形式和参数的变化会隐式地改变从输入空间到特征空间的映射,进而对特征空间的性质产生影响,最终改变各种核函数方法的性能。
(4)核函数方法可以和不同的算法相结合,形成多种不同的基于核函数技术的方法,且这两部分的设计可以单独进行,并可以为不同的应用选择不同的核函数和算法。(参考

7、介绍K-means,有哪些缺点?

K-means 是我们最常用的基于欧式距离的聚类算法,其认为两个目标的距离越近,相似度越大。一般用最小化平方误差描述聚类簇的紧密程度。一个聚类簇中最小化平方差越小,相似度越高。

#获取数据 n 个 m 维的数据
#随机生成 K 个 m 维的点
while(t) 
    for(int i=0;i < n;i++)
        for(int j=0;j < k;j++)
            #计算点i到所有中心点j的距离,找到最小的距离并将i归类其中
    for(int i=0;i < k;i++)
    	#找到k个类中每个类别的所有数据,并计算均值(K-means的由来)
end # 停止条件,比如各聚类簇的平方误差不再减小

优点
(1)容易理解,聚类效果不错;
(2)处理大数据集的时候,该算法可以保证较好的伸缩性;
(3)当簇近似高斯分布的时候,效果非常不错;
缺点
(1)K 值需要人为设定,不同 K 值得到的结果不一样;
(2)对初始的簇中心敏感,不同选取方式会得到不同结果;
(3)对异常值敏感;
(4)不适合太离散的分类、样本类别不平衡的分类、非凸形状的分类;
(5)计算的复杂度很高。

8、GAN和(变分)自编码器(VAE)的区别

GAN和自编码器本质都是将未知的数据分布映射到训练集的数据分布。假设隐变量z服从某种分布,并学习一个映射X=G(z),使得隐变量的分布z能映射到真实数据分布中。
区别:
(1)GAN直接利用判别器去度量生成器生成的数据分布与真实数据分布的距离;
(2)VAE通过约束隐变量z与标准正太分布的KL散度和重构误差去度量(也就是将已知的某种数据分布(比如高斯分布)映射到目标的数据分布,注意一般使用JS散度,重要的地方在于JS散度是对称的,KL散度不对称训练时难以收敛)。

9、为什么会存在梯度消失的问题?(有哪些激活函数,为什么sigmoid效果不好)

在反向传播中,根据损失函数计算误差,然后得到梯度,通过梯度反向传播的方式优化神经网络的权重。由于多层网络的堆叠,其计算的过程可以表示为:
F(x)=fn(…f3(f2(f(1)*θ1+b)*θ2+b)*θ3+b)
网络深度
导数可以计算为fn’ *…f3’*f2’*f1’,如果初始权重较小,梯度小于1,会导致连乘梯度消失;初始权重较大,梯度大于1,会导致连乘梯度爆炸。
激活函数
如果激活函数选择不合适,比如使用 sigmoid,梯度消失就会很明显了。因为Sigmoid的求导之后,梯度最大不会超过0.25,经过链式求导之后梯度消失。
解决梯度消失或梯度爆炸的方法
(1)梯度剪切,如果梯度大于某个阈值,就强制限制在此范围内,避免梯度爆炸;
(2)ReLU激活函数,倒数正数部分是1,不会出现过大或者过小的问题;
(3)batch norm,加快收敛、提升训练稳定性,将输入的信号规范化到均值为0,方差是1,避免出现过大或者过小的情况,保证网络的稳定性;
(4)残差结构,使得深层网络能够跳级到浅层结构中 梯度是f’n(1+f’n-1) ,使得深层网络的梯度能够进行有效的回传,避免出现梯度消失。

10、介绍rcnn、fast rcnn、faster rcnn、cascade rcnn

看下这个链接
当时面试官问我,cascade rcnn为什么比faster rcnn效果好,我回答的是加了检测头,对于上一层的proposal更好了,加大iou的阈值,再进行回归效果更好。面试官就问我有没有看cascede rcnn的论文,我说去年看的。
后来面试官提到了mismatch的问题。

1)在training阶段,由于我们知道gt,所以可以很自然的把与gt的iou大于threshold(0.5)的Proposals作为正样本,这些正样本参与之后的bbox回归学习。
(2)在inference阶段,由于我们不知道gt,所以只能把所有的proposal都当做正样本,让后面的bbox回归器回归坐标。
(3)单一阈值训练出的检测器效果非常有限,单一阈值不能对所有的Proposals都有很好的优化作用。
(4)我们可以明显的看到training阶段和inference阶段,bbox回归器的输入分布是不一样的,training阶段的输入proposals质量更高(被采样过,IoU>threshold),inference阶段的输入proposals质量相对较差(没有被采样过,可能包括很多IoU<threshold的),这就是论文中提到mismatch问题,这个问题是固有存在的,通常threshold取0.5时,mismatch问题还不会很严重

因此采用多种检测头的方式,阈值慢慢提升。参考

11、RPN网络结构?分类损失函数?回归损失函数?

RPN全卷积结构,1×1,分类部分输入特征,输出HWK1的特征图,经过binary cross entropy进行分类;回归部分输入特征,输出HWK4的特征图,K表示每个位置anchor的个数,使用Smooth L1损失。Smooth L1损失,当损失大时,梯度是1,损失小是梯度是本身,有利于收敛。

12、编程题1:

给出两个单词word1和word2,计算将word1到word2最少的操作次数。(可以使用插入、删除、替换操作)
这个题目是leetcode是一道题目,动态规划的方法来做的。面试的时候没有做出来,不知道怎么推导动态转移方程了,晚上一个人推导一会给做出来了。呃呃呃呃呃!

示例 1:
输入:word1 = "horse", word2 = "ros"
输出:3
解释:
horse -> rorse ('h' 替换为 'r')
rorse -> rose (删除 'r')
rose -> ros (删除 'e')
示例 2:
输入:word1 = "intention", word2 = "execution"
输出:5
解释:
intention -> inention (删除 't')
inention -> enention ('i' 替换为 'e')
enention -> exention ('n' 替换为 'x')
exention -> exection ('n' 替换为 'c')
exection -> execution (插入 'u')
提示:
0 <= word1.length, word2.length <= 500
word1 和 word2 由小写英文字母组成
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/edit-distance
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

dp[i][j]表示word1中前i个字符操作几步之后能转化成word2。
dp[i][0] = i,表示当word2是0个字符时,需要删除i个字符,能够将word1转化为word2;
dp[0][j] = j,表示word1是0个字符时,需要添加j个字符能够将word1转化为word2;
状态转移方程:
当word1[i] == word2[j]时,dp[i][j] = dp[i-1][j-1]这个比较好理解的;
当word1[i] != word2[j]时,dp[i][j] = min(dp[i-1][j-1],dp[i-1][j],dp[i][j-1])+1。这个其实比较好理解,就是当前如果不匹配,怎么才能匹配呢?那就是前面三种情况的最小值+1,其中+1表示替换操作。

class Solution:
    def minDistance(self, word1: str, word2: str) -> int:
        dp = [[0 for _ in range(len(word2)+1)] for __ in range(len(word1)+1)]
        for i in range(len(word1)+1):
            dp[i][0] = i
        for j in range(len(word2)+1):
            dp[0][j] = j
        for i in range(1,len(word1)+1):
            for j in range(1,len(word2)+1):
                if word1[i-1] == word2[j-1]:
                    dp[i][j] = dp[i-1][j-1]
                else:
                    dp[i][j] = min(dp[i][j-1],dp[i-1][j],dp[i - 1][j - 1]) + 1
        return dp[-1][-1]

13、编程题2:

给你1-5的随机数,怎么生成1-8的随机数。
这个题目面试的时候傻乎乎的用rand5*1.6,然后被告知无法生成1,现场打脸。通过直接的线性变换是无法实现rand5 到 rand8的转化的。
然后面试官提醒说,如果用rand8生成rand5可以直接多次生成,如果生成的随机数大于5舍弃掉。
经过提醒之后,还是一脸懵逼。后来面试官告诉我咋做了(还嘲讽一番说他大一大二的时候老师就讲过,呃呃呃呃呃)。分享屏幕的时候我直接写的,说我编程习惯不好,没有封装方法或类。

#用随机数1-5生成随机数1-8,可以这样操作:
import random
def rand5_8():
    rand5_1 = 5
    rand5_2 = 5
    while rand5_1 > 2:
        rand5_1 = random.randint(1,5)
    while rand5_2 > 4:
        rand5_2 = random.randint(1,5)
    return (rand5_1 - 1)*4 + rand5_2
count = [0 for _ in range(8)]
for i in range(10000):
    count[rand5_8()-1] += 1
print(count)

恶补一下,稍后把所有问题的解答整理下。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值