机器学习面试准备
(部分内容可能需要梯子)
一大波问题:
各种知识收集:
Sparsity and Some Basics of L1 Regularization
常见的几种最优化方法(梯度下降法、牛顿法、拟牛顿法、共轭梯度法等)
- 一阶方法:梯度下降、随机梯度下降、mini 随机梯度下降降法。随机梯度下降不但速度上比原始梯度下降要快,局部最优化问题时可以一定程度上抑制局部最优解的发生。
- 二阶方法:牛顿法、拟牛顿法:
这里详细说一下牛顿法的基本原理和牛顿法的应用方式。(a).牛顿法其实就是通过切线与x轴的交点不断更新切线的位置,直到达到曲线与x轴的交点得到方程解。在实际应用中我们因为常常要求解凸优化问题,也就是要求解函数一阶导数为0的位置,而牛顿法恰好可以给这种问题提供解决方法。实际应用中牛顿法首先选择一个点作为起始点,并进行一次二阶泰勒展开得到导数为0的点进行一个更新,直到达到要求,这时牛顿法也就成了二阶求解问题,比一阶方法更快。我们常常看到的x通常为一个多维向量,这也就引出了Hessian矩阵的概念(就是x的二阶导数矩阵)。缺点:牛顿法是定长迭代,没有步长因子,所以不能保证函数值稳定的下降,严重时甚至会失败。还有就是牛顿法要求函数一定是二阶可导的。而且计算Hessian矩阵的逆复杂度很大。(b).拟牛顿法: 不用二阶偏导而是构造出Hessian矩阵的近似正定对称矩阵的方法称为拟牛顿法。拟牛顿法的思路就是用一个特别的表达形式来模拟Hessian矩阵或者是他的逆使得表达式满足拟牛顿条件。主要有DFP法(逼近Hession的逆)、BFGS(直接逼近Hession矩阵)、 L-BFGS(可以减少BFGS所需的存储空间)。
一些评价指标:
朴素贝叶斯:
- 是一种根据已经有的样本结果,反推最有可能(最大概率)造成这个结果的算子参数.
- 极大似然估计给定了一种给定观察数据来评估模型参数的办法,即解决'模型已定,参数未知'的问题.通过若干次实验,观察实验结果,求解一组参数使得样本出现的概率最大,这就是极大似然估计.
先验概率是根据以往经验和实验分析得到的概率,由因索果.
后验概率是执果索因,根据结果(条件概率就是果)寻找导致结果的原因().
贝叶斯估计就是这样的一种思路,根据学习先验概率和条件概率,从而确定后验概率.
朴素贝叶斯将实例分到后验概率最大的类中,其实就是等价于期望风险最小化.
Q:为什么朴素贝叶斯提出了特征独立这样一个几乎不成立的假设,却依然有着不错的效果?
A: 如果属性间依赖对所有类别影响相同,或者说依赖关系的影响能相互抵消,则属性条件独立性假设在降低计算开销的同时不会对性能产生负面影响
Q:实际情况中概率可能是非常小的数,这样连乘会造成结果溢出,该如何处理:
A:对概率公式取对数,变连乘为连加.
Q:朴素贝叶斯算法的优缺点:
A:增加样本时依然可以收敛很快,即便存在隐变量的情况,依然使用; 缺点:
无监督学习(聚类部分):
机器学习之深入理解K-means、与KNN算法区别及其代码实现
kmeans聚类:
- 在kmeans聚类中还有很多需要注意的点:1. k值的选择,这其实是最为关键的,通常的做法都是通过尝试和感觉.当然在有标签的情况下就完全可以分一部分测试集出来进行测试,这样肯定是能比较准确的. 2. 初始质心的位置对kmeans的影响其实是很大的,通常的做法就是随机重复多次,然后voting 3. 算法受异常点outlier影响很大,因此需要做仔细的数据清洗 4.数据是需要归一化的,这里毕竟用到了距离度量 5.通常来说聚类都只是得到局部最优,当然也可以用优化方法得到全局最优.
- 无法对类别变量进行运算.
- 对异常点,离群值非常敏感,因此也可以用作异常值检测的算法.
评价指标:
- 簇内的紧密程度(CP)
- 簇间的间隔性(SP)
- 邓恩指数(DVI计算任意两个簇元素的最短距离(类间)除以任意簇中的最大距离(类内)). 因此DVI越大,则说明簇间距离越大,簇内距离越小.
- 利用标签进行评价(一开始在某些blog当中看到这种方式的时候还不能理解,现在的理解是虽然是无监督学习,但是本身样本是有标签的,用来衡量是没有毛病的). 这一部分的方法就比较多了,比如纯度purity,熵entropy,准确率accuracy召回率recall都ok,兰德指数ARI
- 簇内误差平方和SSE,用作衡量簇内的紧密程度.
- 西瓜树上还讲到DB指数(任意两个簇的簇内平均距和/簇间中心距, 当然越小越好),Dunn指数(簇间最小距离/簇内最远距离, 当然越大越好).
- 轮廓系数.
LR:
LR的基本原理(概括:逻辑回归是假设数据服从伯努利分布的,通过极大似然函数方法,运用梯度下降求解参数的一种二分类模型)
LR工业应用的技巧:
总结:
- 求解时的优化:(1). 对于LR来说,求解时需要用到梯度下降的方法,这个方法又可以展开分为全量梯度下降,mini-bacth,随机梯度下降; (2). 再往深一层,对于梯度下降时的学习率还可以采用模拟退火的思路,对学习率进行动态的调整,可以有更好的收敛效果 (3).对于最深入的,可以用到动量法, Adam方法,对梯度下降进行优化(Adam方法中⽬标函数⾃变量中每个元素都分别拥有⾃⼰的学习率,并且更新梯度时用到了动量法的思想,每一次更新自变量在各个方向上的更新都考虑了过去梯度在各个方向上是否一致,有效避免了SGD方法带来的梯度的震荡问题[《动手学习深度学习》中有详细讲解]).
- 逻辑回归的优缺点:
- 优点:(1).模型简单,容易实现,并且结果有着很好的可解释性,从特征前面的系数theta就可以看出特征对于结果的影响程度 (2). 只要特征工程能做得比较细致,模型效果通常是不错的(作为baseline) (3).容易并行,这是在工程上非常具有诱惑力的一点 (4). 因为模型简单所以训练速度也很快,如果在学习率theta和梯度下降上作出一些更好的选择和优化则会有更快的速度 (5).内存占用少, 因为仅仅需要存储每一列特征,不像树模型和一些boosting模型还需要将排序后的样本存储起来 (6). 结果很友好,LR区别于SVM,属于一种软分类器,输出分类概率,这样也给留了工程师更大的操作空间.
- 缺点:(1). 模型简单, 因为拟合数据是从线性回归上发展而来,通过sigmoid映射得到结果,并不具备学习复杂问题的能力 (2). 对于样本不平衡的情况是有缺陷的.例如1000:1的情况下,依然是会有接近0的损失函数值 (3). 原始的逻辑回归只能处理线性的问题, 如果需要拟合非线性的问题产生非线性的决策边界则需要加入多项式 (4)本身是没有特征筛选功能的.
3. 对于逻辑回归在应用时,将特征进行离化散是能够有助于提升模型性能.(1)离散化后特征易于管理,方便迭代;稀疏向量内积乘法运算快;(2)连续特征离散化,对异常数据有较强的鲁棒性(如>10岁的300岁),更稳定;(3)LR属于广义线性模型,表达能力受限,离散化后每个变量有单独的权重,相当于引入非线性,提升模型表达能力;(4)离散化后做特征交叉,数量更多,可进一步引入非线性(5)通过“海量离散特征+简单模型”的方式解决,相对“少量连续特征+复杂模型”效率更高,更简单,可n人一起做(6)特征离散化以后,起到了简化了逻辑回归模型的作用,降低了模型过拟合的风险。(当使用连续特征时,一个特征对应于一个权重,那么,如果这个特征权重较大,模型就会很依赖于这个特征,这个特征的一个微小变化可能会导致最终结果产生很大的变化,而使用离散特征的时候,一个特征变成了多个,权重也变为多个,那么之前连续特征对模型的影响力就被分散弱化了,从而降低了过拟合的风险)(7)离散化后,模型会更稳定,比如如果对用户年龄离散化,20-30作为一个区间,不会因为一个用户年龄长了一岁就变成一个完全不同的人。当然处于区间相邻处的样本会刚好相反,所以怎么划分区间是门学问.
Softmax:
SVM(在sklearn中,SVM的核心参数是C,kernal,gamma(RBF核,gamma决定了rbf核映射的作用范围,其实也就是决定了高斯分布的幅宽,gamma越大就越小,就越是能拟合任意非线性数据,但是容易过拟合,gamma越小则高斯分布越是平缓,那么则容易欠拟合;径向基函数则是局部性强的核函数,其外推能力随着参数 σ 的增大而减弱。多项式形式的核函数具有良好的全局性质。局部性较差)):
SVM就是支持向量机,是一种二分类模型,基本模型定义为特征空间上的间隔最大的线性分类器。模型为分离超平面,策略是间隔最大化,学习算法是凸二次规划(二次即指目标优化函数是二次的形式,凸优化即在有约束条件下求目标函数最优的问题),凸二次规划的过程中涉及到了将原问题转换成对偶问题求解,从而让问题变得更简单,还自然地引入了核函。
(1)当训练样本线性可分时,通过硬间隔最大化,学习一个线性分类器,即线性可分支持向量机;
(2)当训练数据近似线性可分时,引入松弛变量,通过软间隔最大化,学习一个线性分类器,即线性支持向量机;
(3)当训练数据线性不可分时,通过使用核技巧及软间隔最大化,学习非线性支持向量机。
核函数:
- 核函数的本质是映射函数的内积,这是与映射到特征空间后的内积,然鹅这样直接计算时很困难的.于是,设想与在特征空间的内积等于在原始空间中通过核函数k计算的结果.有了这样的函数就不要直接去计算高维甚至无穷维空间中的内积,而只直接求解运算,问题得到隐式地求解.
- 非线性问题往往不好求解,所以希望能采用解线性问题的方法来解决这个问题时我那个网需要用到非线性变换,将非线性问题换成线性问题,然后在新的特征空间中使用线性学习方法从数据中学习分类模型.核技巧就是属于这样的方法. (在多项式回归和逻辑回归中,其实也是有通过构造多项式特征来拟合非线性问题的,和核技巧的区别在于获取到特征的办法不一样)
- 核技巧:也就是说在核函数K(x,z)给定的条件下,可以利用解线性问题的方法求解非线性分类问题的支持向量机.学习是隐式地在特征空间进行的,不需要显示地定义特征空间和映射函数.这样的技巧称为核技巧.
- SVM通过对偶问题自然地引入了核函数.核函数可以将特征空间映射到更高维的空间,从而使得非线性问题得以求解.用作表示映射过后的特征向量,对偶问题中涉及到了难以直接计算的.因此设想并引入了,希望通过直接计算来得到高维的内积.写作,只要已知前者的具体形式就能写出核函数k的表达式.
- 根据前述也能看出对于非线性问题,SVM的核函数的选择是至关重要的,因此kernal的选择也成了非线性问题SVM性能的最大变数.
- 常用的核:线性核,多项式核,高斯核,拉普拉斯核,sigmoid核,此外还可以对核之间进行求积,求加权运算等来产生新的核函数.
- 核函数的选择也是一个常见话题:一般用线性核和高斯核,也就是Linear核与RBF核 注意数据归一化处理 然后一般情况下RBF效果是不会差于Linear 但是时间上RBF会耗费更多;下面是吴恩达的见解:1. 如果Feature的数量很大,跟样本数量差不多,这时候选用LR或者是Linear Kernel的SVM 2. 如果Feature的数量比较小,样本数量一般,不算大也不算小,选用SVM+Gaussian Kernel,高斯核可以把特征映射到无穷维 3. 如果Feature的数量比较小,而样本数量很多,可以选择使用多项式核SVM
软间隔与正则化:
- 软间隔的基本思想即允许部分样本分类错误.
- 软间隔的原始问题目标式中的C,即误分惩罚项是SVM最为重要的参数之一, 如果C偏大那么SVM会错误分类有着很小的容忍性,这样往往会导致不太优的分割超平面.
损失函数:
SVM采用hinge损失,即合页损失.
数学表达式为
学习过NG的SVM的课程过后,完全从另外一个角度重新认识了SVM,发现SVM是完全可以从LR推导而来.也终于明白了为什么总是把SVM和LR放到一起对比.在LR的损失函数J(theta)之上,仅仅是由于损失函数的不同,就可以一步一步推导到SVM.这也印证了经常在一些文章中看到的论调'LR和SVM的本质区别其实就在于损失函数',LR采用了对数损失,而SVM采用的是合页损失.从分类角度上来讲,SVM的分类效果就更加健壮一些.此外,SVM自带正则化,因为最小的目标本身就是原始损失函数的正则化的部分.
SVM的解法---SMO:
XGBoost:
XGBoost及面试常见问题(末尾附有很多有价值的参考文章)
- 如果使用one-hot会造成的问题:1.特征将会变得特别稀疏 2.使用one-hot编码的话,意味着在每一个决策节点上只能使用one vs rest(例如是不是狗,是不是猫等)的切分方式。当类别值很多时,每个类别上的数据可能会比较少,这时候切分会产生不平衡,这意味着切分增益也会很小)3.会影响决策树的学习。因为就算可以在这个类别特征进行切分,也会把数据切分到很多零碎的小空间上,如图1左边所示。而决策树学习时利用的是统计信息,在这些数据量小的空间上,统计信息不准确,学习会变差.
- lightgbm作为直接支持类别变量的算法,在处理类别变量的时候一般会采用类别特征的最有切分的方式:1.在枚举分割点之前,先把直方图按每个类别的均值进行排序(实际上似乎不是这样的);然后按照均值的结果依次枚举最优分割点。从图2可以看到,Sum(y)/Count(y)为类别的均值。当然,这个方法很容易过拟合,所以在LGBM中加入了很多对这个方法的约束和正则化。图3是一个简单的对比实验,可以看到该最优方法在AUC上提升了1.5个点,并且时间只多了20%. 2.转换成数值特征, 比如统计类别特征的label的平均值,当然这样容易泄露,因此可以采用一些防止泄露的手法.
CatBoost
XGBoost、LightGBM和CatBoost的同与不同
GBDT:
- GBDT在处理分类和回归的时候,都是采用回归树; 但是两种任务的细节区别在于损失函数的选择不同和节点值的计算公式不同. 回归用MSE作为损失,叶子节点样本均值mean作为节点值;分类用logistic损失(节点值的计算公式比较复杂,这里偷个懒就不编辑了).
- GBDT在处理多分类的时候,会针对每一类都训练一批棵树,因此树的总个数为M*K. 并且最后分类的时候,采用softmax来对样本服从各个类别的概率,然后选择概率最大的类别.
- 多分类具体的算法伪代码如下(只是比二分类多了内层针对类别K的for循环;另外不得不提的是建树的方法和细节和回归是一模一样的,采用MSE来选择切分点):
为什么xgboost/gbdt在调参时为什么树的深度很少就能达到很高的精度?
- 对于Boosting来说,每一步我们都会在上一轮的基础上更加拟合原数据,这样的串行模型可以很好地保证偏差(bias). 所以对于每个基分类器来说,问题就在于如何选择variance更小的分类器,即更简单的分类器,所以我们选择了深度很浅的决策树同时也不需要那么精细的调参工程.即boosting的思想是每个模型可以简单一点粗糙一点,只要是一步步在往前优化就行,大不了多训练一些树(当然会增加训练成本).
- 对于bagging来说,因为每个模型都是基于重采样的样本训练得到的,各个模型其实是比较接近的.而bagging的投票方式,也要求各个模型和而不同,要求各个模型是要尽量优异的,对于单棵树要有足够优异的性能那么就需要更深的深度和更加合适的超参.
对于GBDT有一些思考:
- boosting系列的adboost算法在训练过程中通过更改样本权重,实现了更好的学习.在GBDT中似乎也隐含了这样的原理,在其学习过程中假如存在一个拟合bias较大的样本A, 那么这样一个样本会在每一棵树的生成过程中都会对节点的划分和叶节点的取值造成更大的影响,即使得模型训练时会更加照顾到A,即其实每一个样本的重要程度就已经不一样了.
- GBDT之所以引入梯度提升是为了解决损失函数难度量的问题,当引入梯度后,损失函数的负梯度在当前模型的值等于残差(当损失函数为MSE的时候,可以推导出一阶倒数就是残差表达式y-f(x))或者可以近似为残差。当损失函数是平方损失和指数损失时,每一步优化是很简单的。但对一般损失函数而言,往往每一步优化没那么容易,如绝对值损失函数和Huber损失函数.下表给出一些常用的损失函数及其梯度表达式.
PCA & SVD(主要考虑PCA的计算步骤,以及PCA和SVD区别)
归一化 (Normalization)、标准化 (Standardization)和中心化/零均值化 (Zero-centered)
为什么PCA需要进行标准化处理(如果数据其中某一特征(矩阵的某一列)的数值特别大,那么它在整个误差计算的比重上就很大,那么可以想象在投影到低维空间之后,为了使低秩分解逼近原数据,整个投影会去努力逼近最大的那一个特征,而忽略数值比较小的特征)
协方差(度量各个维度偏离其均值的程度。协方差的值如果为正值,则说明两者是正相关的(从协方差可以引出“相关系数”的定义),结果为负值就说明负相关的,如果为0,也是就是统计上说的“相互独立”。)
关于集成学习的一些问题:
为什么说bagging是减少variance,而boosting是减少bias?
- bagging模型下是将很多个比较强或者说很强的模型的结果做投票/评价.从子模型上看,各个模型的bias和var都是比较接近的,采用求平均的方式是无法明显降低bias的,但是却可以降低var.从bagging采样的方法上来看,多次不一样的重采样,造成了数据的扰动,训练出m个不同的模型,然后在集成的步骤降低了var.从公式角度讲:,
- boosting模型下是将很多个弱分类器进行组合成一个非常强的分类器,强分类器本身就是有很小bias的.从模型的学习方法上看,作为串行的分步加法模型,每一个新模型的构建都是基于前一个模型和目标之间的残差,因此会有很小的bias.但是由于各个模型相关度极高,因此是不能够降低var的.
机器学习中的Bias(偏差),Error(误差),和Variance(方差)有什么区别和联系?
- 偏差指的是算法的期望预测与真实预测之间的偏差程度,反应了模型本身的拟合能力;方差度量了同等大小的训练集的变动导致学习性能的变化,刻画了数据扰动所导致的影响.
为什么bagging的重采样有着优异的效果?
- 从反面的角度来讲,如果不是有放回的抽样,那么每棵树的训练样本都是不同的,都是没有交集的,这样每棵树都是"有偏的",都是"片面的"(当然这样说可能不对),也就是说每棵树训练出来都是有很大的差异的,虽然'异'对于集成模型的各个子模型来说是一个好事,但是完全不同,则超出了那个'尺度';
- 随机森林最后分类取决于多棵树(弱分类器)的投票表决,这种表决应该是"求同",因此使用完全不同的训练集来训练每棵树这样对最终分类结果是没有帮助的,这样无异于是"盲人摸象.
- bagging的有放回的重采样思路是有助于实现训练生成大量'和而不同'的子模型的.
缺失处理与异常值敏感:
怎么理解决策树、xgboost能处理缺失值?而有的模型(svm)对缺失值比较敏感呢?
找茬(区别)系列:
深度学习:
DNN部分:
深度神经网络(DNN)反向传播算法(BP) (要求推导)
- 梯度消失和梯度爆炸问题(BP算法中权值更新的过程需要计算激活函数梯度的连乘,如果梯度小于1,连乘就会造成梯度指数级下降,从而导致,神经元权值更新缓慢,即训练缓慢;解决这样一个问题要么换成ReLu激活函数,要么就调整初始化的权值,对于具体的激活函数,最优的初值当然也是不一样的,对于Sigmoid来说最优是1/n,n为特征维数)
- 深度学习中的正则化
竞赛:
RF, GBDT和Xgboost构造新特征+LR融合的原理及实践
华为:
模型代码框架:
- 样本单独编号,特征保存,保证了每一次的测试效率
- 多进程加速特征提取,分模块的特征提取,同时也分对象进行特征提取(因为需要用多进程加速)
- 在最后运用热插拔的原理,写出了add函数, 能够非常方便地增删任意数量的特征,然后直接送入到模型中训练.
多进程的处理:
对于python的多进程来说存在一个比较坑的地方,在于如果从父进程中传数据到子进程中,那么子进程是会拷贝父进程的状态的,也就是会导致内存占用翻倍. 对于这个问题,我采用的解决方案是先将数据拆分为n份,然后开启子进程处理的时候都直接传数据到子进程当中,然后单独处理,这样不会导致内存占用的增多.还能有效利用python多进程解决加速特征提取的问题.
细节优化:
特征处理的时候, 对于一个DF,我每次都只提取出目标列放到内存中进行处理,这样一来也能够减少特征计算时对于内存的占用和对cpu的消耗.这样的处理在特征累计起来过后效果是很明显的.
内存管理:
- 数据类型的转换,因为大量的计算得到的特征都是默认float64的大小,占用了大量的内存空间.在这个问题上,在保证精度的前提下将数据转换为int, 或者float32是明显减少数据的内存占用.
- 实时使用gc包,回收内存
特征保存:
- 采用额外对每一行进行编号(instance_id)的方法,让一条样本都有了单独的区分度.这使得后续对于计算完成的特征保存有了可行的前提.
数据预处理与特征选择方面:
- 拿到数据过后,首先做数据清洗
- 清洗完成过后做一些可视化的分析与特征筛选(这一部分可能还需要看一些比赛温习一下).可视化和特征筛选都是可以看出一些特征和label的相关性(其实这是我实战中用的最多的).
- 过滤式:在跑模型之前就可以用到(a).皮尔逊相关系数,直接查看每个特征和标签之间的响应关系,特征和标签越是相关说明这个特征越是重要,即越有挖掘和开发的潜力(但是皮尔逊相关系数只能够表现出线性的关系,对于稍复杂一些的关系就没有办法了);(b).卡方检验(但是几乎没用过);(c)方差检验:这种方法先要计算各个特征的方差,然后根据阈值,选择方差大于阈值的特征,即判断出模型的一个区分效果;(d)距离相关系数;(e)最大信息系数
- 包裹式:分为前向搜索和后向搜索两种思路,反正就是每次扔进去或者刨除来一个或者多个特征,然后交叉验证模型的性能,如果变得更优,那么就进行筛选即可. 但是这种思路可能会陷入局部最优.
- 嵌入式:即依靠模型本身的一些特质或者L1稀疏算子进行特征筛选.比如LR可以根据w判断特征的重要程度,树模型可以输出特征重要性等等.
特征方面:
- 转化率是最强的特征之一, 采用了防止过拟合办法(五折交叉构造, 历史数据) , 还做了平滑(更符合实际的业务场景)
- 聚类:kmeans对数据做了人口的聚类(注意:常见的聚类算法都是无法对类别变量进行运算的,类别变量传入是没有任何意义的,如果这个地方必须要用kmeans的话也得是在统计量的基础上来做(要么就说聚类时用到了kmeans的变体,针对类别变量设计的k-mode算法)!!!! 另外,也可以直接跟面试官讲这个地方用到了逻辑回归进行了多分类处理),在聚类得到的类别基础上进行一些统计特征的提取,这样做可以从更粗的粒度上提取信息,可以防止过拟合,使得模型有更好的泛化性能.可以讲到在房租预测的AI Future比赛中运用location.area.shi等特征进行聚类效果是很好的.
- 统计特征: 多个粒度层级做了交叉统计,提取了用户, 广告信息, 广告商的特征.
- 行为编码: 通过count_cvr两个特征的组合再编码形成用户行为编码,这样的特征有着更好的业务意义,同时在类别较少时效果是很好的,因为很贴近业务,不会过拟合同时还能保证很不错的泛化效果. 其实这个和离散编码应该是有相似的地方的,或者说原理应该就是一样的,在房租比赛中我用到了离散编码的思想将community进行了分组编码,带来了非常好的效果.
- 业务特征: 从正推时间窗口,倒推时间窗口,到趋势特征. 再到活跃天数,活跃热度,连续未点击等等都是从业务层面对对象进行了刻画.
- rank特征: rank特征通常是建立在cvr特征的基础之上, 是能够有效描述出竞争信息的.
关于python的一些问题: