机器学习算法工程师面试问题汇总(持续更新)

目录

一、通用基础知识

1.1ReLU与Leaky ReLU

1.2损失函数

1.3怎么去选择损失函数呢?

1.4Focal loss及其优缺点

1.5特征归一化/标准化的意义

1.5Batch Normalization的原理与作用

1.6解决过拟合的方法。

二、特征工程

2.1如何进行特征选择?

三、模型评估

四、回归

4.1介绍一下逻辑回归

五、集成学习与树模型系列

5.1介绍一下集成算法

5.2介绍一下树模型系列。

5.2.1决策树:

5.2.2随机森林:

5.2.3Adaboost:

5.2.4GBDT:

5.2.5XGBoost:

5.2.6lightGBM:

六、神经网络系列

6.1ResNet怎么解决梯度消失、梯度爆炸和网络退化问题

6.2Transformer

七、聚类

7.1K-means聚类

7.2DBSCAN聚类

八、降维

8.1介绍一下线性判别分析(LDA)

8.2介绍一下主成分分析(PCA)

九、其他算法

9.1介绍一下支持向量机

十、概率图模型

十一、模型优化算法

11.1一般怎样进行超参数的自动调节。

11.1.1网格搜索:

11.1.2随机搜索:

11.1.3贝叶斯优化:

11.2NMS算法

十二、采样方法

12.1介绍一下MCMC马尔可夫-蒙特卡洛抽样

十三、AI应用案例分析

13.1文本相似度计算方法


一、通用基础知识

1.1ReLU与Leaky ReLU

修正线性单元(Rectified linear unit,ReLU)是神经网络中最常用的激活函数。它保留了 step 函数的生物学启发(只有输入超出阈值时神经元才激活),不过当输入为正的时候,导数不为零,从而允许基于梯度的学习(尽管在 x=0 的时候,导数是未定义的)。使用这个函数能使计算变得很快,因为无论是函数还是其导数都不包含复杂的数学运算。然而,当输入为负值的时候,ReLU 的学习速度可能会变得很慢,甚至使神经元直接无效,因为此时输入小于零而梯度为零,从而其权重无法得到更新,在剩下的训练过程中会一直保持静默。

综上可知,ReLu激活函数的优点是:

1,相比Sigmoid/tanh函数,使用梯度下降(GD)法时,收敛速度更快;

2,相比Sigmoid/tanh函数,Relu只需要一个门限值,即可以得到激活值,计算速度更快。

缺点是:

Relu的输入值为负的时候,输出始终为0,其一阶导数也始终为0,这样会导致神经元不能更新参数,也就是神经元不学习了,这种现象叫做“Dead Neuron”。

为了解决Relu函数这个缺点,在Relu函数的负半区间引入一个泄露(Leaky)值,所以称为Leaky Relu函数,如下图所示:

LeakyReLU(x)=\begin{\Bmatrix} x ,x\geqslant 0& \\ \alpha x ,else& \end{Bmatrix}

其中\alpha的值很小,所以此时在负半区间内也可以进行梯度下降与参数更新,但是更速度较慢。

1.2损失函数

什么是损失,损失其实是针对某一个样本点来谈的,针对整个数据集的损失函数的平均,称为成本函数

天天说损失最小,最小,那是因为损失函数是凸函数才会必然存在最小值,那凭什么就是凸函数呢,因为选择损失函数的权力在人的手中,所以,你选择一个凸函数作为损失不就行了。。。

常见的损失有:

1.基于距离度量的损失:

MSE损失

msle损失

mean_absolute_percentage_error

L2损失

L1损失

Smooth L1损失

huber损失

poisson损失

hinge 铰链损失

squared hinge损失

categorical_hinge损失

Log-Cosh损失函数

cosine_proximity:即预测值与真实标签的余弦距离平均值的相反数

1.3怎么去选择损失函数呢?

(1)选择最能表达数据的主要特征来构建基于距离或基于概率分布度量的特征空间。

(2)选择合理的特征归一化方法,使特征向量转换后仍能保持原来数据的核心内容。

(3)选取合理的损失函数,在实验的基础上,依据损失不断调整模型的参数,使其尽可能实现类别区分。

(4)合理组合不同的损失函数,发挥每个损失函数的优点,使它们能更好地度量样本间的相似性。

(5)将数据的主要特征嵌入损失函数,提升基于特定任务的模型预测精确度。

1.4Focal loss及其优缺点

首先介绍信息熵的概念,何为信息熵,我们就用讲故事的方式来讲解,首先大家都知道现在是信息是很重要的,有时候你只要拥有一个重要的信息,就能赚很多钱,这也是信息不对称造成的,那么什么样的信息是重要的呢,我理解的是,越容易推测出来的信息越不重要,比如明天太阳会从东方升起,这个信息,你说它是不是一个信息,那它是一个重要的信息嘛,我认为不是,为啥?

太阳从东边升起,这还用你说吗,人人都知道。所以它包含的“信息量”比较小,那有人说,我有一个信息,明天会有外星人到访地球,这个信息够劲爆啊,而且很难准确推测出来,这个就是“信息量”大,于是有一位伟大的科学家,叫Shannon,他说,这个世界上,有迹可循的事情都没什么价值,越混乱的状态信息量越大,而混乱的程度,就是“熵”,熵有很多,像是我们学的高等数理统计中的Fisher Info,还有这里的香农熵。

香农认为,某种很难推测出来的事件,其实就是发生的概率低的事件,其信息量更大,那么就有信息量的函数f(x)与概率p(x)应该是负相关的关系,香农希望用一个函数来表示,但是负向的函数有很多,怎么选择呢?

不急,还有一个结论,就是若有两个不相关的事件x和y,事件x与事件y同时发生的信息与他们各自发生的信息之和,这两者应该是相同的。 即 h(x,y)=h(x)+h(y),那对于不相关的事件x和y来说,在概率上有p(x,y)=p(x)*p(y),那就得了,显然h(x)+h(y)=h(x,y)即:

log(p(x))+log(p(y))=log(p(x)*p(y))=log(p(x,y)),但是又因为log(x)是单调递增函数,所以要取一个负号变成负向函数,于是我们的“信息量”就记作h(x)=-log(p(x))啦

那对于一个事件来说,它可能有多种结果,为了普适性,先举一个多分类的例子,假设有p1,p2,...,pn这n种可能的结果,那么对于一个事件来说,它有这么多种结果,我要怎么来描述它的信息量呢,Shannon的做法是求数学期望,首先h(x)它是x的函数吧,是函数就可以用函数的期望公式:

H(x)=E(h(x))=\sum_{i=1}^{n}h(x_{i})p_{i}

那么h(x)=-log(p(x)),于是上式就可以写作:

H(x)=E(h(x))=\sum_{i=1}^{n}(-log(p(x_{i})))p(x_{i})=-\sum_{i=1}^{n}log(p_{i})p_{i}

这就是所谓的“信息熵”,因为是香农提出的,又被称为“香农熵”。

上面这个好像是可以衡量你这个事件含有的信息量大小哈,但是好像还没有感觉到它有什么具体的用处呀,没关系我们继续来看下一个概念,相对熵,又叫Kullback-Leibler散度(KL散度),我开始看到这个概念的时候也在想,啥KL散度,从字面上根本看不出它是干嘛的啊,哦,仔细一看,这就是一个用来比较实际分布与预测分布的相似性的东西,就是你做了某某预测之后,那不是要评价一下,自己预测的准不准嘛,在有实际数据的情况下,你用预测出来的数据与那些个实际数据去一比较,不就可以发现,实际与预测之间的差别有多大了吗(夹带点私活,我感觉这个活,假设检验也能做啊),具体的原理如下:

用预测分布的信息熵减去实际分布的信息熵,即可~

昂,就这么一句话,我感觉就ok了,它就是说,你们两个分布的信息量如果差不多,就说明你们两个分布很接近了。。。就这意思。。。对了h(q(x))对应的概率也是p(x),emmm

于是,就有KL散度的公式如下;

KL(x)=H(x)_{q}-H(x)_{p}=-\sum_{i=1}^{n}log(q_{i})p_{i}-(-\sum_{i=1}^{n}log(p_{i})p_{i})=-\sum_{i=1}^{n}log(\frac{q_{i}}{p_{i}})p_{i}

这就是所谓的KL散度了,当然KL散度是恒大于0的,但我们肯定是希望KL散度越接近0越好的,那说了半天,交叉熵呢,这不才是最常用的损失函数吗,其实交叉熵很简单,因为在有监督学习中,比如神经网络,标签是已经知道的,所以实际分布的信息熵是可以直接计算出来的,这就是一个常数C啊,那我们的目标是KL散度接近于0,那我令一个统计量=KL散度+实际分布的信息熵>=实际分布的信息熵,这个统计量就是交叉熵,其公式如下:

CE=-\sum_{i=1}^{n}p_{i}log(q_{i})

然后不就把目标转换成了,令交叉熵尽可能去逼近实际分布的信息熵,从数值上来看,就是越小越好的。

那交叉熵可以作为分类任务的损失函数来用,也就是希望训练出,可以使得交叉熵函数尽可能小的模型参数,然后用这组模型参数结合模型去进行推理预测~

但是实际应用中,经常会遇到类别不平衡问题,所谓类别不平衡,就比如说二分类问题中,正例数量占比90%,负例占比只有10%,这就很烦了,因为这样容易造成负例的预测效果很差,因为负例的数量少导致它的变化对损失函数影响不大,因而对这部分样本的学习效果就很差,那就有人提出可以加一个系数\alpha来进行调节,该系数处于0到1之间即可,让数量多的正例乘以一个小一点系数,来降低这部分样本的影响力,让数量少的负例乘以大一些的1-\alpha,这样就形成了所谓的“平衡交叉熵”,公式如下:

CE_{balance}=-\sum_{i=1}^{n}\alpha_ip_ilog(q_i)

但是有时候,占比小的那个类别,它比例真的太小了,即便它这个类别的影响调大那么一点,也顶不住人家比例大的那个类别,因为人家样本太多了啊,100个0.1加起来照样比你1个9要大呢,所以又有了Focal loss,Focal loss会考虑到样本分类成功的难易程度,它会多关注到难分的样本,对容易分的样本的关注度会降低,具体的操作就是,对(1-该样本的置信度)求幂来作为权重,就可以扩大置信度低的样本的影响程度了,数学推导如下:

\left\{\begin{matrix} if:C=x_2/x_1>1 & & \\ then:C^2=x_2^2/x_1^2>C& &\\ and:C^2>>>>C,if:C>>1& & \end{matrix}\right.

例如p1=0.9,而p2=0.6,那么1-p1=0.1,1-p2=0.4,然后就有(1-p_1)^2=0.01,(1-p_2^2)=0.16,从数据上看,\frac{1-p_2}{1-p_1}=4\frac{1-p_2^2}{1-p_1^2}=16,这就是幂对倍数的放大效果,这样Focal loss就做到了对不同的置信度(其实就是概率,概率越小就认为越难识别,就应该加大对这个样本的关注啊)的样本,通过次幂的方式实现分而治之地赋权,要知道,一般置信度高的样本,也都是占比偏大的那个类别里的,如果还是不放心,那就还有一种办法,把那个\alpha再拿进来,这样就既考虑到不同占比类别的关注度,又考虑到不同的分类难易程度的样本的关注度,这个损失就考虑的比较全面了,我称之为平衡Focal loss,具体公式如下:

FL_{balance}=-\sum_{i=1}^{n}\alpha_i(1-p_i)^\gamma p_ilog(q_i)

好啦,完结撒花~

1.5Batch Normalization的原理与作用

批归一化Batch Normalization是一种用于训练神经网络模型的有效方法。这种方法的目标是对特征进行归一化处理(使每层网络的输出都经过激活),得到标准差为1的零均值状态。所以其相反的现象是非零均值。这将如何影响模型的训练:

首先,这可以被理解成非零均值是数据不围绕0值分布的现象,而是数据的大多数值大于0或小于0。结合高方差问题,数据会变得非常大或非常小。在训练层数很多的神经网络时,这个问题很常见。如果特征不是分布在稳定的区间(从小到大的值)里,那么就会对网络的优化过程产生影响。我们都知道,优化神经网络将需要用到导数计算。

假设一个简单的层计算公式y=(Wx+b),y在W上的导数就是这样:dy=dWx。因此,x的值会直接影响导数的值(当然,神经网络模型的梯度概念不会如此之简单,但理论上,x会影响导数)。因此,如果x引入了不稳定的变化,则这个导数要么过大,要么就过小,最终导致学习到的模型不稳定。而这也意味着当使用批归一化时,我们可以在训练中使用更高的学习率。

批归一化可帮助我们避免x的值在经过非线性激活函数之后陷入饱和的现象。也就是说,批归一化能够确保激活都不会过高或过低。这有助于权重学习——如果不使用这一方案,某些权重可能永远不会学习。这还能帮助我们降低对参数的初始值的依赖。

批归一化也可用作正则化的一种形式,有助于实现过拟合的最小化。使用批归一化时,我们无需再使用过多的dropout,这是有好处的,因为我们不用担心因为dropout时丢失太多信息了。但是,最好仍然组合使用这两种技术。

BN层的作用主要有三个:

  1. 加快网络的训练和收敛的速度;

在深度神经网络中中,如果每层的数据分布都不一样的话,将会导致网络非常难收敛和训练,而如果把每层的数据都转换成均值为零,方差为1 的状态,每层数据的分布都是一样的,训练会比较容易收敛。

  1. 控制梯度爆炸防止梯度消失;

梯度消失:在深度神经网络中,如果网络的激活输出很大,其对应的梯度就会很小,导致网络的学习速率就会很慢,假设网络中每层的学习梯度都小于最大值0.25,网络中有n层,因为链式求导的原因,第一层的梯度将会小于0.25的n次方,所以学习速率相对来说会变的很慢,而对于网络的最后一层只需要对自身求导一次,梯度就大,学习速率就会比较快,这就会造成在一个很深的网络中,浅层基本不学习,权值变化小,而后面几层网络一直学习,后面的网络基本可以表征整个网络,这样失去了深度的意义。(使用BN层归一化后,网络的输出就不会很大,梯度就不会很小

梯度爆炸:第一层偏移量的梯度=激活层斜率1x权值1x激活层斜率2x…激活层斜率(n-1)x权值(n-1)x激活层斜率n,假如激活层斜率均为最大值0.25,所有层的权值为100,这样梯度就会指数增加。(使用bn层后权值的更新也不会很大)

  1. 防止过拟合。

在网络的训练中,BN的使用使得一个minibatch中所有样本都被关联在了一起,因此网络不会从某一个训练样本中生成确定的结果,即同样一个样本的输出不再仅仅取决于样本的本身,也取决于跟这个样本同属一个batch的其他样本,而每次网络都是随机取batch,这样就会使得整个网络不会朝这一个方向使劲学习。一定程度上避免了过拟合。

1.6解决过拟合的方法。

有增加样本数量,对样本进行降维,降低模型复杂度,利用先验知识(L1,L2正则化),利用交叉验证,早停法,批归一化等。

二、特征工程

2.1如何进行特征选择?

在现实任务中我们会遇到维数灾难的问题(样本密度非常稀疏),若能从中选择一部分特征,那么这个问题就能大大缓解,另外就是去除不相关特征会降低学习任务的难度,增加模型的泛化能力。冗余特征指该特征包含的信息可以从其他特征中推演出来,但是这并不代表该冗余特征一定没有作用,例如在欠拟合的情况下也可以用过加入冗余特征,增加简单模型的复杂度。

在理论上如果没有任何领域知识作为先验假设那么只能遍历所有可能的子集。但是这显然是不可能的,因为需要遍历的数量是组合爆炸的。一般我们分为子集搜索和子集评价两个过程,子集搜索一般采用贪心算法,每一轮从候选特征中添加或者删除,分别成为前向和后先搜索。或者两者结合的双向搜索。子集评价一般采用信息增益,对于连续数据往往排序之后选择中点作为分割点。

常见的特征选择方式有过滤式filter,包裹式wrapper和嵌入式embedding。Filter类型先对数据集进行特征选择,再训练学习器。Wrapper直接把最终学习器的性能作为特征子集的评价准则,一般通过不断候选子集,然后利用交叉验证过程更新候选特征,通常计算量比较大。嵌入式特征选择将特征选择过程和训练过程融为了一体,在训练过程中自动进行了特征选择,例如L1正则化更易于获得稀疏解,而L2正则化更不容易过拟合。L1正则化可以通过PGD,近端梯度下降进行求解。

2.2特征归一化/标准化的意义

先说结论,特征归一化处理常见的就是min-max Normalization,Z-score Normalization以及非线性归一化,如取log。事实上,特征归一化的目的就是为了消除量纲并将不同特征放缩到同一数量级,最直观的感觉,对于两个特征x1和x2,其目标函数为f(x_{1},x_{2})=\theta_{1} x_{1}+\theta_{2} x_{2}+\theta,当x1的取值范围为[0,100]而x2的取值范围为[0,10]时,要想让x1与x2对目标函数的影响程度相当,则\theta_{1}应当比\theta_{2}小很多才能做到,这也就是为什么特征归一化只对梯度下降算法有意义,对树模型没有意义,具体原因如下:

首先对于f(x_{1},x_{2})=\theta_{1} x_{1}+\theta_{2} x_{2}+\theta,要求解\theta_{1}\theta_{2}的话,即令目标值与估计值相等,\frac{1}{2}\sum_{i=1}^{m}(f(x_{1}^{i},x_{2}^{i})-y^{i})^2,对\theta_{1}求偏导,可以得出\sum_{i=1}^{m}(f(x_{1}^{i},x_{2}^{i})-y^{i})x_1^{i},另一方面对\theta_{2}求偏导,可以得出\sum_{i=1}^{m}(f(x_{1}^{i},x_{2}^{i})-y^{i})x_2^{i},由于x1大于x2,所以,在\theta_{2}方向上梯度下降的速度更慢,因此有V_{\theta_{1}}>V_{\theta_{2}},从图上来看:

 首先红色的环是等高线,但在为归一化的数据上,\theta_{1}方向比\theta_{2}方向上的速度更快,所以其到达最优点更快,如果两个方向上到达最优点的距离是一致的,那么这个不同方向上的距离可以理解成抵达最优点所需的时间长度,即t = L / V。

但是因为出发点都是基于当前位置的,也就是垂直于等高线的方向发出的,因此椭圆可能会导致其优化路径走成“之”字形,进而导致收敛速度变慢甚至不收敛;

而归一化后,等高线是圆形,梯度下降的出发方向基本都是直指圆心的,因此可以快速收敛。

最后看归一化和标准化的使用场景。

(1)如果对输出结果范围有要求,用归一化。

(2)如果数据较为稳定,不存在极端的最大最小值,用归一化。

(3)如果数据存在异常值和较多噪音,用标准化,可以间接通过中心化避免异常值和极端值的影响。

2.3类别型特征的编码方式

简而言之,可以分为三种编码方式,一是序号(Ordinal)编码,二是(One-Hot)独热编码,三是二进制(Binary)编码。但如果有些模型例如树模型,可以直接处理离散特征,可以选择不做编码~

序号编码就是,对于优秀、良好、中等、差,这个有序的四档类别,对其进行排序,其中4代表优秀,3代表良好,2代表中等,1代表差,注意,这种编码是针对有序类别的,其转换后依然保留了大小关系。

独热编码是处理类别间大小没有关系的特征的,如果没有大小概念的特征采用序号编码方式,其实是不合理的,因为模型会将3认为比1重要,这是不对的,其具体编码方式如下,例如样本A有特征“性别”和“职业”,其类别分别为“男,女”和“前端程序员、后端程序员、产品经理、数据分析师、算法工程师”,经过独热编码,男为(1,0),女为(0,1),而职业特征的取值中,前端程序员为(1,0,0,0,0),后端程序员为(0,1,0,0,0),产品经理为(0,0,1,0,0),数据分析师为(0,0,0,1,0),算法工程师为(0,0,0,0,1),那么就有样本【女,产品经理】的独热编码结果为(0,1,0,0,1,0,0)。

之所以这样编制,是因为其是采用N位状态寄存器来对N个状态进行编码,每个状态都有其独立的寄存器位,并且任意时刻只有一位有效,其主要就是为了把数值映射到二进制向量,每一个数值都可以用一个二进制向量表示,这比较适合计算机来识别。

另一方面,对于回归、聚类、分类等机器学习方法来说,其对特征之间的距离的计算以及相似性(如余弦相似度)的计算均是依赖于欧氏距离计算的,而独热编码刚好对应到N维欧氏空间中,例如一个平面就是二维欧氏空间,一个立方体就是三维欧氏空间(可见例子),以此类推,如果加上时间维度那就算是四维欧氏空间了,但继续增加维度就只能抽象地去想象该欧氏空间的状态了,但该空间构造完成后,其中每一个取值都将是空间中的一个点

 如果是个三维欧氏空间,其实就是特征B的取值1:(0,1,0)这种在空间上找到对应的点,再找到特征B的取值2:(0,0,1),计算欧氏距离即可当成该特征的两个取值之间的距离或者叫相似程度,当然也还有很多其他计算方式,这里先不细说,后面再补充。

那对于独热编码也会由他自己的优缺点,比如会使得特征变成稀疏矩阵,什么是稀疏矩阵,零值多的就是稀疏阵,稀疏矩阵的可以通过压缩其表示方式来节省内存空间,常规的机器学习方法都可以只存储稀疏矩阵中的非零值,这种方式需要将稀疏矩阵转换为压缩稀疏行矩阵(CSR阵),原理如下:

\begin{bmatrix} 1 &0 &0 &0 \\ 0& 1 & 0 &0 \\ 0& 0 &0 &1 \\ 0& 0 & 1 & 0 \end{bmatrix}=\left\{\begin{matrix} [1,1,1,1]\\ [0,1,3,2]\\ [0,1,2,3,4] \end{matrix}\right.

其中的[1,1,1,1]是所有非0元素值,[0,1,3,2]是每一行的非零值的索引,[0,1,2,3,4]是每一行之前的非零值个数,其中的最后一个值是所有非零值的个数,这样的话就可以将一个稀疏矩阵用三个数组表示出来,实现了压缩其占用的内存的目的。目前sklearb的api基本都可以接受CSR矩阵输入,且与原始数据相比,稀疏矩阵无论是内存/磁盘还是训练耗时都有减少,且在LR与GBDT等模型上效果较好,但在线性支持向量机上效果一般。

另外提一嘴,pandas就是将0值都存到内存上去的,所以数据量一旦大起来,pandas会非常地占内存和磁盘,运行速度也会变慢,但是稀疏矩阵的方式确实可以将0值去掉,以CSR的形式存在内存中,这样去参与模型的训练也会更快。

另一方面由于one-hot会增加特征维度,可能会出现维数灾难,甚至特征维数大于样本量的情况,这将会造成过拟合,因此要配合特征工程进行降维,简单介绍维度过多的几种情况,比如KNN算法在高维空间中将会很难度量其真实距离,因为一个高维空间上的分类器,更倾向于表现地更复杂,其决策边界可能过于曲折,以至于将错误的样本也学习到了,这样的分类器固然在训练数据集上表现更好,但是泛化能力差,无法投入测试集上实际使用。

举个例子如下,假设有一个特征,它的取值范围D在0到1之间均匀分布,并且对狗和猫来说其值都是唯一的,我们现在利用这个特征来设计分类器。如果我们的训练数据覆盖了取值范围的20%(e.g 0到0.2),那么所使用的训练数据就占总样本量的20%。上升到二维情况下,覆盖二维特征空间20%的面积,则需要在每个维度上取得45%的取值范围。在三维情况下,要覆盖特征空间20%的体积,则需要在每个维度上取得58%的取值范围...在维度接近一定程度时,要取得同样的训练样本数量,则几乎要在每个维度上取得接近100%的取值范围,或者增加总样本数量,但样本数量也总是有限的。

这个例子说明,随着维度增加,想要获取占总体百分比相等的训练数据,需要比更低维度上付出更大的代价,否则就可能会陷入过拟合。

另外提一下,随着维数的增加,单位空间内分布的样本数量变少了,所以需要扩大样本量来支持模型训练或者在低维上扩大取值范围,并且数据在边缘上的分布密度比空间中心要大。

回到问题上来,那如果就是维度很高了,怎么办呢?更有甚者,你只有两个特征,一个连续的,一个离散的,离散的这个有3000个类别,经过one-hot后,会发现出现了3001个特征,那很离谱啊,那个连续特征的影响会被缩小,该怎么处理呢?经过我的调研和收集网上资料,除了常规的经验筛选,按规则合并以外,还给出了以下几种思路,但是具体效果还有待大家一起探讨:

A.将特征取值的出现频率变成取值,甚至可以进行频率排序,比如特征“归属地”,取值为“中国”,“美国”,“英国”,“印度”等,可以统计不同取值的频率,将占比低的归为一类“其他”,也可以将频率接近的合并为一类,最后再从低到高赋值为1,2,3,4...,再进一步做one-hot编码

B.可以one-hot后,再进行降维,降维方式可以采用常规降维如PCA、LDA等,也可以用聚类来降低维度,总之就是无监督学习减少无用的维度

C.做Hash Trick,再取mod,这个方式就是要自己设计一个hash函数(当然很多地方都已经有对应的hash函数了,可以直接用),hash结束后取模即可降维

D.以结果为导向进行特征选择等~

但是one-hot毕竟还是分裂成了如此多的特征列,所以其实还是占内存很高的,特别是没有做CSR的话更高,那还有一种方式,Binary即二进制编码方式,其特征列相对少一些,会节省一点存储,其编码方式为1->001,2->010,3->011,纯粹就是二进制的编码方式而已,没什么特别的。

2.4高维组合特征

特征工程时,我们不仅仅针对单一特征做处理,往往为了获取特征组合的复杂特征,还要了解特征的组合与选择的技巧,比如“天气”,“心情”这两个变量,对“是否出门”的影响,天气有:晴天,雨天2个取值,心情有:好,坏2个取值,那么这两个特征对出门情况的影响如下:

是否出门天气心情
1晴天
0雨天
0晴天
0雨天

那对其进行组合,组合特征的影响就可以得到了:

是否出门天气=晴天,
心情=好
天气=雨天,
心情=好
天气=晴天,
心情=坏
天气=雨天,
心情=坏
01000
10100
10010
00001

但是有一个问题就是,这样组合出来的特征更加高维了啊,那又回到了最初的问题,降维或者特征选择,降维可以采用PCA,LDA或者SVD分解。

或者做组合特征,不要盲目去把所有特征都进行组合,例如可以使用决策树进行特征组合,比如利用GBDT进行组合特征,也就是利用决策树进行训练,最后训练和验证完成后,将树模型从根节点到叶节点进行一次组合,就可以得到一组特征~

文本特征

词袋模型与N-gram

所谓的词袋模型就是对一整篇文章进行分词,得到的无序词袋就是一种词袋模型,每篇文章就是一个长向量,每个词都是向量的一维,然后既然词语是无序的,那最起码要有重要性的区别吧,设计一个权重来代表某个词语的重要性,权重就是TF-IDF(称之为词频*逆文档频率),具体来说也就是,TF指的是某个词在该文章中的频率,这很好理解,出现的越频繁,在该文章的重要程度越高吗,但是有很多常见词的频率会比较高,要降低这类词的影响,因此要加上IDF,IDF是指文章总数/(包含该单词的文章总数+1),其实也就是这个单词在所有文章中占比大小,就是指单词的通用程度,从公式上看,通用程度越高,说明越不重要,分母上看就越大,IDF就会越小,想一想也是哈,越常见的词就越不重要~比较直观~

另外就是有时不可以仅仅考虑词本身,还考虑词组(N-gram),可以把词组也当成一个单独的特征放到向量中去,也作为单独的一维,当词语有多形同义词,如dogs,dog,那就可以采用两种常见的方式来对其进行意义统一处理,1是词干抽取,这就是只抽取其主干部分来代表其主要含义(例如dogs的主干就是dog),2就是词形还原,就是将任意形式的词语还原为最一般的词形(一般是使用频率最高的那个词性,例如dog就比dogs更常用)。

但是词句都是文本,无法被计算机识别,所以还是要进行文本转数字,或者叫文本转向量,这种转换被称为词嵌入,常见的方式就是,一个词对应一个K维向量,那一个拥有N个词的句子,就表现成一个N*K的矩阵,但是如果直接将这个矩阵作为输入来代表该文章,效果就不会太好,因为要做特征提取,一般采用深度网络来提取特征~

词嵌入常见的方法有Word2Vec:

三、模型评估

3.1评估指标的局限性

3.1.1准确率的局限性:

准确率指的是分类正确的样本占总样本个数的比例,即:

ACC=N_{correct}/N_{total}

容易因为正负样本不均衡,导致ACC不准确。

可以考虑召回率Recall和精确率Precision,RC召回率又可以称为查全率,也就是查全所有正例的概率,PR精确率则成为查准率,这才是对正例的查准的概率。

PR曲线的话,其实可以这样理解,想一想,二分类模型的输出值是在[0,1]区间内的,那么想实现二分类的结果,就要取一个0-1之间的数作为阈值,而这个阈值的选取将会影响到RC与PR的大小。将RC作为横轴,PR作为纵轴,此时每一个阈值对应的RC与PR都将对应到一个坐标点,将这些点连起来,就形成了PR曲线。

从PR曲线上可以了解到,某一个阈值下的RC与PR的值,无法完整地表示出模型的能力,最好绘制出PR曲线图,这样就可以描述出这个模型在不同阈值下的评价指标情况,这比对单一的阈值下的模型的分类能力评价效果更好。

四、回归

4.1介绍一下逻辑回归

(1)逻辑回归属于一种广义线性回归,但它是用来做分类的。传统回归模型输出变量的取值为\left ( -\infty ,+\infty \right ),无法解释分类问题,逻辑回归的输入与传统线性回归没有区别,其参数计算方法可以通过极大似然估计这种数学方式推导出来,也可以用反向传播->梯度下降->降低损失函数的方式训练推导出参数,其中损失函数一般选择交叉熵,看交叉熵的请直接去看Focal loss那里,有详细介绍。

引入激活函数,二分类时是sigmoid,将输出变量取值映射到(0,1)之间,看作是取正例的概率,一般设置阈值为0.5,概率>0.5认为是正例,反之认为是负例。多分类时,激活函数为softmax,将各分类得分做指数变换后进行归一化处理,处理后的值为各分类概率,且其和为1,预测结果为概率最大的类别。

(2)z = w1*x1+w2*x2+w3*x3

其中w是权重,x是0-1变量,z是最终的输出,输出经过激活,得到结果。

sigmoid函数的公式如下:

S(x)=\frac{1}{1+e^{-x}}

其图像如下,可以看到,该函数可以将\left ( -\infty ,+\infty \right )范围上的数映射到(0,1),并且符合值越大,函数值也越大的规律,这样就可以看出概率了,其实这里可以发现sigmoid的形态很容易导致反向传播时的梯度消失,以及出现阶梯性的梯度下降方向,这是它的缺陷,后面这个激活函数就逐渐呗取代了。

softmax函数的公式如下:

S(x)=\frac{e^{x_{i}}}{\sum e^{x_{i}}}

其图像如下:

可以看到softmax也将x映射到了(0,1)上,这个是适用于多分类的激活函数。 

五、集成学习与树模型系列

5.1介绍一下集成算法

集成算法一共有三大类,分别为bagging,boosting,stacking。

其中bagging是一种并联式的集成算法,它是将多个相同的弱学习器通过并联方式形成强学习器,其中各个弱学习器是相互独立的,如果是分类问题,那么结果为各个弱分类器的投票所得,如果是回归问题,其结果是各个弱学习器的平均所得,比如随机森林算法。

Boosting是一种串联式的集成算法,它是将多个相同的弱学习器通过串联方式形成强学习器,首先用第一个弱学习器对数据进行拟合,但单个弱学习器不能完整地解释信息,会存在一定误差,故需要用第二个弱学习器对误差进行拟合,并以此类推,迭代下去,直到误差收敛到设定的阈值,比如真实值为1000,第一个弱学习器的预测值为900,第二个弱学习器的目标就是1000-900 = 100,若第二个弱学习器的预测值为90,第三个弱学习器的目标就是100-90 = 10,若第三个弱学习器的预测值为9,且设定的阈值为5,则误差为10-9 = 1,已经达到了要求,故收敛。然后将前面三个弱学习器串联起来形成强学习器,这就是boosting的全过程。常见的算法有Adaboost、GBDT、XGBoost与lightGBM。

Stacking就是将多个不同的弱学习器组合在一起,将他们的输出结果作为输入传入一个新的学习器中去,输出结果作为最终结果。

5.2介绍一下树模型系列。

5.2.1决策树:

决策树可以分为分类树和回归树,其中分类树有ID3树,ID4.5树以及CART树,ID3树中间节点的特征选择是根据信息增益,ID4.5树中间节点的特征选择是根据信息增益率(信息增益/特征自身的信息熵),CART树中间节点的特征选择是根据GINI系数得到的,并且是二叉树,其预测结果是根据各个叶子节点的值投票所得;回归树的中间节点的特征选择是各个节点的方差,方差越小越好,其预测结果是根据各个叶子节点的值平均所得。

对于CART(Classification and Regression Tree,CART)树来说,其是一种经典的二叉决策树,可以用来处理涉及连续数据的分类或者回归任务。其中CART回归树的思想大概是:将自变量的取值空间二叉分化,不断去切分为若干个碎块,并假设这个空间碎块内的所有样本的因变量取值接近(甚至相同)。

5.2.2随机森林:

随机森林是一种bagging集成算法,是由很多棵CART树组成的,每棵树相互独立,构成每棵树样本是从总体中通过boostrap重抽样所得,特征为随机抽样所得,特征数一般为总特征数的四分之三,决策树的数目可由网格搜索得到,最终形成随机森林,当进行分类时,预测结果由各棵树结果投票决定,当进行回归时,预测结果由各棵树结果平均得到。

当不限制树的生长规模时,它可以一直向下生长,直到不能生长,这样即便对于每个样本都进行很好的拟合,但明显与事实不符,出现了过拟合现象,就需要对其进行剪枝,剪枝又分为预剪枝和后剪枝,预剪枝是对模型设定最大深度、最大叶子节点数等阈值限制树的生长,后剪枝则是通过一定的衡量标准即(损失+α*叶子节点数),这样就既要求损失小,又要求叶子节点数少。

5.2.3Adaboost:

Adaboost是一种boosting集成算法,它是由多个弱学习器(决策树)串联而成,若进行分类,则首先用一颗决策树对样本进行拟合,对于此次预测错误的点,增加它的权重,扩大这些样本点的影响,将新样本输入到新的树中去,继续进行拟合和预测,以此类推,直到迭代完毕,然后将这些决策树按照预测效果的好坏,为各棵树赋权,组合成强学习器Adaboost。

5.2.4GBDT:

GBDT称为梯度提升决策树,它是一种boosting集成算法,这里的梯度其实就是损失函数的负梯度-\frac{\partial L}{\partial f(x))},当损失函数为L=\frac{1}{2}(y-f(x))^{2}时,负梯度恰好为残差y-fx,第一次学习是用样本拟合一棵决策树,然后第二次学习就是对上一次产生的梯度进行拟合,以此类推,直到迭代完毕,最终将第一个决策树+后面的决策树乘以对应的步长得到最终的强学习器GBDT,步长要求在0到1之间,步长越小迭代次数也越多。

5.2.5XGBoost:

Xgboost是一种boosting集成算法,是GDBT的改进方法,是通过多个二叉决策树串行而成,GBDT的核心在于后面的树拟合的是前面预测值的残差,这样可以一步步逼近真值。然而,之所以拟合残差可以逼近到真值,是因为损失函数为平方损失,如果换成是其他损失函数,使用残差将不再能够保证逼近真值。XGBoost的方法是,将平方损失函数做泰勒展开到第二阶,使用前两阶作为改进的残差,并且对损失函数加入了正则化惩罚项,限制了叶子节点个数以及叶子节点权重,限制了模型复杂度,避免了过拟合。传统GBDT使用的残差是泰勒展开到一阶的结果,因此,GBDT是XGBoost的一个特例;此外XGBoost中每个决策树中间节点的选择为根据损失函数算出的信息增益决定。

优点:

精度更高:GBDT 只用到一阶泰勒展开,而 XGBoost 对损失函数进行了二阶泰勒展开。XGBoost 引入二阶导一方面是为了增加精度,另一方面也是为了能够自定义损失函数,二阶泰勒展开可以近似大量损失函数;

灵活性更强:GBDT 以 CART 作为基分类器,XGBoost 不仅支持 CART 还支持线性分类器,使用线性分类器的 XGBoost 相当于带L1和L2正则化项的逻辑斯蒂回归(分类问题)或者线性回归(回归问题)。此外,XGBoost 工具支持自定义损失函数,只需函数支持一阶和二阶求导;

正则化: XGBoost 在目标函数中加入了正则项,用于控制模型的复杂度。正则项里包含了树的叶子节点个数、叶子节点权重的   范式。正则项降低了模型的方差,使学习出来的模型更加简单,有助于防止过拟合,这也是XGBoost优于传统GBDT的一个特性。

列抽样:XGBoost 借鉴了随机森林的做法,支持列抽样(训练时可以只考虑一部分特征),不仅能降低过拟合,还能减少计算。这也是XGBoost异于传统GBDT的一个特性;

缺失值处理:对于特征的值有缺失的样本,XGBoost 采用的稀疏感知算法可以自动学习出它的分裂方向;

缺点:计算量大、消耗内存。

5.2.6lightGBM:

lightGBM算法是XGBoost的改进算法,相较于XGBoost算法,lightGBM在保证了模型效果的同时,大大加快了优化拟合速度。lightGBM采用了直方图算法,先将特征值离散化成k个整数,然后构造宽度为k的直方图,将数据进行装桶,在每个bin中对数据进行梯度累加和个数统计。分桶过后以每个bin为单位遍历的分裂点会少很多,减少了计算量。同时在分裂时,采用直方图做差加速,比如左节点为一二两个bin,那么其他bin就分到另一个节点。使用单边梯度抽样算法(GOSS),根据样本的权重信息对样本进行抽样,减少梯度小的样本,在计算增益时为梯度小的样本增加一个常数进行平衡,使得数据集分布不发生太大改变。如果多个指标之间互斥程度较大(大多数数据不同时非零),可将这些指标进行捆绑降低特征维度。特征合并算法,其关键在于原始特征能从合并的特征中分离出来。通过在特征值中加入一个偏置常量来解决。比如要融合A,B两个特征,A取值为[0,10],B取值为[0,20],给B加上一个偏置10,两个变量就没有重回部分了,就可以放心融合了。用带深度限制的Leaf-wise算法去生成树,每次分裂都找到增益最大的那个叶子节点进行分裂,而不是逐层分裂,lightGBM支持类别特征,不需要做独热码转换。避免独热码转换造成的特征稀疏问题,训练效果较好。lightGBM支持特征并行,不同于XGBoost对数据特征进行划分,在不同的机器上进行分割,最后机器间进行通信,增加了额外复杂度,lightGBM直接在同一台机器上保存全部数据,然后分块并行处理得到最佳方案,节省了通信时间。另外还支持数据并行,数据分块进行划分再组合到一起。基于投票的数据并行则进一步优化数据并行中的通信代价,使通信代价变成常数级别。在数据特征数量很大的时候,使用投票并行的方式只合并部分效果好特征的直方图从而达到降低通信量的目的,可以得到非常好的加速效果。

优点:

速度更快

(1)lightGBM 采用了直方图算法将遍历样本转变为遍历直方图,极大的降低了时间复杂度;

(2)lightGBM 在训练过程中采用单边梯度算法过滤掉梯度小的样本,减少了大量的计算;

(3)lightGBM 采用了基于 Leaf-wise 算法的增长策略构建树,减少了很多不必要的计算量;

(4)lightGBM 采用优化后的特征并行、数据并行方法加速计算,当数据量非常大的时候还可以采用投票并行的策略;

(5)lightGBM 对缓存也进行了优化,增加了缓存命中率;

内存更小

(1)lightGBM 采用了直方图算法将存储特征值转变为存储 bin 值,且不需要特征值到样本的索引,降低了内存消耗;

(2)lightGBM 在训练过程中采用互斥特征捆绑算法减少了特征数量,降低了内存消耗。

缺点:

(1)可能会长出比较深的决策树,产生过拟合。因此lightGBM在Leaf-wise之上增加了一个最大深度限制,在保证高效率的同时防止过拟合;

(2)Boosting族是迭代算法,每一次迭代都根据上一次迭代的预测结果对样本进行权重调整,所以随着迭代不断进行,误差会越来越小,模型的偏差(bias)会不断降低,所以会对噪点较为敏感;

(3)在寻找最优解时,依据的是最优切分变量,没有将最优解是全部特征的综合这一理念考虑进去;

六、神经网络系列

6.1ResNet怎么解决梯度消失、梯度爆炸和网络退化问题

 讲到梯度问题就首先介绍一下神经网络的反向传播,上图是一个简单的3层神经网络,我们都知道,神经网络收敛的目标就是损失函数L最小,那损失函数是怎么得来的,最简单的,就是L(p,y),其中p是预测值,y是真实的标签值,所以损失要想最小,取决于谁?显然是取决于p预测值,因为y真实值是不能调节的。

那么预测值p又来自于什么,上图来看p=sigmoid(z),所以,L的大小取决于p,p的大小取决于z,所以L=L(sigmoid(z)),那如果要想L尽可能小,应该看z怎么变化,才会使得L变小吧,我们反向传播就是为了调节z的大小,使得L也往小的方向变化。

那就求导,L对z求导,看z对L是正向还是反向的影响,\frac{\partial L}{\partial z},若该导数大于0,显然,z增大,L就会随之增大,因此,我们希望z减小,那减小多少呢,实际上,减小任意一个常数都行,因为后面会一遍一遍地反向传播来调整参数,即使这次调多了,下次还会往回调一点,直到L的大小进入可接受的范围内才收敛,但是这样随便拿一个常数来作为调节量,有点太粗糙了,我们还是希望调节量和梯度挂钩比较好,大家都知道,梯度就是z从当前值可以使得L最小的z值 的方向,的奔跑速度,那肯定是梯度绝对值越大,意味着你需要的速度也就要越快,理应用一个比较大的数才好,怎么能需要跑的快的,和需要跑的慢的,都用同一个奔跑速度(调节量不也就是与速度正相关的嘛)呢,这里我们干脆就用梯度本身(注意,梯度本身就是可正可负的了)乘以一个正系数\lambda就行了,所以最后对z应该怎么更新呢,就用原来的z加上调节量呗(或者叫增量,注意增量与梯度一致,所以它也是可正可负的),最后z的更新公式就如下:

 z=z-\lambda \frac{\partial L}{\partial z}

显然上面的\frac{\partial L}{\partial z}如果大于0,L和z就是正向的函数关系,L就应该与z同向变动,而更新公式中的z此时会减去一个正数,z就会变小,L与z同向变动,所以L也减小!!!!没有比这个说的更好懂的了吧。

这里知道了z的调节公式,但是z是不能直接改变的,我们需要作用到z的决定因素上,通过改变其决定因素来改变z的值,那z怎么变由谁决定呢?显然z=y1*w5+y2*w6+b(上图没有强调偏置项b,这个可以先不看),那么可以看出z的变动,要由y1,y2,w5,w6决定,立即推---->>>求导,先以w5为例子,得到\frac{\partial z}{\partial w_5},那求导完,看什么,看导数是否大于0呗。

若该导数大于0,说明w5与z同向变动,这时候你要考虑到z需要怎么变动,那就看一下上一层调节公式的增量吧,那里有z需要变动的方向的信息,增量就是-\lambda \frac{\partial L}{\partial z},若增量大于0,说明z需要增大,而\frac{\partial z}{\partial w_5}也大于0的话,就希望w5可以增大,因为w5增大,就可以实现z增大的目标了,那我们就把w5的更新公式设置如下:

w_5=w_5+\frac{\partial z}{\partial w_5}(-\lambda \frac{\partial L}{\partial z}),then, w_5=w_5-\lambda\frac{\partial L}{\partial z}\frac{\partial z}{\partial w_5}

 来解析一下这个更新公式:

-\lambda \frac{\partial L}{\partial z}大于0,\frac{\partial z}{\partial w_5}大于0,\frac{\partial z}{\partial w_5}(-\lambda \frac{\partial L}{\partial z})就大于0,w5加上就会增长,此时z会随之增长(正向函数关系),L会随之减小(注意增量大于0,L对z的导数刚好与之相反,是小于0的哦),正是我们想要的;

-\lambda \frac{\partial L}{\partial z}大于0,\frac{\partial z}{\partial w_5}小于0,\frac{\partial z}{\partial w_5}(-\lambda \frac{\partial L}{\partial z})就小于0,w5加上就会减小,此时z会随之增长(负向函数关系),L会随之减小(L对z的导数小于0),符合目标;

-\lambda \frac{\partial L}{\partial z}小于0,\frac{\partial z}{\partial w_5}大于0,\frac{\partial z}{\partial w_5}(-\lambda \frac{\partial L}{\partial z})就小于0,w5加上就会减小,此时z会随之减小(正向函数关系),L会随之减小(L对z的导数大于0),符合目标;

-\lambda \frac{\partial L}{\partial z}小于0,\frac{\partial z}{\partial w_5}小于0,\frac{\partial z}{\partial w_5}(-\lambda \frac{\partial L}{\partial z})就大于0,w5加上就会增长,此时z会随之减小(负向函数关系),L会随之减小(L对z的导数大于0),符合目标;

 对于y1来说,也是一样的,因为w5和y1就是可以看成相互的,w5可以是y1的系数,反过来y1也可以看成w5的系数,因此y1的更新公式如下:

y_1=y_1+\frac{\partial z}{\partial y_1}(-\lambda \frac{\partial L}{\partial z}),then, y_1=y_1-\lambda\frac{\partial L}{\partial z}\frac{\partial z}{\partial y_1}

 那y1又是取决于前面的w1,w2,x1,x2的,这就是相当于递归重复上面的过程即可,显然x1,x2就是最初的输入值了,他们的值是无法改变的,只能调节w1,w2的值了。

要调节y1,就传导到调节w1,w2了,以w1为例,w1的更新公式应该为:

w_1=w_1-\lambda\frac{\partial L}{\partial z}\frac{\partial z}{\partial y_1}\frac{\partial y_1}{\partial w_1}

其他的参数的更新原则与上面的一致,那么最后来总结一下,整个反向传播的过程吧,首先以L最小化为目标,L=L(p)=L(sigmoid(z)),直接L对z求导,希望调节z的值,但是z是由其他参数推出的,z=w5*y1+w6*y2,z的大小就取决于w5,w6,y1,y2的大小,z就应该对这四个值求偏导,来看他们怎么变才能让z变成可以使得L最小的值。。。说的有点绕口,但是就是这么个意思,w5,w6在这一次求导中就可以更新了,因为它们俩可以自己自发地调节,不受什么别的参数的影响,但是y1,y2不行,y1=w1*x1+w2*x2,y2=w3*x3+w4*x4,所以要调节y1就落到了调节w1,w2,x1,x2上来,显然x1,x2已经是输入值了,他们就是原始数据,无法调节,只调节w1,w2就行了,y2同理,只调节w3,w4就行了。

到了这里基本就完成了一次反向传播了,调节完了之后呢,计算一次Loss,看看有没有收敛(就是有没有进入我们设的阈值范围内),收敛了就结束,没收敛就再来一次反向传播,很多时候预训练模型就是调整了很多很多次,得到的很不错的模型参数,我们再把自己的数据输进去,按照我们的数据,对参数做一做微调就行了,这就是所谓的迁移学习。。。

从数学上来看,上式称为链式求导法则,什么意思呢,就比如w1的调节公式,L=L(sigmoid(z)),L=L(sigmoid(w5*y1+w6*y2))=(w5*sigmoid(w1*x1+w2*x2)+w6*sigmoid(w3*x3+w4*x4))

没错,每一次神经元内计算,都会激活一下,这里每次运算其实都要加上激活函数的,那么要调节w1来使得L变小,是不是就应L对w1求偏导,根据链式求导法则,就有

 \frac{\partial L}{\partial w_1}=\frac{\partial L}{\partial z}\frac{\partial z}{\partial y_1}\frac{\partial y_1}{\partial w_1}

 这个东西,乘以学习率\lambda(没错,公式里的那个\lambda就是学习率,可以看出来\lambda越大就会奔跑速度越快,也就越快收敛,但是也容易跑过头,也就是直接跳过了最低点,甚至出现来回震荡的现象,\lambda小一点就不容易跑过头,但是,跑的太慢了,这啥时候能收敛啊,所以学习率要设置成适当的大小,一般就是0.001~0.01之间)就是我们每次反向传播对对应的wi更新的增量值了~是不是超简单超清楚,看到这里,麻烦动动您的小手,点一波关注吧,整理和解析不易~谢谢~ 

好了前面说明白了反向传播,再来看梯度消失问题就简单多了,想一想,假如那个每次求导的导数都很小怎么办,那就是梯度很小咯,梯度很小,比如0.1,就反向传播一层还好哈,那就是对这一层上,对应的w值调节个0.1*\lambda,那也还行哈,但是想一想,每一层都是0.1会怎样,往前传个10层,0.1的10次方,这也太小了吧。直接就不会对前面的层上的w做更新了哎,那个调节增量也太小了,可以忽略不计了吧,对吧,那我搞这么多层还有啥意义,我只调节最后几层,那不如就用浅浅的几层算了,对吧,不需要加深网络了,说到这里就有一个问题,梯度大小和谁有关系,其实就是和激活函数还有对应的那个w乘上的y值有关嘛,但是y值吧,如果很小或者很大肯定也有影响,但激活函数的斜率影响也很大,比如sigmoid函数,这个函数一旦横轴大一点或者小一点,斜率就直接消失了,这那就是一个极小的值,甚至可以叫,无穷小的梯度值,它乘以任何常数都是无穷小,所以,用sigmoid做激活函数,就容易出现梯度消失问题。。。后面就换成了ReLU了,它就是只要输入值是正数(实际上图像上都是正数的,即便有一些输出经过反向传播,在某一层输出成了负数,那就更新出少量的0输出,就相当于对这个神经元进行Dropout一样了,还有助于缓解过拟合。。。并且也不影响大局~我个人的理解是这样),扯远了,不过这也说明白了啥是梯度消失了,梯度消失就是因为某些层的梯度很小很小,累积相乘之后,直接让前几层的梯度消失了(趋于0),就不更新前面的层了,这样不好,非常不好,不符合我们深度学习的深度二字之精髓~

于是何凯明大神就横空出世,他说要有光~于是便有了光。。。哦,不是,便有了ResNet,哈哈。残差结构如下图所示:

未完待续。。。

X_L=\sum_{i=l}^{L-1}F(x_i,W_i)

X是输入值,F(x)相当于residual,它只是普通神经网络的正向传播;输出是这两部分的加和H(x) = F(x)(就是residual)+x(就是shortcut,shortcut部分可以做一次卷积,也可以不做);之所以可以避免梯度消失问题,是因为反向传播时,ε代表的是loss 方程,由链式求导法得:

\frac{\partial \varepsilon }{\partial x_l}=\frac{\partial \varepsilon }{\partial x_L}\frac{\partial x_L}{\partial x_l}=\frac{\partial \varepsilon }{\partial x_L}(1+\frac{\partial }{\partial x_l}\sum_{i=l}^{L-1}F(x_i,W_i))

可以看出,反向传播的梯度由2项组成的:

  • 对x的直接映射,梯度为1;
  • 通过多层普通神经网络映射结果为:\frac{\partial }{\partial x_l}\sum_{i=l}^{L-1}F(x_i,W_i)

即使新增的多层神经网络的梯度\frac{\partial }{\partial x_l}\sum_{i=l}^{L-1}F(x_i,W_i)为0,那么输出结果也不会比传播前的x更差。同时也避免了梯度消失问题。

6.2Transformer

初始文章:Attention is all you need

1.提出了一种transformer结构,所谓transformer就是指多次堆叠encoder与decoder,其中encoder与decoder包含了多头注意力机制,层级归一与残差结构。

多头注意力,取代了之前的seq2seq的编码解码结构中使用的递归层。

那什么是seq2seq结构呢?

seq2seq模型一般是在输出的长度不确定时,采用的模型,比如将一句英文翻译成中文,那这句中文可能比英文短,也可能比他长,所以就不确定输出的长度。

那最常见的seq2seq其实又是由2个rnn网络构成的,一个rnn作为encoder,一个rnn作为decoder,那我们再来解析rnn网络:

rnn网络从何而来,相比于传统的神经网络,有何优势与劣势,首先传统的神经网络是只有输入与输出,这对于前后没有关系的输入来说,是可行的,比如输入的是一组产品,输出的是一组价格,先输入的与后输入的,没有什么关系,谁先输入都一样,所以我们直接用传统网络就可以解决了,那如果前后是有关系的就不行了,要考虑前面的值对后面的值的影响,例如一个简单的词性分类任务,比如我吃苹果,我 作为输入,输出 我\nn(名词),吃 作为输入,输出 吃\v(动词),苹果 作为输入,输出 苹果\nn(名词),但是吃的后面,一般接的是 名词,所以在吃后面的 苹果 一词,会因为其在吃 的后面,被分类为名词的概率增加,这就是利用到了前一次输入的信息,包括视频分析也是这样,视频的前一帧与后一帧,也存在着类似的关系。

首先是输入,将几个不同word经过word2vec训练成几个词向量X,

接着是进入Encoder模块,Encoder模块包括self-attention与FFNN两部分,

X经过线性变换,即X*Wq,X*Wk,X*Wv,得到q,k,v向量,

计算score=q*k,

为了梯度稳定,score要进行归一化,score=score/根号下的k的长度,

词向量X有多个,所以score也有多个,就可以对score进行softmax处理得到soft-score,

令soft-score*v得到新的v,

令v求和,得到z,

这就完成了self-attention了,接着进入Encoder的下一个模块,Feed Forward Neural Network,简称FFNN,

FFNN就是两层全连接,第一层输出后进行ReLU激活,第二层输出进行线性激活即可,

这就是从Encoder出来了,紧接着就是Decoder,

Decoder与Encoder区别在于,在self-attention与FFNN之间有一块Encoder-Decoder Attention,

Decoder就是输入是上一次的输出,比如I love you.

I先进入Encoder,然后经过Decoder,再输出就是love,那

七、聚类

7.1K-means聚类

  k-means算法是一种非监督算法,kmeans算法又名k均值算法,K-means算法中的k表示的是聚类为k个簇,means代表取每一个聚类中数据值的均值作为该簇的中心,或者称为质心,即用每一个的类的质心对该簇进行描述。

其算法思想大致为:第一步:先从样本集中随机选取 k个样本作为簇中心,并计算所有样本点与这 k个“簇中心”的距离,对于每一个样本点,将其划分到与其距离最近的“簇中心”所在的簇中。第二步:对于新的簇计算均值作为簇的新的“簇中心”,并将相比其他簇距离ci 簇最近的样本点划分到此簇所在的类中。以此一直迭代,直至达到迭代次数或者误差达到设定的阈值。

优点:

 1.理论成熟,思想简单,既可以用来做分类也可以用来做回归。

 2.可用于非线性分类 。

 3.适用于样本容量比较大的类域的自动分类。

缺点:

 1.计算量大,分类速度慢

 2.KNN在对属性较多的训练样本进行分类时,由于计算量大而使其效率大大降低效果。

 3.K值难以确定 :目前没有很好的方法,一般采用先定一个初始值,然后根据实验测试的结果调整K值,并且聚类结果受初始值影响很大

 4.对不平衡样本集比较敏感:当样本不平衡时,有可能导致当输入一个新样本时,该样本的K个邻居中大容量类的样本占多数。

7.2DBSCAN聚类

DBSCAN是一种基于密度的聚类算法,聚类的时候不需要预先指定簇的个数,最终簇的个数不确定。这类密度聚类算法一般假定类别可以通过样本分布的紧密程度决定。同一类别的样本,他们之间是紧密相连的,在该类别任意样本周围不远处一定有同类别的样本存在。通过将紧密相连的样本划为一类,这样就得到了一个聚类类别。通过将所有各组紧密相连的样本划为各个不同的类别,则我们就得到了最终的所有聚类类别结果。

DBSCAN算法将数据点分为三类:

1、核心点:在半径Eps内含有超过MinPts数目的点。

2、边界点:在半径Eps内点的数量小于MinPts,但是落在核心点的邻域内的点。

3、噪音点:既不是核心点也不是边界点的点。

DBSCAN算法的流程:

 1.根据邻域条件遍历所有点,将所有点分别标记为核心点、边界点或噪声点;

 2.删除噪声点;

 3.为距离在Eps之内的所有核心点之间赋予一条边;

 4.每组连通的核心点形成一个簇;

 5.将每个边界点指派到一个与之关联的核心点的簇中(哪一个核心点的半径范围之内)。

优点:

可以对任意形状的稠密数据集进行聚类,而Kmeans一般只适用于凸数据集;

可以在聚类的同时发现异常点,对数据集中的异常点不敏感;

聚类效果不像Kmeans那样受初始值的影响。

缺点:

样本集的密度不均匀,聚类间距相差很大时,聚类质量较差,这时用DBSCAN聚类一般不适合;

样本集较大,聚类收敛时间长,此时可以对搜索最近邻时建立的KD树或者球树进行规模限制来改进;

调参相对于Kmeans稍显复杂,需要对距离阈值和样本阈值进行联合调参,不同的参数组合对最后的聚类效果有很大影响。

八、降维

8.1介绍一下线性判别分析(LDA)

线性判别分析是一种有监督学习方法,LDA的主要思想是:给定训练集,想办法将这些样本投影到一条直线上,使得投影后同类的样本尽可能靠近,不同类的样本尽可能远离;在对新样本进行分类时,将其投影到同样的这条直线上,再根据投影点的位置来确定新样本的类别。

线性判别分析的目标就是找到这样一条直线,使得投影后满足:“类内差异小、类间差异大”。类内差异我们可以用同一个类的方差来衡量,方差越大表示数据波动越大,差异越大,反之差异越小;类间差异可以用两个类的均值向量之间的距离来衡量,如果两个类的均值向量距离较大,表明它们相距越远,差距越大。因此,线性判别分析的目标函数为:

优点:在降维过程中可以使用类别的先验知识经验。

缺点:当总共有K个类别时,LDA最多降到K-1维。

8.2介绍一下主成分分析(PCA)

主成分分析是一种无监督学习方法,PCA是比较常见的线性降维方法,通过线性投影将高维数据映射到低维数据中,所期望的是在投影的维度上,新特征自身的方差尽量大,方差越大特征越有效,尽量使产生的新特征间的相关性越小(相互独立)。PCA算法的具体操作为对所有的样本进行中心化操作,计算样本的协方差矩阵,然后对协方差矩阵做特征值分解,取最大的n个特征值对应的特征向量构造投影矩阵。

优点:

仅仅需要以方差衡量信息量,不受数据集以外的因素影响;

各主成分之间正交,可消除原始数据成分间的相互影响的因素;

计算方法简单,主要运算是特征值分解,易于实现。

缺点:

主成分各个特征维度的含义具有一定的模糊性,不如原始样本特征的解释性强;

方差小的非主成分也可能含有对样本差异的重要信息,因此降维丢弃可能对后续数据处理有影响。

九、其他算法

9.1介绍一下支持向量机

支持向量机是一种二分类模型,它的基本模型定义在特征空间上的间隔最大的线性分类器,间隔最大使它有别于感知机;支持向量机还包括核技巧,这使他成为实质上的非线性分类器。支持向量机的学习策略就是间隔最大化,可形式化为一个求解凸二次规划的问题,也等价于正则化的合页损失函数的最大化问题。支持向量机的学习算法是求解凸二次规划的最优化算法。简单来说SVM就是,在特征空间上找到最优超平面使得数据的正负样本间隔最大。

支持向量机的目标函数为:

放缩变换:对于决策方程(w,b)可以通过放缩使得其结果值|Y|>=1

                => y_{i}(w^T\Phi (x_{i})+b)>=1

优化目标:\underset{w,b}{arg max}\left \{ \frac{1}{\left | \left | w \right | \right |} \underset{i}{min} [y_{i}(w^{T} \Phi (x_{i})+b)]\right \}

                由于y_{i}(w^T\Phi (x_{i})+b)>=1,只需要考虑\underset{w,b}{argmax}\frac{1}{\left | \left | w \right | \right |} (目标函数搞定)

为什么要引入核函数:

当样本在原始空间线性不可分时,可将样本从原始空间映射到一个更高维的特征空间,使得样本在这个特征空间内线性可分。常见的核函数有多项式核函数和高斯核函数。

多项式核函数:多项式核函数可以实现将低维的输入空间映射到高纬的特征空间,但是多项式核函数的参数多,当多项式的阶数比较高的时候,核矩阵的元素值将趋于无穷大或者无穷小,计算复杂度会大到无法计算。

高斯核函数:高斯径向基函数是一种局部性强的核函数,其可以将一个样本映射到一个更高维的空间内,该核函数是应用最广的一个,无论大样本还是小样本都有比较好的性能,而且其相对于多项式核函数参数要少,因此大多数情况下在不知道用什么核函数的时候,优先使用高斯核函数。

支持向量机如何避免过拟合:(软间隔)

解决过拟合的办法是为SVM引入了松弛变量,

因此SVM公示中的目标函数也需要相应修改,加上松弛变量的平方和,并求最小值。新的目标函数为:

 这样就达到一个平衡:既希望松弛变量存在以解决异常点问题,又不希望松弛变量太大导致分类解决太差。

十、概率图模型

十一、模型优化算法

11.1一般怎样进行超参数的自动调节。

11.1.1网格搜索:

我们在选择超参数有两个途径:1)凭经验;2)选择不同大小的参数,代入到模型中,挑选表现最好的参数。通过途径2选择超参数时,人力手动调节注意力成本太高,非常不值得。所以我们可以通过网格搜索交叉验证调参,它通过遍历传入的超参数的所有排列组合,通过交叉验证的方式,返回所有参数组合下的评价指标得分,选出最优的超参数。它其实就是暴力搜索,这也导致了它在小数据集上很有用,但数据集大了就不太适用了,不过此时可以使用一个快速调优的方法——坐标下降,它其实是一种贪心算法:拿当前对模型影响最大的超参数作为初始值进行坐标下降,直到最优化,坐标下降可以理解为只按着坐标的方向进行优化,相比于梯度下降不同的是,梯度下降是按照指定梯度的方向进行优化的;然后就是再接着拿下一个影响最大的参数作为初始值进行坐标下降,如此下去,直到所有的参数调整完毕。这个方法的缺点就是可能会调到局部最优而不是全局最优,但是省时间省力。

11.1.2随机搜索:

我们在搜索超参数的时候,如果超参数个数较少,那么我们可以采用网格搜索。但是当超参数个数比较多的时候,网格搜索所需时间将会指数级上升。所以就有了随机搜索,这种做法比上面的坐标下降的做法快,而且实验证明,随机搜索法结果也比其稍好。

随机搜索使用方法和网格搜索很相似,随机在超参数空间中搜索几十几百个点,其中就有可能有比较小的值。但他不是尝试所有可能的组合,而是通过选择每一个超参数的几个随机值的随机组合,这个方法有两个优点:

相比于网格搜索,它可以选择相对较少的参数组合数量。如果让随机搜索运行,它会探索每个超参数的不同的值,可以方便的通过设定搜索次数,控制超参数搜索的计算量。

还有就是对于有连续变量的参数时,RandomizedSearchCV会对其进行采样,这是网格搜索做不到的。

11.1.3贝叶斯优化:

假设上面这个是目标函数f,现在想找到使得f最小的超参数,可以直接随机设置几个超参数,然后得出对应的目标函数,然后从目标函数最小的那个超参数附近再采样几个点吗,不行,因为如果恰好在目标函数的局部最优点附近,就会陷入局部最优,而且每次选取超参数去计算目标函数值的时间代价是很高的,这样我们就可以考虑贝叶斯优化来解决这些问题,首先对于时间代价问题,贝叶斯优化采用了简单点的代理模型来代替原来的复杂的模型,代理模型一般是随机从复杂的原模型中采样几个样本特征与其对应的标签,然后通过高斯过程,得出一个代理模型,也就是输出一个高斯过程,具体如下:

绿色实线就是代理模型,绿色范围是输出分布的标准差,贝叶斯优化的后续超参数效果验证就不再是通过原模型进行验证的了,而是根据代理模型来进行效果验证,这样极大地降低了代价。

解决了代价问题,接下来就要解决参数寻优问题了,首先可以看出代理模型上最低点位置应该是我们比较感兴趣的地方,很有可能在这里有全局最优点,但是这也不绝对,还有很多地方没有被探索过,我们应该优先探索那些方差大的区域,这样可以减小我们需要猜测的方差,为了实现猜测范围与最低点之间的平衡,引入了一个采集函数,其中最常见的是expectated of improvement(EI),当均值减少方差增大时,EI会增大,这时就实现了既希望目标函数变小,又希望代理模型最大可能地包含真实值的最优超参数。

还有一些其他智能参数优化算法,比如粒子群优化,遗传算法优化等。

11.2NMS算法

输出结果的NMS非极大值抑制

因为最后输出的预测框可能会有很多个,就从IOU上来看,对于交并比IOU大于0.5的,就很有可能代表的是同样的物体,所以就选择score最大的那个框保留就行了。

十二、采样方法

12.1介绍一下MCMC马尔可夫-蒙特卡洛抽样

讲到MCMC就要先从马尔可夫过程说起,对于一个平稳的马尔可夫链来说,在转移次数足够多时,其必然会收敛到一个平稳的过程,并且转移一次就是进行一次随机游走,随机游走一次传递到的值,可以看作是在一个分布上进行的一次随机抽样,这样一直随机游走下去,就可以看作一次次进行随机抽样,进而实现模拟随机抽样,而所谓蒙特卡洛,就是利用随机抽样来模拟计算问题,MCMC中正是借助马尔可夫链收敛到平稳过程的特性来实现随机抽样的。

十三、AI应用案例分析

13.1文本相似度计算方法

基于关键词的模型:如直接计算词向量的余弦相似度,这只能解决词形的相近,无法解决语义的问题;

基于语义的模型:基于知识语料库的,可能需要自己建设语料库;

基于本体的相似度模型:先根据识别出来的实体信息计算词与词之间的相似性,然后利用词语之间的相似度来计算,文档的相似性;

编辑距离(Levenshtein Distance):

指的是从一个字符串到另一个字符串,所需要的编辑次数,显然越相似的词语或句子,其编辑距离就越小

可以使用动态规划的方法去测量LD的值,步骤大致如下:

  • 初始化一个LD矩阵(M,N),M和N分别是两个输入字符串的长度。
  • 矩阵可以从左上角到右下角进行填充,每个水平或垂直跳转分别对应于一个插入或一个删除。
  • 通过定义每个操作的成本为1,如果两个字符串不匹配,则对角跳转的代价为1,否则为0,简单来说就是:
    • 如果[i][j]位置的两个字符串相等,则从[i][j]位置左加1,上加1,左上加0,然后从这三个数中取出最小的值填充到[i][j]。
    • 如果[i][j]位置的两个字符串不相等,则从[i][j]位置左、左上、上三个位置的值中取最小值,这个最小值加1(或者说这三个值都加1然后取最小值),然后填充到[i][j]。
  • 按照上面规则LD矩阵(M,N)填充完毕后,最终矩阵右下角的数字就是两个字符串的LD值。

本文参考了《百面机器学习》、《百面深度学习》、《机器学习》西瓜书、《统计学习方法》李航、《Deep Learning》花书等教材,并加以自身理解,同时集思广益,参考了网上大量的博客提炼而成,学无止境,会持续更新持续迭代;

最后,各位同行和同学们,有看到我哪里写的有问题,欢迎在评论区或者私信我指出来,我随时在线,此贴也会保持更新,希望大家一起共同学习,共同进步~

  • 15
    点赞
  • 96
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: 机器学习算法工程师面试常见问题包括: 1. 你对机器学习的理解是什么? 2. 你熟悉哪些机器学习算法? 3. 你如何选择合适的算法来解决问题? 4. 你如何评估模型的准确性? 5. 你如何处理样本不平衡的问题? 6. 你对过拟合和欠拟合的理解是什么? 7. 你对深度学习的了解是什么? 8. 你如何使用神经网络解决图像识别问题? 9. 你对计算机视觉的了解是什么? 10. 你如何在实际应用中部署机器学习模型? 回答这些问题需要结合个人经验, 如果没有经验或者知识,需要了解学习相关知识点. ### 回答2: 机器学习算法工程师面试中常见的问题有很多,以下是几个常见问题及回答: 1. 介绍一下机器学习算法中的监督学习和无监督学习。 答:监督学习是通过已有的标签数据进行模型训练,然后预测新数据的标签;无监督学习是在没有标签数据的情况下,从数据中寻找模式和结构。 2. 请解释一下过拟合和欠拟合的概念。 答:过拟合是指模型在训练集上表现很好,但在未见过的数据上表现不佳;欠拟合是指模型过于简单,不能很好地捕捉数据的复杂性。 3. 请简要解释一下交叉验证的原理和作用。 答:交叉验证是将训练集划分成k个不重叠的子集,然后每次选取一个子集作为验证集,其余k-1个子集作为训练集,重复k次,最后取平均值作为模型的性能评估指标。交叉验证可以评估模型的性能,并且可以用于调参和模型选择。 4. 请解释一下决策树算法的原理。 答:决策树算法根据特征的属性值建立一颗树状的分类模型。通过对特征的选择和节点分裂,不断将数据集分割成纯度更高的子集,直到达到停止条件。在进行预测时,根据特征属性值从根节点开始,按照条件判断沿着树的分支下行,最终到达叶子节点得到预测结果。 5. 请介绍一下常用的评估指标,如准确率、精确率、召回率和F1值。 答:准确率指预测正确的样本占总样本数的比例;精确率指所有预测为正的样本中,真实为正的样本的比例;召回率指所有真实为正的样本中,被正确预测为正的样本的比例;F1值综合了精确率和召回率,是一个综合评价指标,计算公式为2 * (精确率 * 召回率) / (精确率 + 召回率)。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不会抓鼠鼠的阿猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值