机器学习面试知识点总结(更新中...)

参考资料:
https://blog.csdn.net/weixin_40355324/article/details/80426952 (非常全面)
https://www.cnblogs.com/zuochongyan/p/5407053.html
https://blog.csdn.net/woaidapaopao/article/details/77806273 (很好的深度相关总结,简短)

  1. 监督学习和非监督学习的区别?
    监督学习有标签(神经网络,SVM等),非监督学习无标签(聚类等)。

  2. 对SVM的理解(损失函数,求解方式,推导,特性,多分类问题)
    SVM(支持向量机)是一个面向数据的分类算法,它的目标是为确定一个分类超平面,从而将不同的数据分隔开。
    【 扩展】支持向量机学习方法包括构建由简至繁的模型:当训练数据线性可分时,通过硬间隔最大化,学习一个线性的分类器,即线性可分支持向量机,又称为硬间隔支持向量机;当训练数据近似线性可分时,通过软间隔最大化,也学习一个线性的分类器,即线性支持向量机,又称为软间隔支持向量机;当训练数据线性不可分时,通过使用核技巧及软间隔最大化,学习非线性支持向量机
    SVM的推导过程:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    SVM的补充理解: https://blog.csdn.net/sinat_35512245/article/details/54984251
    核函数的选择
    线性核:主要用于线性可分的情形。参数少,速度快,对于一般数据,分类效果已经很理想了。
    高斯核:主要用于线性不可分的情形。参数多,分类结果非常依赖于参数。有很多人是通过训练数据的交叉验证来寻找合适的参数,不过这个过程比较耗时。我个人的体会是:使用libsvm,默认参数,RBF核比Linear核效果稍差。通过进行大量参数的尝试,一般能找到比linear核更好的效果。
    SVM解决多分类问题:
    a. 理想的方法(一对一)是直接修改目标函数,将解空间或分成N个部分,每一块区域对应一个类,实现难度较大;b. 一对多:每一次将一个例作为正例,其他的作为反例,训练N个分类器,测试时如果只有一个分类器预测为正类,则对应类别为最终结果,如果有多个,则一般选择置信度最大的。从分类器角度一对一更多,但是每一次都只用了2个类别,因此当类别数很多的时候一对一开销通常更小(只要训练复杂度高于O(N)即可得到此结果)。

  3. 对LR(逻辑回归)的理解(损失函数,求解方式,推导,特性)
    LR的优点在于实现简单,并且计算量非常小,速度很快,存储资源低,缺点就是因为模型简单,对于复杂的情况下会出现欠拟合,并且只能处理2分类问题(通过和SVM类似的一对多处理,也可以解决多分类问题)。
    LR推导:
    在这里插入图片描述

  4. SVM和LR的异同点
    相同点:
    a. LR和SVM都可以处理分类问题,且一般都用于处理线性二分类问题(在改进的情况下可以处理多分类问题)
    b. 两个方法都可以增加不同的正则化项,如L1、L2等等。所以在很多实验中,两种算法的结果是很接近的。
    c. 都是监督学习方法
    不同点:
    a. LR对异常值敏感,SVM对异常值不敏感。
    b. LR采用log损失,SVM采用合页损失。
    c、在训练集较小时,SVM较适用,而LR需要较多的样本。
    d、LR模型找到的那个超平面,是尽量让所有点都远离他,而SVM寻找的那个超平面,是只让最靠近中间分割线的那些点尽量远离,即只用到那些支持向量的样本。
    e、对非线性问题的处理方式不同,LR主要靠特征构造,必须组合交叉特征,特征离散化。SVM也可以这样,还可以通过kernel。
    f、SVM只需要计算与少数几个支持向量的距离,在进行复杂核函数计算时优势很明显,能够大大简化模型和计算。
    g、Logic 能做的 SVM能做,但可能在准确率上有问题,SVM能做的Logic有的做不了。

  5. LR(逻辑回归)与线性回归的区别与联系
    a. 个人感觉逻辑回归和线性回归首先都是广义的线性回归,
    b. 经典线性模型的优化目标函数是最小二乘(找到一条直线,所有点大直线的距离之和最小),而逻辑回归则是似然函数。
    c. 线性回归在整个实数域范围内进行预测,敏感度一致,而分类范围,需要在[0,1]。逻辑回归就是一种减小预测范围,将预测值限定为[0,1]间的一种回归模型,因而对于这类问题来说,逻辑回归的鲁棒性比线性回归的要好。
    d. 逻辑回归和线性回归的区别在于因变量(?)不同,一个是二项分布,一个是连续分布。

  6. 决策树的理解
    决策树基于树结构进行决策,与人类在面临问题的时候处理机制十分类似。其特点在于需要选择一个属性进行分支,在分支的过程中选择信息增益最大的属性,定义如下:
      在这里插入图片描述
    在划分中我们希望决策树的分支节点所包含的样本属于同一类别,即节点的纯度越来越高。决策树计算量简单,可解释性强,比较适合处理有缺失属性值的样本,能够处理不相关的特征,但是容易过拟合,需要使用剪枝或者随机森林。
    信息增益是熵减去条件熵,代表信息不确定性较少的程度,信息增益越大,说明不确定性降低的越大,因此说明该特征对分类来说很重要。由于信息增益准则会对数目较多的属性有所偏好,因此一般用信息增益率(c4.5)
    在这里插入图片描述
    其中分母可以看作为属性自身的熵。取值可能性越多,属性的熵越大。
    Cart决策树使用基尼指数来选择划分属性,直观的来说,Gini(D)反映了从数据集D中随机抽取两个样本,其类别标记不一致的概率,因此基尼指数越小数据集D的纯度越高,一般为了防止过拟合要进行剪枝,有预剪枝和后剪枝,一般用cross validation集进行剪枝

  7. SVM、LR、决策树的对比
    a. SVM既可以用于分类问题,也可以用于回归问题,并且可以通过核函数快速的计算,LR实现简单,训练速度非常快,但是模型较为简单,决策树容易过拟合,需要进行剪枝等。
    b. 从优化函数上看,soft margin的SVM用的是hinge loss,而带L2正则化的LR对应的是cross entropy loss,另外adaboost对应的是exponential loss。所以LR对远点敏感,但是SVM对outlier不太敏感,因为只关心support vector。
    c. SVM可以将特征映射到无穷维空间,但是LR不可以,一般小数据中SVM比LR更优一点,但是LR可以预测概率,而SVM不可以,SVM依赖于数据测度,需要先做归一化,LR一般不需要,对于大量的数据LR使用更加广泛,LR向多分类的扩展更加直接.
    d. 对于类别不平衡SVM一般用权重解决,即目标函数中对正负样本代价函数不同,LR可以用一般的方法,也可以直接对最后结果调整(通过阈值),一般小数据下样本维度比较高的时候SVM效果要更优一些。

  8. Bagging 和 Boosting 的区别
    参考:https://www.cnblogs.com/earendil/p/8872001.html
    Baggging 和Boosting都是模型融合的方法,可以将弱分类器融合之后形成一个强分类器,而且融合之后的效果会比最好的弱分类器更好。
    Bagging:
    其算法过程如下:
    a. 从原始样本集中抽取训练集。每轮从原始样本集中使用Bootstraping的方法抽取n个训练样本(在训练集中,有些样本可能被多次抽取到,而有些样本可能一次都没有被抽中)。共进行k轮抽取,得到k个训练集。(k个训练集之间是相互独立的)
    b. 每次使用一个训练集得到一个模型,k个训练集共得到k个模型。
    c. 对分类问题:将上步得到的k个模型采用投票的方式得到分类结果;对回归问题,计算上述模型的均值作为最后的结果。(所有模型的重要性相同)
    Boosting:
    AdaBoosting方式每次使用的是全部的样本,每轮训练改变样本的权重。下一轮训练的目标是找到一个函数f 来拟合上一轮的残差。当残差足够小或者达到设置的最大迭代次数则停止。Boosting会减小在上一轮训练正确的样本的权重,增大错误样本的权重。(对的残差小,错的残差大)
    梯度提升的Boosting方式是使用代价函数对上一轮训练出的模型函数f的偏导来拟合残差。
    Bagging和Boosting的区别:
    1)样本选择上:
    Bagging:训练集是在原始集中有放回选取的,从原始集中选出的各轮训练集之间是独立的。
    Boosting:每一轮的训练集不变,只是训练集中每个样例在分类器中的权重发生变化。而权值是根据上一轮的分类结果进行调整。
    2)样例权重:
    Bagging:使用均匀取样,每个样例的权重相等
    Boosting:根据错误率不断调整样例的权值,错误率越大则权重越大。
    3)预测函数:
    Bagging:所有预测函数的权重相等。
    Boosting:每个弱分类器都有相应的权重,对于分类误差小的分类器会有更大的权重。
    4)并行计算:
    Bagging:各个预测函数可以并行生成
    Boosting:各个预测函数只能顺序生成,因为后一个模型参数需要前一轮模型的结果。
    5)为什么说bagging是减少variance,而boosting是减少bias?这个很重要面试被问到了
    Bagging: 对样本重采样,对每一重采样得到的子样本集训练一个模型,最后取平均。由于子样本集的相似性以及使用的是同种模型,因此各模型有近似相等的bias和variance(事实上,各模型的分布也近似相同,但不独立)。由于E[\frac{\sum X_i}{n}]=E[X_i],所以bagging后的bias和单个子模型的接近,一般来说不能显著降低bias。另一方面,若各子模型独立,则有Var(\frac{\sum X_i}{n})=\frac{Var(X_i)}{n},此时可以显著降低variance。若各子模型完全相同,则Var(\frac{\sum X_i}{n})=Var(X_i),此时不会降低variance。bagging方法得到的各子模型是有一定相关性的,属于上面两个极端状况的中间态,因此可以一定程度降低variance。为了进一步降低variance,Random forest通过随机选取变量子集做拟合的方式de-correlated了各子模型(树),使得variance进一步降低。
    (用公式可以一目了然:设有i.d.的n个随机变量,方差记为\sigma^2,两两变量之间的相关性为\rho,则\frac{\sum X_i}{n}的方差为\rho*\sigma2+(1-\rho)*\sigma2/n,bagging降低的是第二项,random forest是同时降低两项。详见ESL p588公式15.1)
    Boosting: 从优化角度来看,是用forward-stagewise这种贪心法去最小化损失函数L(y, \sum_i a_i f_i(x))。例如,常见的AdaBoost即等价于用这种方法最小化exponential loss:L(y,f(x))=exp(-yf(x))。所谓forward-stagewise,就是在迭代的第n步,求解新的子模型f(x)及步长a(或者叫组合系数),来最小化L(y,f_{n-1}(x)+af(x)),这里f_{n-1}(x)是前n-1步得到的子模型的和。因此boosting是在sequential地最小化损失函数,其bias自然逐步下降。但由于是采取这种sequential、adaptive的策略,各子模型之间是强相关的,于是子模型之和并不能显著降低variance。所以说boosting主要还是靠降低bias来提升预测精度。

  9. GBDT(梯度提升树) 和随机森林的区别?
    1)Bagging + 决策树 = 随机森林
    2)AdaBoost + 决策树 = 提升树
    3)Gradient Boosting + 决策树 = GBDT
    随机森林采用的是bagging的思想,通过在训练样本集中进行有放回的采样得到多个采样集,基于每个采样集训练出一个基学习器,再将基学习器结合。随机森林在对决策树进行bagging的基础上,在决策树的训练过程中引入了随机属性选择。传统决策树在选择划分属性的时候是在当前节点属性集合中选择最优属性,而随机森林则是对结点先随机选择包含k个属性的子集,再选择最优属性,k作为一个参数控制了随机性的引入程度。
    **GBDT(梯度提升树)**训练是基于Boosting思想,每一迭代中根据错误更新样本权重,因此是串行生成的序列化方法,而随机森林是bagging的思想,因此是并行化方法。
    两者都是使用决策树作为基模型.
    随机森林对异常值不敏感,GBDT对异常值非常敏感
    随机森林对训练集一视同仁,GBDT是基于权值的弱分类器的集成
    随机森林是通过减少模型方差提高性能,GBDT是通过减少模型偏差提高性能

  10. 如何解决类别不平衡问题
    通常有三种做法: (反例偏多,正例偏少)一种是对训练集的负样本进行欠采样,第二种是对正例进行升采样,第三种是直接基于原始训练集进行学习,在预测的时候再改变阈值,称为阈值移动。注意过采样一般通过对训练集的正例进行插值产生额外的正例,而欠采样将反例划分为不同的集合供不同的学习器使用。

  11. 为什么会产生过拟合,有哪些方法可以预防或克服过拟合
    欠拟合:一般来说欠拟合更容易解决一些,例如增加模型的复杂度,增加决策树中的分支,增加神经网络中的训练次数等等。
    过拟合:一般认为过拟合是无法彻底避免的,因为机器学习面临的问题一般是np-hard,但是一个有效的解一定要在多数时间内是可以工作,所以会牺牲一些泛化能力。过拟合的解决方案一般有增加样本数量,对样本进行降维,降低模型复杂度,利用先验知识(L1,L2正则化),利用cross-validation,early stopping等等。

  12. 什么是偏差与方差
    泛化误差可以分解成偏差的平方加上方差加上噪声。偏差度量了学习算法的期望预测和真实结果的偏离程度,刻画了学习算法本身的拟合能力方差度量了同样大小的训练集的变动所导致的学习性能的变化,**刻画了数据扰动所造成的影响,**噪声表达了当前任务上任何学习算法所能达到的期望泛化误差下界,刻画了问题本身的难度。偏差和方差一般称为bias和variance,一般训练程度越强,偏差越小,方差越大,泛化误差一般在中间有一个最小值,如果偏差较大,方差较小,此时一般称为欠拟合,而偏差较小,方差较大称为过拟合。

  13. 在k-means或kNN,我们是用欧氏距离来计算最近的邻居之间的距离。为什么不用曼哈顿距离
    曼哈顿距离只计算水平或垂直距离,有维度的限制。另一方面,欧氏距离可用于任何空间的距离计算问题。因为,数据点可以存在于任何空间,欧氏距离是更可行的选择。例如:想象一下国际象棋棋盘,象或车所做的移动是由曼哈顿距离计算的,因为它们是在各自的水平和垂直方向做的运动。

  14. 神经网络训练过程中过拟合怎么办?
    dropout、regularization、batch normalizatin

  15. 为什么XGBoost要用泰勒展开,优势在哪里
    XGBoost使用了一阶和二阶偏导, 二阶导数有利于梯度下降的更快更准. 使用泰勒展开取得二阶倒数形式, 可以在不选定损失函数具体形式的情况下用于算法优化分析.本质上也就把损失函数的选取和模型算法优化/参数选择分开了. 这种去耦合增加了XGBoost的适用性。

  16. XGBoost如何寻找最优特征?是又放回还是无放回的呢
    XGBoost在训练的过程中给出各个特征的评分,从而表明每个特征对模型训练的重要性.。XGBoost利用梯度优化模型算法, 样本是不放回的(想象一个样本连续重复抽出,梯度来回踏步会不会高兴)。但XGBoost支持子采样, 也就是每轮计算可以不使用全部样本。

  17. 谈谈判别式模型和生成式模型
    判别方法:由数据直接学习决策函数 Y = f(X),或者由条件分布概率 P(Y|X)作为预测模型,即判别模型。
    生成方法:由数据学习联合概率密度分布函数 P(X,Y),然后求出条件概率分布P(Y|X)作为预测的模型,即生成模型。
    由生成模型可以得到判别模型,但由判别模型得不到生成模型。
    常见的判别模型有:K近邻、SVM、决策树、感知机、线性判别分析(LDA)、线性回归、传统的神经网络、逻辑斯蒂回归、boosting、条件随机场
    常见的生成模型有:朴素贝叶斯、隐马尔可夫模型、高斯混合模型、文档主题生成模型(LDA)、限制玻尔兹曼机。

  18. L1和L2的区别
    L1是拉普拉斯分布,L2是高斯分布
    L1范数: 为x向量各个元素绝对值之和。
    L2范数: 为x向量各个元素平方和的1/2次方,L2范数又称Euclidean范数或Frobenius范数
    Lp范数: 为x向量各个元素绝对值p次方和的1/p次方.
    在支持向量机学习过程中,L1范数实际是一种对于成本函数求解最优的过程,因此,L1范数正则化通过向成本函数中添加L1范数,使得学习得到的结果满足稀疏化,从而方便人类提取特征。
    L1范数可以使权值稀疏,方便特征提取。
    L2范数可以防止过拟合,提升模型的泛化能力。

  19. AdaBoost理解
    参考: https://blog.csdn.net/fuqiuai/article/details/79482487
    Adaboost算法是一种提升方法,将多个弱分类器,组合成强分类器。
    它的自适应在于:前一个弱分类器分错的样本的权值(样本对应的权值)会得到加强,权值更新后的样本再次被用来训练下一个新的弱分类器。在每轮训练中,用总体(样本总体)训练新的弱分类器,产生新的样本权值、该弱分类器的话语权,一直迭代直到达到预定的错误率或达到指定的最大迭代次数。
    总体——样本——个体三者间的关系需要搞清除
    总体N。样本:{ni}i从1到M。个体:如n1=(1,2),样本n1中有两个个体。
    算法原理
    (1)初始化训练数据(每个样本)的权值分布:如果有N个样本,则每一个训练的样本点最开始时都被赋予相同的权重:1/N。
    (2)训练弱分类器。具体训练过程中,如果某个样本已经被准确地分类,那么在构造下一个训练集中,它的权重就被降低;相反,如果某个样本点没有被准确地分类,那么它的权重就得到提高。同时,得到弱分类器对应的话语权。然后,更新权值后的样本集被用于训练下一个分类器,整个训练过程如此迭代地进行下去。
    (3)将各个训练得到的弱分类器组合成强分类器。各个弱分类器的训练过程结束后,分类误差率小的弱分类器的话语权较大,其在最终的分类函数中起着较大的决定作用,而分类误差率大的弱分类器的话语权较小,其在最终的分类函数中起着较小的决定作用。换言之,误差率低的弱分类器在最终分类器中占的比例较大,反之较小。

  20. .机器学习中,为何要经常对数据做归一化
    参考:http://www.cnblogs.com/LBSer/p/4440590.html
    1)归一化后加快了梯度下降求最优解的速度;2)归一化有可能提高精度。一些分类器需要计算样本之间的距离(如欧氏距离),例如KNN。如果一个特征值域范围非常大,那么距离计算就主要取决于这个特征,从而与实际情况相悖(比如这时实际情况是值域范围小的特征更重要)。
    归一化的类型
    1)线性归一化

    这种归一化方法比较适用在数值比较集中的情况。这种方法有个缺陷,如果max和min不稳定,很容易使得归一化结果不稳定,使得后续使用效果也不稳定。实际使用中可以用经验常量值来替代max和min。
    2)标准差标准化
      经过处理的数据符合标准正态分布,即均值为0,标准差为1,其转化函数为:
    在这里插入图片描述
    其中μ为所有样本数据的均值,σ为所有样本数据的标准差。
    3)非线性归一化
    经常用在数据分化比较大的场景,有些数值很大,有些很小。通过一些数学函数,将原始值进行映射。该方法包括 log、指数,正切等。需要根据数据分布的情况,决定非线性函数的曲线,比如log(V, 2)还是log(V, 10)等。

  21. 谈谈深度学习中的归一化问题
    参考教学视频: http://www.julyedu.com/video/play/69/686
    参考:https://blog.csdn.net/lx10271129/article/details/78984623
    BN算法像卷积层,池化层、激活层一样也输入一层。BN层添加在激活函数前,对输入激活函数的输入进行归一化。这样解决了输入数据发生偏移和增大的影响。
    优点:
    1、加快训练速度,能够增大学习率,及时小的学习率也能够有快速的学习速率; 原因在于神经网络学习过程本质就是为了学习数据分布,一旦训练数据与测试数据的分布不同,那么网络的泛化能力也大大降低;另外一方面,一旦每批训练数据的分布各不相同(batch 梯度下降),那么网络就要在每次迭代都去学习适应不同的分布,这样将会大大降低网络的训练速度,这也正是为什么我们需要对数据都要做一个归一化预处理的原因。
    2、不用理会拟合中的droupout、L2 正则化项的参数选择,采用BN算法可以省去这两项或者只需要小的L2正则化约束。原因,BN算法后,参数进行了归一化,原本经过激活函数没有太大影响的神经元,分布变得明显,经过一个激活函数以后,神经元会自动削弱或者去除一些神经元,就不用再对其进行dropout。另外就是L2正则化,由于每次训练都进行了归一化,就很少发生由于数据分布不同导致的参数变动过大,带来的参数不断增大。
    3、 可以把训练数据集打乱,防止训练发生偏移。
    BN算法概述
    在网络的每一层输入的时候,插入了一个归一化层,也就是先做一个归一化处理,然后再进入网络的下一层。不过文献归一化层,可不像我们想象的那么简单,它是一个可学习、有参数的网络层。其实如果是仅仅使用上面的归一化公式,对网络某一层A的输出数据做归一化,然后送入网络下一层B,这样是会影响到本层网络A所学习到的特征的。打个比方,比如我网络中间某一层学习到特征数据本身就分布在S型激活函数的两侧,你强制把它给我归一化处理、标准差也限制在了1,把数据变换成分布于s函数的中间部分,这样就相当于我这一层网络所学习到的特征分布被你搞坏了,这可怎么办?于是文献使出了一招惊天地泣鬼神的招式:变换重构,引入了可学习参数γ、β,这就是算法关键之处:
    在这里插入图片描述
    每一个神经元xk都会有一对这样的参数γ、β。这样其实当:
    、
    是可以恢复出原始的某一层所学到的特征的。因此我们引入了这个可学习重构参数γ、β,让我们的网络可以学习恢复出原始网络所要学习的特征分布。最后Batch Normalization网络层的前向传导过程公式就是:
    在这里插入图片描述
    上面的公式中m指的是mini-batch size。

  22. 请简要说说一个完整机器学习项目的流程
    1 抽象成数学问题
    这里的抽象成数学问题,指的我们明确我们可以获得什么样的数据,目标是一个分类还是回归或者是聚类的问题,如果都不是的话,如果划归为其中的某类问题。
    2 获取数据
    数据决定了机器学习结果的上限,而算法只是尽可能逼近这个上限。
    数据要有代表性,否则必然会过拟合。
    而且对于分类问题,数据偏斜不能过于严重,不同类别的数据数量不要有数个数量级的差距。
    而且还要对数据的量级有一个评估,多少个样本,多少个特征,可以估算出其对内存的消耗程度,判断训练过程中内存是否能够放得下。如果放不下就得考虑改进算法或者使用一些降维的技巧了。如果数据量实在太大,那就要考虑分布式了。
    3 特征预处理与特征选择
    良好的数据要能够提取出良好的特征才能真正发挥效力。
    特征预处理、数据清洗是很关键的步骤,往往能够使得算法的效果和性能得到显著提高。归一化、离散化、因子化、缺失值处理、去除共线性等,数据挖掘过程中很多时间就花在它们上面。这些工作简单可复制,收益稳定可预期,是机器学习的基础必备步骤。
    筛选出显著特征、摒弃非显著特征,需要机器学习工程师反复理解业务。这对很多结果有决定性的影响。特征选择好了,非常简单的算法也能得出良好、稳定的结果。这需要运用特征有效性分析的相关技术,如相关系数、卡方检验、平均互信息、条件熵、后验概率、逻辑回归权重等方法。
    4 训练模型与调优
    直到这一步才用到我们上面说的算法进行训练。现在很多算法都能够封装成黑盒供人使用。但是真正考验水平的是调整这些算法的(超)参数,使得结果变得更加优良。这需要我们对算法的原理有深入的理解。理解越深入,就越能发现问题的症结,提出良好的调优方案。
    5 模型诊断
    如何确定模型调优的方向与思路呢?这就需要对模型进行诊断的技术。
    过拟合、欠拟合 判断是模型诊断中至关重要的一步。常见的方法如交叉验证,绘制学习曲线等。过拟合的基本调优思路是增加数据量,降低模型复杂度。欠拟合的基本调优思路是提高特征数量和质量,增加模型复杂度。
    误差分析 也是机器学习至关重要的步骤。通过观察误差样本,全面分析误差产生误差的原因:是参数的问题还是算法选择的问题,是特征的问题还是数据本身的问题……
    诊断后的模型需要进行调优,调优后的新模型需要重新进行诊断,这是一个反复迭代不断逼近的过程,需要不断地尝试, 进而达到最优状态。
    6 模型融合
    一般来说,模型融合后都能使得效果有一定提升。而且效果很好。
    工程上,主要提升算法准确度的方法是分别在模型的前端(特征清洗和预处理,不同的采样模式)与后端(模型融合)上下功夫。因为他们比较标准可复制,效果比较稳定。而直接调参的工作不会很多,毕竟大量数据训练起来太慢了,而且效果难以保证。
    7 上线运行
    这一部分内容主要跟工程实现的相关性比较大。工程上是结果导向,模型在线上运行的效果直接决定模型的成败。 不单纯包括其准确程度、误差等情况,还包括其运行的速度(时间复杂度)、资源消耗程度(空间复杂度)、稳定性是否可接受。
    这些工作流程主要是工程实践上总结出的一些经验。并不是每个项目都包含完整的一个流程。这里的部分只是一个指导性的说明,只有大家自己多实践,多积累项目经验,才会有自己更深刻的认识。

  23. new 和 malloc的区别?
    参考链接: https://www.cnblogs.com/fly1988happy/archive/2012/04/26/2470542.html

  24. 怎么解决梯度消失和梯度膨胀
    参考链接: https://zhuanlan.zhihu.com/p/25631496
    (1)梯度消失:
    根据链式法则,如果每一层神经元对上一层的输出的偏导乘上权重结果都小于1的话,那么即使这个结果是0.99,在经过足够多层传播之后,误差对输入层的偏导会趋于0。
    可以采用ReLU激活函数有效的解决梯度消失的情况。
    (2)梯度膨胀:
    根据链式法则,如果每一层神经元对上一层的输出的偏导乘上权重结果都大于1的话,在经过足够多层传播之后,误差对输入层的偏导会趋于无穷大。
    可以通过激活函数来解决。

  25. 对正则化的理解
    正则化是针对过拟合而提出的,以为在求解模型最优的是一般优化最小的经验风险,现在在该经验风险上加入模型复杂度这一项(正则化项是模型参数向量的范数),并使用一个rate比率来权衡模型复杂度与以往经验风险的权重,如果模型复杂度越高,结构化的经验风险会越大,现在的目标就变为了结构经验风险的最优化,可以防止模型训练过度复杂,有效的降低过拟合的风险。
    奥卡姆剃刀原理,能够很好的解释已知数据并且十分简单才是最好的模型。

  26. 常见激活函数
    参考链接: https://blog.csdn.net/u012897374/article/details/79199935
    在这里插入图片描述
    在这里插入图片描述
    常用的非线性激活函数有sigmoid、tanh、relu等等,前两者sigmoid/tanh比较常见于全连接层,后者relu常见于卷积层。这里先简要介绍下最基础的sigmoid函数
    在这里插入图片描述
    也就是说,Sigmoid函数的功能是相当于把一个实数压缩至0到1之间。当z是非常大的正数时,g(z)会趋近于1,而z是非常小的负数时,则g(z)会趋近于0。
    压缩至0到1有何用处呢?用处是这样一来便可以把激活函数看作一种“分类的概率”,比如激活函数的输出为0.9的话便可以解释为90%的概率为正样本。
    Relu和Sigmoid对比
    a. 采用sigmoid等函数,算激活函数时(指数运算),计算量大,反向传播求误差梯度时,求导涉及除法,计算量相对大,而采用Relu激活函数,整个过程的计算量节省很多。并且计算的过程当中只需要判断输入是或大于0,因此Relu函数的收敛速度会快很多。
    b. 对于深层网络,sigmoid函数反向传播时,很容易就会出现梯度消失的情况(在sigmoid接近饱和区时,变换太缓慢,导数趋于0,这种情况会造成信息丢失),从而无法完成深层网络的训练。vanishing gradient在网络层数多的时候尤其明显,是加深网络结构的主要障碍之一。相反,Relu的gradient大多数情况下是常数,有助于解决深层网络的收敛问题。
    c. Relu会使一部分神经元的输出为0,这样就造成了网络的稀疏性,并且减少了参数的相互依存关系,缓解了过拟合问题的发生。
    d. 在生物上的合理性,它是单边的,相比sigmoid和tanh,更符合生物神经元的特征。
    relu存在的一些问题:
    a. ReLU的输出不是zero-centered。如果所有均为正数或负数,那么其对的导数总是正数或负数,这会导致如下图红色箭头所示的阶梯式更新,这显然并非一个好的优化路径。深度学习往往需要大量时间来处理大量数据,模型的收敛速度是尤为重要的。所以,总体上来讲,训练深度学习网络尽量使用zero-centered数据 (可以经过数据预处理实现) 和zero-centered输出(如tanh)。如下图:
    在这里插入图片描述
    Dead ReLU Problem,指的是某些神经元可能永远不会被激活,导致相应的参数永远不能被更新。有两个主要原因可能导致这种情况产生: (1) 非常不幸的参数初始化,这种情况比较少见 (2) learning rate太高导致在训练过程中参数更新太大,不幸使网络进入这种状态。解决方法是可以采用Xavier初始化方法,以及避免将learning rate设置太大或使用adagrad等自动调节learning rate的算法。
    relu作为激活函数,本身看起来是一个线性的函数,但是对于普通的其他任意函数来讲,都可以看成是一个个小小的线段组成的。因此当网络层数很少,比如只有一个隐藏层的时候,relu很难达到非线性的效果,此时应该使用sigmoid等函数。但是如果网络层数增到比较大的时候,此时的relu就可以达到非线性的效果。就类似于用多个线性的小线段组成一个非线性的函数。

  27. 感受野的计算方法
    https://www.cnblogs.com/objectDetect/p/5947169.html

  28. 对随机梯度下降的理解
    ![

  29. KNN和Kmeans
    (1)KNN 和Kmean缺点
      都属于惰性学习机制,需要大量的计算距离过程,速度慢(但都有相应的优化方法)。
    (2)KNN
      KNN不需要进行训练,只要对于一个陌生的点利用离其最近的K个点的标签判断其结果。KNN相当于多数表决,也就等价于经验最小化。而KNN的优化方式就是用Kd树来实现。
    (3)Kmean
      要求自定义K个聚类中心,然后人为的初始化聚类中心,通过不断增加新点变换中心位置得到最终结果。Kmean的缺点可以用Kmean++方法进行一些解决(思想是使得初始聚类中心之间的距离最大化)

  30. 推导下反向传播Backpropagation
    参考链接: http://blog.csdn.net/woaidapaopao/article/details/77806273

  31. 哈希冲突怎么解决
    什么是还行冲突? 不同的键值k1, k2经过哈希函数f映射之后,得到相同的哈希值。
    怎么解决哈希冲突?参考链接: https://www.cnblogs.com/wuchaodzxx/p/7396599.html https://blog.csdn.net/xiaoping8411/article/details/7706376
    开放定址法
    这种方法也称再散列法,其基本思想是:当关键字key的哈希地址p=H(key)出现冲突时,以p为基础,产生另一个哈希地址p1,如果p1仍然冲突,再以p为基础,产生另一个哈希地址p2,…,直到找出一个不冲突的哈希地址pi ,将相应元素存入其中。这种方法有一个通用的再散列函数形式:Hi=(H(key)+di)% m i=1,2,…,n
    其中H(key)为哈希函数,m 为表长,di称为增量序列。增量序列的取值方式不同,相应的再散列方式也不同。主要有以下三种:
    a. 线性探测再散列
    di=1,2,3,…,m-1
    这种方法的特点是:冲突发生时,顺序查看表中下一单元,直到找出一个空单元或查遍全表。
    b. 二次探测再散列
    di=12,-12,22,-22,…,k2,-k2 ( k<=m/2 )
    这种方法的特点是:冲突发生时,在表的左右进行跳跃式探测,比较灵活。
    c. 伪随机探测再散列
    di=伪随机数序列。
    具体实现时,应建立一个伪随机数发生器,(如i=(i+p) % m),并给定一个随机数做起点。
    举例
    例如,已知哈希表长度m=11,哈希函数为:H(key)= key % 11,则H(47)=3,H(26)=4,H(60)=5,假设下一个关键字为69,则H(69)=3,与47冲突。
    如果用线性探测再散列处理冲突,下一个哈希地址为H1=(3 + 1)% 11 = 4,仍然冲突,再找下一个哈希地址为H2=(3 + 2)% 11 = 5,还是冲突,继续找下一个哈希地址为H3=(3 + 3)% 11 = 6,此时不再冲突,将69填入5号单元。
    如果用二次探测再散列处理冲突,下一个哈希地址为H1=(3 + 12)% 11 = 4,仍然冲突,再找下一个哈希地址为H2=(3 - 12)% 11 = 2,此时不再冲突,将69填入2号单元。
    如果用伪随机探测再散列处理冲突,且伪随机数序列为:2,5,9,………,则下一个哈希地址为H1=(3 + 2)% 11 = 5,仍然冲突,再找下一个哈希地址为H2=(3 + 5)% 11 = 8,此时不再冲突,将69填入8号单元。
    再哈希法
    这种方法是同时构造多个不同的哈希函数:
    Hi=RH1(key) i=1,2,…,k
    当哈希地址Hi=RH1(key)发生冲突时,再计算Hi=RH2(key)……,直到冲突不再产生。这种方法不易产生聚集,但增加了计算时间。
    链地址法
    这种方法的基本思想是将所有哈希地址为i的元素构成一个称为同义词链的单链表,并将单链表的头指针存在哈希表的第i个单元中,因而查找、插入和删除主要在同义词链中进行。链地址法适用于经常进行插入和删除的情况。
    建立公共溢出区
    这种方法的基本思想是:将哈希表分为基本表和溢出表两部分,凡是和基本表发生冲突的元素,一律填入溢出表。

32.哈希查找
参考链接: https://blog.csdn.net/xiaoping8411/article/details/7706376
哈希查找的操作步骤:

  1.   用给定的哈希函数构造哈希表;
    
  2.   根据选择的冲突处理方法解决地址冲突;
    
  3.   在哈希表的基础上执行哈希查找。
    

建立哈希表操作步骤:

  1.   step1 取数据元素的关键字key,计算其哈希函数值(地址)。若该地址对应的存储空间还没有被占用,则将该元素存入;否则执行step2解决冲突。
    
  2.   step2 根据选择的冲突处理方法,计算关键字key的下一个存储地址。若下一个存储地址仍被占用,则继续执行step2,直到找到能用的存储地址为止。
    

哈希查找步骤为:

  1.   Step1 对给定k值,计算哈希地址 Di=H(k);若HST为空,则查找失败;若HST=k,则查找成功;否则,执行step2(处理冲突)。
    
  2.   Step2 重复计算处理冲突的下一个存储地址 Dk=R(Dk-1),直到HST[Dk]为空,或HST[Dk]=k为止。若HST[Dk]=K,则查找成功,否则查找失败。
    

比如说:”5“是一个要保存的数,然后我丢给哈希函数,哈希函数给我返回一个”2",那么此时的”5“和“2”就建立一种对应关系,这种关系就是所谓的“哈希关系”,在实际应用中也就形成了”2“是key,”5“是value。
那么有的朋友就会问如何做哈希,首先做哈希必须要遵守两点原则:
①: key尽可能的分散,也就是我丢一个“6”和“5”给你,你都返回一个“2”,那么这样的哈希函数不尽完美。
②:哈希函数尽可能的简单,也就是说丢一个“6”给你,你哈希函数要搞1小时才能给我,这样也是不好的。
其实常用的做哈希的手法有“五种”:
第一种:”直接定址法“。
很容易理解,key=Value+C;这个“C"是常量。Value+C其实就是一个简单的哈希函数。
第二种:“除法取余法”。
很容易理解, key=value%C;解释同上。
第三种:“数字分析法”。
这种蛮有意思,比如有一组value1=112233,value2=112633,value3=119033,
针对这样的数我们分析数中间两个数比较波动,其他数不变。那么我们取key的值就可以是
key1=22,key2=26,key3=90。
第四种:“平方取中法”。此处忽略,见名识意。
第五种:“折叠法”。
这种蛮有意思,比如value=135790,要求key是2位数的散列值。那么我们将value变为13+57+90=160,然后去掉高位“1”,此时key=60,哈哈,这就是他们的哈希关系,这样做的目的就是key与每一位value都相关,来做到“散列地址”尽可能分散的目地。
影响哈希查找效率的一个重要因素是哈希函数本身。当两个不同的数据元素的哈希值相同时,就会发生冲突。为减少发生冲突的可能性,哈希函数应该将数据尽可能分散地映射到哈希表的每一个表项中。

  1. 对BN层的理解
    参考链接:
    https://www.jianshu.com/p/fcc056c1c200
    https://www.cnblogs.com/kk17/p/9693462.html
    https://blog.csdn.net/qq_29573053/article/details/79878437

  2. 神经网络参数的初始化方法
    参考链接: https://blog.csdn.net/u012704941/article/details/82378345
    https://blog.csdn.net/u012328159/article/details/80025785
    a. Xavier初始化方法
    为了使得网络中信息更好的流动,每一层输出的方差应该尽量相等。基于这个目标,现在我们就去推导一下:每一层的权重应该满足哪种条件。
    在这里插入图片描述
    nj为输入的个数,nj+1为输出的个数。
    b. MSRA初始化(何凯明)
    只考虑输入个数时,MSRA初始化是一个均值为0方差为2/n的高斯分布:
    在这里插入图片描述
    文章做了一些对比试验,表明在网络加深后,MSRA初始化明显优于Xavier初始化
    虽然Xavier initialization能够很好的 tanH 激活函数,但是对于目前神经网络中最常用的ReLU激活函数,当达到5,6层后几乎又开始趋向于0,更深层的话很明显又会趋向于0。而MSRA方法可以避免这个问题。
    Xavier对于权值的分布:均值为0,方差为(1 / 输入的个数) 的 均匀分布。如果我们更注重前向传播的话,我们可以选择 fan_in,即正向传播的输入个数;如果更注重后向传播的话,我们选择 fan_out, 因为在反向传播的时候,fan_out就是神经元的输入个数;如果两者都考虑的话,就选 average = (fan_in + fan_out) /2。
    MSRA对于权值的分布:基于均值为0,方差为( 2/输入的个数)的高斯分布;它特别适合 ReLU激活函数,该方法主要是基于Relu函数提出的,推导过程类似于xavier

  3. 神经网络怎么调参
    a. 建议优先在对数尺度上进行超参数搜索:
    比较典型的是学习率和正则化项,我们可以从诸如0.001 0.01 0.1 1 10,以10为阶数进行尝试。因为他们对训练的影响是相乘的效果。不过有些参数,还是建议在原始尺度上进行搜索,例如dropout值: 0.3 0.5 0.7)。
    b. 选择合适的Epoch训练次数
    如果随着Epoch的次数增加,准确度在一定时间内(比如5到10次)变化很小,就可以停止Epoch。开始时可以把Epoch次数设置的大一些,观察在哪个地方准确度变化很小,就把Epoch设置成几。也可以用早停法,防止过拟合。
    c. 调节Regularization parameter lambda
    实验lambda,从1.0,10,100…找到一个合适的。注意:lambda的大小是和样本数成正比关系的,比如现在样本数、lambda分别是1000、0.4,以后把样本数扩大到10000时,对应的lambda也要扩大到4。
    d. 调节mini-batch size
    mini-batch选择太小:没有充分利用计算资源;太大:更新权重和偏向比较慢,mini-batch size和其他参数相对独立,一旦找到一个合适的以后,就不需要再改了。一般就是16,32,64,128,256找一个就行。详细见深度机器学习中的batch的大小对学习效果有何影响?
    e. 如何选择梯度下降算法
    adam或者SGD,当然还有其他自适应的梯度下降算法都可以试试。
    f. 如何选择激励函数
    如何选择激励函数,没有特别好的方法,只能靠实验比较。常用的激励函数有:sigmoid,tanh,relu。
    g. 如何设置Weights和biases
    最简单的方法:让W和b服从N(0, 1 / sqrt(n_in) ),n_in:输入神经元的个数,设置合适的W和b可以加快学习的速率,在极个别的神经网络中,W和b甚至可以影响最后训练的准确度。
    h. 选择何种Regularization
    L1和L2是对cost函数后面增加一项。L1和L2都是为了减少连接对cost影响的权重,但是L1和L2又存在一定的区别。L1减少的是一个常量,L2减少权重的一个固定比例,如果权重本身很大,L1减少的比L2少很多,反之,如果权重本省很小,L1减少的更多。L1倾向于集中在少部分重要的连接上。
    注意:对于L1,当W=0时,cost关于W的偏导没有意义,因为在W=0时不可导,此时就使用un-regulazied表达式,sgn(0)=0,本来regularization的目的就是减少权重,到权重=0时,就没有必要再减少。
    编程的时候发现这个在pytorch里是用weight decay来实现的,选择L2范式的系数就行了,但是一般用了dropout再用L2范式性能会下降,这点我没弄清楚,可能我这里说的不对,以后补充。
    i. 是否使用dropout
    pytorch里的dropout方法就是对Tensor进行随机mask,这样做可以避免过拟合,一般就是0.2,0.3,0.5,用了效果都挺好的,而且不一定拘泥于神经元,你也可以试试对训练过程中各种Tensor是用dropout。
    j. 训练集多大比较合适
    训练集越大越好,增加训练集在一定程度上也可以减少过拟合,数据集对模型很重要,有文章说,参数是对应于数据集的,多大的数据集需要数量差不多的参数就够了。
    k. Loss函数选择
    一般用交叉熵就能解决,但是具体问题具体对待,每个人都可以定义自己的损失函数。
    l. 神经元的个数
    这个在实验中其实起到挺大作用的,句子匹配中,一般第一个隐层要和输入层差不多,最后用于分类的MLP神经元2倍左右,经验值。具体任务具体对待。
    m. 自己模型的超参数
    这个最小二乘法呗。

  4. 学习率怎么调整
    学习率设置
    在训练过程中,一般根据训练轮数设置动态变化的学习率。在这里插入图片描述
    刚开始训练时:学习率以 0.01 ~ 0.001 为宜。
    一定轮数过后:逐渐减缓。
    接近训练结束:学习速率的衰减应该在100倍以上。
    Note:
    如果是 迁移学习 ,由于模型已在原始数据上收敛,此时应设置较小学习率 (≤10−4≤10−4) 在新数据上进行 微调 。
    学习率减缓机制
    在这里插入图片描述
    37.常见深度神经网路的优化方法。
    参考链接: https://blog.csdn.net/u014595019/article/details/52989301
    https://www.cnblogs.com/sunhongwen/p/9419318.html
    https://www.jianshu.com/p/aebcaf8af76e
    常见的一阶梯度方法有: BGD,SGD,Momentum,AdaGrad,RMSProp,Adam
    BGD
    即batch gradient descent. 在训练中,每一步迭代都使用训练集的所有内容. 也就是说,利用现有参数对训练集中的每一个输入生成一个估计输出yi(带尖),然后跟实际输出yi比较,统计所有误差,求平均以后得到平均误差,以此来作为更新参数的依据.
    具体实现:
    在这里插入图片描述
    优点:
    由于每一步都利用了训练集中的所有数据,因此当损失函数达到最小值以后,能够保证此时计算出的梯度为0,换句话说,就是能够收敛.因此,使用BGD时不需要逐渐减小学习速率ϵ
    缺点:
    由于每一步都要使用所有数据,因此随着数据集的增大,运行速度会越来越慢.
    SGD
    SGD全名 stochastic gradient descent, 即随机梯度下降。不过这里的SGD其实跟MBGD(minibatch gradient descent)是一个意思,即随机抽取一批样本,以此为根据来更新参数.
    具体实现:
    在这里插入图片描述
    优点:
    训练速度快,对于很大的数据集,也能够以较快的速度收敛.
    缺点:
    由于是抽取,因此不可避免的,得到的梯度肯定有误差.因此学习速率需要逐渐减小.否则模型无法收敛
    因为误差,所以每一次迭代的梯度受抽样的影响比较大,也就是说梯度含有比较大的噪声,不能很好的反映真实梯度.
    学习速率该如何调整:
    在这里插入图片描述
    在这里插入图片描述
    Momentum
    上面的SGD有个问题,就是每次迭代计算的梯度含有比较大的噪音. 而Momentum方法可以比较好的缓解这个问题,尤其是在面对小而连续的梯度但是含有很多噪声的时候,可以很好的加速学习.Momentum借用了物理中的动量概念,即前几次的梯度也会参与运算.为了表示动量,引入了一个新的变量v(velocity).v是之前的梯度的累加,但是每回合都有一定的衰减.
    具体实现:
    在这里插入图片描述
    特点:
    前后梯度方向一致时,能够加速学习
    前后梯度方向不一致时,能够抑制震荡
    Nesterov Momentum
    这是对之前的Momentum的一种改进,大概思路就是,先对参数进行估计,然后使用估计后的参数来计算误差。
    具体实现:
    在这里插入图片描述
    RMSProp
    RMSProp通过引入一个衰减系数,让r每回合都衰减一定比例,类似于Momentum中的做法。
    具体实现:
    在这里插入图片描述
    优点:
    相比于AdaGrad,这种方法很好的解决了深度学习中过早结束的问题
    适合处理非平稳目标,对于RNN效果很好
    缺点:
    又引入了新的超参,衰减系数ρρ
    依然依赖于全局学习速率
    Adam
    Adam(Adaptive Moment Estimation)本质上是带有动量项的RMSprop,它利用梯度的一阶矩估计和二阶矩估计动态调整每个参数的学习率。Adam的优点主要在于经过偏置校正后,每一次迭代学习率都有个确定范围,使得参数比较平稳。
    具体实现:
    在这里插入图片描述

  5. 常见深度神经网络理解
    参考链接:https://gwansiu.com/2017/08/06/from-alexnet-to-densenet/
    AlexNet,VGG,googleNet家族(inception v1-v4, xception), Resnet,DenseNet
    在这里插入图片描述
    AlexNet
    在这里插入图片描述

深度(depth):是指除去第一层输入层的层数 宽度(width):是指神经元个数=滤波器的个数=feature map的层数
AlexNets的深度为8:5层卷积层,3层全连接层(fc层,维度分别为:2048,2048,1000),采用Relu激活函数,其中卷积层的结构为:conv-relu-max pooling。 kernel的大小为:11x11,5x5,3x3,3x3,3x3,网络的宽度为:48,128,192,192,128.
AlexNet用两路GPU进行训练:Conv1,Conv2,Conv4,Conv5在同一个GPU进行训练,Conv3,Fc6,Fc7,Fc8之间需要两路GPU相互信息进行训练。 过拟合:dropout + 数据增广
VGGNet
在这里插入图片描述
VGGNet在kernel size和depth上走上极致:1.采用更小的卷积核(3x3,1x1) 2.堆叠卷积层把网络造深。
在这里插入图片描述
VGGNet小结:
VGGNet使用kernel factorization的方法将大的卷积核分解成小卷积核,并进一步加深网络,使网络达到了更好的效果。其中,kernel factorization的方法为后面GoogleNet的诞生提供了很好的降低参数的思路,但仅仅加深网络而并没有解决梯度消失的问题,使得VGGNet训练起来非常困难。后面,GoogleNet,ResNet便为我们提供了很好的解决思路:如何让深度神经网络稳定性训练?
GoogleNet
Inceptionv1
在这里插入图片描述
GoogleNet作者的初始想法是用多个不同类型的卷积核代替一个3x3的小卷积核(如左图),这样做的好处是可以使提取出来的特征具有多样化,并且特征之间的co-relationship不会很大,最后用concatenate的方法把feature map连接起来使网络做得很宽,然后堆叠Inception Module将网络变深。但仅仅简单这么做会使一层的计算量爆炸式增长,如下图:

在这里插入图片描述
解决办法就是在插入1x1卷积核作为bottleneck layer进行降维,以上式3x3 conv为例:
28x28x192x1x1x256, 计算量主要来自于输入前的feature map的维度256,和1x1卷积核的输出维度:192。那可否先使用1x1卷积核将输入图片的feature map维度先降低,进行信息压缩,在使用3x3卷积核进行特征提取运算?答案是:可行的。于是便有了Inception with dimensioin reduction的版本,也就是Inception v1的版本。下图便是Inception v1的计算量:
在这里插入图片描述

Stem部分:论文指出Inception module要在在网络中间使用的效果比较好,因此网络前半部分依旧使用传统的卷积层代替。 辅助函数(Axuiliary Function):从信息流动的角度看梯度消失的因为是梯度信息在BP过程中能量衰减,无法到达浅层区域,因此在中间开个口子,加个辅助损失函数直接为浅层网络提供梯度信息。 Classifier部分:从VGGNet以及NIN的论文中可知,fc层具有大量层数,因此用average pooling替代fc,减少参数数量防止过拟合。在softmax前的fc之间加入dropout,p=0.7,进一步防止过拟合。
Inception v2
Inception v2的论文,亮点不在于网络结构的变化中,提出”Batch Normalization”思想:消除因conv而产生internal covariant shift, 保持数据在训练过程中的统计特性的一致性。Inception v2的结构是在卷积层与激活函数之间插入BN层:conv-bn-relu.具体详情可见我写的关于BN的博文,以及相关论文. BN的提出进一步促进了神经网络稳定性的发展,BN可以缓解梯度消失和防止过拟合,减少dropout的使用。我之前浏览一些论坛的时候,就有人开玩笑说: Initialization is very important for neural network. If you find a good Initialization, please use BN.
Inception v3
Inception v3使用factorization的方法进一步对inception v2的参数数量进行优化和降低,并在文章中对于神经网络的设计提出了4个原则以及总结了之前的经验。该篇文章建议可以好好读一读,是inception系列写得非常好第一篇文章。
Inception v4
Inception v4是将Inception module和residual module结合起来。原因很直觉,双通路结构的residual module使梯度在BP过程中更顺畅的到达网络节点。文章通过对比了两种inception-res modules,发现加入residual module后的inception收敛得更快,但是最终的error rate并没有显著提高。可见,residual module可以加速训练。
Xception
文章指出,单个卷积核是同时映射cross-channel correlation信息和spatial correlation信息。因此,便很自然想到,基于cross-channel correlation information和spatial correlation information可以完全分离的假设,设想可否将cross-channel correlation信息和spatial correlation分开,这便Xception所做的事情。Xception使用1x1卷积核现将cross-channel correlation informatio分开,然后再使用3x3的卷积核对每一部分的channel information进行spatial information的提取,结构如下图。文章进行了两组实验,一组是将Xception与inception v3进行对比,一组是将Xception 与Xception with residual module进行对比,发现,Xception with residual module的效果更好。
GoogleNet小结:为了同时增加网络深度和宽度而又同时需要控制参数,inception v1被提出来;之后通过conv layer与conv layer之间的特性研究,提出BN的方法,形成Inception v2;在Inception v3中,把factorization的方法用到极致,连pooling layer都不曾放过,进一步减少参数总量降低网络的冗余度,从而提高网络性能。搞完网络冗余度之后,便联想到将Inception v3和residual module结合起来看看会怎么样,便有了inception v4。最后,将1x1卷积极致发挥,分离cross-channel correlation和spatial correlation,搞出Xception。
ResNet
何凯明大神在ResNet的文章指出神经网络的深度训练存在两个问题:
a. 梯度消失/梯度爆炸
b. 当网络不断加深的时候,会存在network degradation的现象。Network degradation是指网络仅仅靠堆叠conv layer加深网络会使得深度网络的效果不如浅层的网络,而且这样并不是因为过拟合所造成的,如下图。Degradation问题是一个优化问题,深度模型不能轻易被优化。
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
ResNet小结
ResNet针对梯度消失问题和Network degradation问题提出identity mapping的双通路方法。Shortcut connection的使用使得ResNet不必像GoogLeNet那样使用辅助函数帮助浅层网络接收梯度信息,Residual lerning的思想解决了深度模型优化难的问题,最终使得网络可以进一步加深直到上千层。并且shortcut connection的方案进一步启发了后续DenseNet的诞生。经过这几个网络的分析,网络一直在追求深度发展,深度是最终决定网络效果的好坏,因为网络一深,意味着非线性层的增加,网络对复杂函数的拟合能力便可以寄一步增加。最后发一张cs231n课堂网络深度发展的趋势图:
DenseNet
ResNet,HighwayNet,FractalNets都使用shortcut connection让深层的信息直接回传到浅层而取得了成功,Densenet便把shortcut connections的模式发挥到极致,每一层都互相连接,使得每一层的输入都有前面所有层的输出信息。这样做使得DenseNet可以有效的减缓梯度消失和degradation的行为,让每一层网络的输入特征多样化使得计算更加有效,shortcut connection的使用起到了深度监督式学习的效果。下图为DenseNet的连接方式:
在这里插入图片描述
在这里插入图片描述
DenseNet主要由输入端的卷积层,Dense Block, transition layer, global average pooling之后的classifier所构成。
1) Concatenation in Dense Block: 每一层输出都会和自己的输出进行简单的合并,传到下一层输入中。这样使得下一层的输入特征多样化,有效的提高计算并且帮助网络整合浅层网络特征学到discriminative feature。同时,同一 Dense bolck里的神经元相互连接达到feature reused的效果,这也就是为什么DenseNet不需要很宽也能达到很好的效果。(注意:深度和宽度都是网络的关键因素,网络的宽度必须在网络达到一定效果之后才能发挥作用)。另外,之所以不选择使用ResNet中加法合并,是因为加法是一种简单的特征融合行为,会造成信息的丢失或者紊乱。
2) Compression in transition layer: DenseNet有一个特点是:参数使用量远远少于ResNet,除了feature reused减少了网络宽度之外,就是在transition layer使用了1x1卷积进行了信息压缩,这是在GoogLeNet inception v3中使用的手法,使得模型可以更加compact。另外,参数量减少带来另外一个好处就是减少模型的复杂度防止过拟合现象发生。
3) Deeply supervision:shortcut connections形成了多通路模型,使得信息流从输入到输出畅通无阻,梯度信息也可以直接从loss function直接反馈回网络的各个节点,有一种大脑直接控制身体部位的行为。
DenseNet小结
ResNet,HighwayNet,FractalNets,DenseNet揭示了多通路模型的成功,clean shortcut connections可以feature resued,提高模型的学习效率(compact,discriminative features)有效的减缓梯度消失和network degradation的现象,并且一定程度上达到deeply supervision learning的效果,transition layer则进一步降维压缩模型参数,减少计算量。
MobileNet
参考链接:
https://blog.csdn.net/u011974639/article/details/79199306
MobileNets是为移动和嵌入式设备提出的高效模型。
本文提出的MobileNet网络架构,允许模型开发人员专门选择与其资源限制(延迟、大小)匹配的小型模型,MobileNets主要注重于优化延迟同时考虑小型网络,从深度可分离卷积的角度重新构建模型。
Architecture
Depthwise Separable Convolution
MobileNet是基于深度可分离卷积的。通俗的来说,深度可分离卷积干的活是:把标准卷积分解成深度卷积(depthwise convolution)和逐点卷积(pointwise convolution)。这么做的好处是可以大幅度降低参数量和计算量。分解过程示意图如下:
在这里插入图片描述
在这里插入图片描述
38. 哈希表常见的映射方法和寻址方法
散列函数
若关键字为k,则其值存放在f(k)的存储位置上。由此,不需比较便可直接取得所查记录。称这个对应关系f为散列函数,按这个思想建立的表为散列表。若对于关键字集合中的任一个关键字,经散列函数映象到地址集合中任何一个地址的概率是相等的,则称此类散列函数为均匀散列函数(Uniform Hash function),这就是使关键字经过散列函数得到一个"随机的地址",从而减少碰撞。散列函数能使对一个数据序列的访问过程更加迅速有效,通过散列函数,数据元素将被更快地定位。一个好的散列函数一般应该考虑下列因素:1.计算简单,以便提高转换速度。 2.关键词对应的地址空间分布均匀,以尽量减少冲突。
常见的散列函数(映射方法)
1)直接寻址法 取关键字或者关键字的某个线性函数值作为哈希地址,即H(Key)=Key或者H(Key)=a*Key+b(a,b为整数),这种散列函数也叫做自身函数.如果H(Key)的哈希地址上已经有值了,那么就往下一个位置找,直到找到H(Key)的位置没有值了就把元素放进去。
2)数字分析法 数字分析法就是找出数字的规律,尽可能利用这些数据来构造冲突几率较低的散列地址。
3) 平方取中法 取关键字平方后的中间几位作为散列地址。这种方法的原理是通过取平方扩大差别,平方值的中间几位和这个数的每一位都相关,则对不同的关键字得到的哈希函数值不易产生冲突,由此产生的哈希地址也较为均匀。该方法适用于关键字中的每一位都有某些数字重复出现频度很高的现象。
4) 折叠法 折叠法是将关键字分割成位数相同的几部分,最后一部分位数可以不同,然后取这几部分的叠加和(注意:叠加和时去除进位)作为散列地址。数位叠加可以有移位叠加和间界叠加两种方法。移位叠加是将分割后的每一部分的最低位对齐,然后相加;间界叠加是从一端向另一端沿分割界来回折叠,然后对齐相加。该方法适用于关键字特别多的情况。
5) 随机数法 选择一个随机数,作为散列地址,通常用于关键字长度不同的场合。
6)除留余数法 取关键字被某个不大于散列表表长m的数p除后所得的余数为散列地址.即H(Key)=Key MOD p,p<=m.不仅可以对关键字直接取模,也可在折叠、平方取中等运算之后取模。对p的选择很重要,一般取素数或m,若p选得不好,则很容易产生冲突。
散列表的查找过程基本上和造表过程同样。一些关键码可通过散列函数转换的地址直接找到,还有一些关键码在散列函数得到的地址上产生了冲突,须要按处理冲突的方法进行查找。在介绍的三种处理冲突的方法中,产生冲突后的查找仍然是给定值与关键码进行比較的过程。所以,对散列表查找效率的量度,依旧用平均查找长度来衡量。
哈希寻址
查找过程中,关键码的比較次数,取决于产生冲突的多少,产生的冲突少,查找效率就高,产生的冲突多,查找效率就低。因此,影响产生冲突多少的因素,也就是影响查找效率的因素。影响产生冲突多少有下面三个因素:
a. 散列函数是否均匀;
b. 处理冲突的方法;
c. 散列表的装填因子。
散列表的装填因子定义为:α= 填入表中的元素个数 / 散列表的长度
α是散列表装满程度的标志因子。因为表长是定值,α与“填入表中的元素个数”成正比,所以,α越大,填入表中的元素较多,产生冲突的可能性就越大;α越小,填入表中的元素较少,产生冲突的可能性就越小。
实际上,散列表的平均查找长度是装填因子α的函数,仅仅是不同处理冲突的方法有不同的函数。

  1. resnet50网络的bottleneck结构
    在这里插入图片描述
    bottleneck先通过一个1x1的卷积减少通道数,使得中间卷积的通道数减少为1/4;中间的普通卷积做完卷积后输出通道数等于输入通道数;第三个卷积用于增加(恢复)通道数,使得bottleneck的输出通道数等于bottleneck的输入通道数。这两个1x1卷积有效地较少了卷积的参数个数和计算量。

  2. softmax函数,交叉熵公式以及softmax损失之前的区别和联系。
    softmax函数是将神经网络得到的多个值,进行归一化处理,使得到的值在[0,1]之间,让结果变得可解释。即可以将结果看作是概率,某个类别概率越大,将样本归为该类别的可能性也就越高。
    在这里插入图片描述
    交叉熵损失函数的形式: 在这里插入图片描述
    之前推导LR是的交叉熵损失其实和这里是相同的, L = - 求和(ylogf(y) + (1 - y)log(1 - y))

  3. 虚函数的实现机制
    参考: https://blog.csdn.net/weixin_40237626/article/details/82313339
    虚函数的实现机制是虚函数表。子类没有重载父类的虚函数,那么虚函数表和父类是一样的,如果子类重载了父类的虚函数,那么子类的虚函数会出现覆盖。
    一般继承无虚函数覆盖:
    在这里插入图片描述
    一般继承有虚函数覆盖
    在这里插入图片描述
    多重继承无虚函数覆盖
    在这里插入图片描述
    多重继承有虚函数覆盖
    在这里插入图片描述

  4. python参数传递时,* 和 ** 的区别
    定义函数时在形参前面加上 * 或**,* 所对应的形参(如上面的a)会被解释为一个元组tuple 或list,而**所对应的形参(如上面的b)会被解释为一个字典。具体调用时参数的传递见下面的代码:

def f(*a,**b):
    print(a)
    print(b)
	a=3
	b=4
	f(a,b,m=1,n=2)

上面代码的运行结果是:
(3, 4)
{'n': 2, 'm': 1}

可见,对于不使用关键字传递的变量,会被作为元组的一部分传递给a,而使用关键字传递的变量作为字典的一部分传递给了**b。
此外,在进行函数
调用*时,与之配套的就有个被称为解包裹的方式:

def f(*a,**b):
    print(a)
    print(b)
	c=3
	d=4
	h=(c,d)
	k={"m":1,"n":2}
	f(*h,**k)
	
上面代码的运行结果是:
(3, 4)
{'n': 2, 'm': 1}

把元组或字典作为参数传入时,如果要适配包裹形式的形参定义(如上面将h传给a,k传给**b),按照元组用,字典用**的方式“解包裹”传递即可。

  1. 红黑树和普通平衡二叉树的区别?
    参考:https://github.com/julycoding/The-Art-Of-Programming-By-July/blob/master/ebook/zh/03.01.md
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值