0%

ML/DL面试问题笔记

一些面试问题的笔记

深度学习基础

  1. 为什么要归一化?为什么归一化能够提高求解最优解的速度?
  2. 归一化与标准化
    1. 归一化/标准化的目的是为了获得某种“无关性”——偏置无关、尺度无关、长度无关……当归一化/标准化方法背后的物理意义和几何含义与当前问题的需要相契合时,其对解决该问题就有正向作用,反之,就会起反作用。所以,“何时选择何种方法”取决于待解决的问题,即problem-dependent。
    2. https://www.cnblogs.com/shine-lee/p/11779514.html
    3. 有什么联系和区别?
      1. 归一化和标准化的区别:归一化是将样本的特征值转换到同一量纲下把数据映射到[0,1]或者[-1, 1]区间内,仅由变量的极值决定,因区间放缩法是归一化的一种。标准化是依照特征矩阵的列处理数据,其通过求z-score的方法,转换为标准正态分布,和整体样本分布相关,每个样本点都能对标准化产生影响。它们的相同点在于都能取消由于量纲不同引起的误差;都是一种线性变换,都是对向量X按照比例压缩再进行平移。
    4. 归一化类型:
      1. min-max
      2. 线型比例,就是除以最大值
      3. zscore转到标准正态分布
    5. 什么时候需要使用feature scaling?
      1. 涉及或隐含距离计算的算法,比如K-means、KNN、PCA、SVM等,一般需要feature scaling,因为
        • zero-mean一般可以增加样本间余弦距离或者内积结果的差异,区分力更强,假设数据集集中分布在第一象限遥远的右上角,将其平移到原点处,可以想象样本间余弦距离的差异被放大了。在模版匹配中,zero-mean可以明显提高响应结果的区分度。
        • 就欧式距离而言,增大某个特征的尺度,相当于增加了其在距离计算中的权重,如果有明确的先验知识表明某个特征很重要,那么适当增加其权重可能有正向效果,但如果没有这样的先验,或者目的就是想知道哪些特征更重要,那么就需要先feature scaling,对各维特征等而视之。
      2. 增大尺度的同时也增大了该特征维度上的方差
        1. PCA算法倾向于关注方差较大的特征所在的坐标轴方向,其他特征可能会被忽视,因此,在PCA前做Standardization效果可能更好,如下图所示,图片来自scikit learn-Importance of Feature Scaling,
      3. 损失函数中含有正则项时,一般需要feature scaling:
        1. 对于线性模型𝑦=𝑤𝑥+𝑏而言,𝑥的任何线性变换(平移、放缩),都可以被𝑤和𝑏“吸收”掉,理论上,不会影响模型的拟合能力。但是,如果损失函数中含有正则项,如𝜆||𝑤||2,𝜆为超参数,其对𝑤的每一个参数施加同样的惩罚,但对于某一维特征𝑥𝑖而言,其scale越大,系数𝑤𝑖越小,其在正则项中的比重就会变小,相当于对𝑤𝑖惩罚变小,即损失函数会相对忽视那些scale增大的特征,这并不合理,所以需要feature scaling,使损失函数平等看待每一维特征。
      4. 梯度下降算法,需要feature scaling。
        1. 梯度下降的参数更新公式:。𝐸(𝑊) 为损失函数,收敛速度取决于:参数的初始位置到local minima的距离,以及学习率𝜂的大小。
        2. 一维情况下,在local minima附近,不同学习率对梯度下降的影响如下图所示,
        3. 多维情况下可以分解成多个上图,每个维度上分别下降,参数𝑊为向量,但学习率只有1个,即所有参数维度共用同一个学习率(暂不考虑为每个维度都分配单独学习率的算法)。收敛意味着在每个参数维度上都取得极小值,每个参数维度上的偏导数都为0,但是每个参数维度上的下降速度是不同的,为了每个维度上都能收敛,学习率应取所有维度在当前位置合适步长中最小的那个。下面讨论feature scaling对gradient descent的作用
      5. 对于传统的神经网络,对输入做feature scaling也很重要,因为采用sigmoid等有饱和区的激活函数,如果输入分布范围很广,参数初始化时没有适配好,很容易直接陷入饱和区,导致梯度消失,所以,需要对输入做Standardization或映射到[0,1]、[−1,1],配合精心设计的参数初始化方法,对值域进行控制。但自从有了Batch Normalization,每次线性变换改变特征分布后,都会重新进行Normalization,似乎可以不太需要对网络的输入进行feature scaling了?但习惯上还是会做feature scaling。
    6. 什么时候不需要feature scaling?
      1. 与距离计算无关的概率模型,不需要feature scaling,比如Naive Bayes;
      2. 与距离计算无关的基于树的模型,不需要feature scaling,比如决策树、随机森林等,树中节点的选择只关注当前特征在哪里切分对分类更好,即只在意特征内部的相对大小,而与特征间的相对大小无关。
    7. 什么时候用z-score 归一化?
      1. 当特征的区间相差非常大时使用。比如X1区间是[0,2000],X2区间是[1,5],其所形成的等高线非常尖。当使用梯度下降法寻求最优解时,很有可能走“之字型”路线(垂直等高线走),从而导致需要迭代很多次才能收敛。
    8. 什么时候用min-max归一化?
      1. 适和于数值比较集中的情况。如果max和min不稳定,很容易使得归一化结果不稳定,使得后续使用效果也不稳定,实际使用中可以用经验常量值来替代max和min。而且当有新数据加入时,可能导致max和min的变化,需要重新定义。
  3. 学习率的影响
    1. 常用的学习率衰减方法,包括:分段常数衰减、指数衰减、自然指数衰减、多项式衰减、间隔衰减、多间隔衰减、逆时间衰减、Lambda衰减、余弦衰减、诺姆衰减、loss自适应衰减、线性学习率热身
  4. batch size的影响
    1. 传统的梯度下降用所有数据
      1. 缺点1:如果是凸问题,局部最优就是全局最优,准确的梯度计算可以使梯度更新朝着正确的方向进行,以较快的速度达到全局最优解。但是真实场景中,很多都是非凸,这样容易陷入局部最优点或者鞍点。
      2. 缺点2:当整体样本数不大时,采用全体样本做batch size不会非常耗时,而当样本数很大时,每一次的计算将会非常耗时,也会导致内存爆炸。
    2. 随机梯度下降SGD:
      1. 随机梯度下降法时,batch size值为1,每次获得的梯度都是根据当前的随机样本计算得来。由一个样本的梯度来近似所有的样本,会导致梯度估计不是很准确
      2. 梯度易收到极端值的影响,导致损失剧烈震荡。但因为batch size为1,随机梯度下降法的计算速度会非常快。
    3. mini-batch:
      1. 优点:
        1. 用部分样本来近似全部样本,梯度相对于batch size为1更为准确,同时相比与使用全部样本,计算量减小,计算速度和收敛速度都会得到提升
        2. 相对于训练全部样本,由于梯度存在不准确性,噪声的影响很可能会让梯度下降的过程中离开局部最优点或鞍点,从而有机会寻找全局最优点
      2. 为什么10000样本训练1次会比100样本训练100次收敛慢呢?
        1. 我们假设样本真实的标准差为 𝜎,则 𝑛 个样本均值的标准差为表明使用更多样本来估计梯度的方法回报是低于线性的。10000个样本训练一次和100个样本训练一次,由于计算量是线性的,前者的计算量是后者的100倍,但均值标准差只比后者降低了10倍,那么在相同的计算量下(同样训练10000个样本),小样本的收敛速度是远快于使用整个样本集的
      3. 如何选择一个适当的batch size呢?
        1. 更大的batch size会得到更精确的梯度估计值,但其估计梯度的回报是低于线性的。要更久收敛
        2. 如果训练集较小,可以直接使用梯度下降法,batch size等于样本集大小。
        3. 使用GPU时,通常使用2的幂数作为batch size可以获得更少的运行时间。
  5. 在参数初始化时,为什么不能全零初始化?(转自paddlepedia)
    1. 梯度更新后,由于前面的初始值都是一样的,所以会导致梯度更新后的参数在每一层都是一样的。再因为初始值相同,所以会导致无论经过多少次网络训练,相同网络内的参数都是相同的。使得网络在学习的时候没有重点,对所有特征处理相同时,导致模型无法收敛训练失败。这种现象也称为对称失效。
    2. 同样,如果被初始化为相同的非零值时,也是这样的情况。此时的模型就和线性模型的效果相似。
  6. 常见的初始化方法
    1. 非常常见的方式是采用高斯分布或均匀分布来对权重进行随机初始化。高斯分布和均匀分布的选择似乎没有很大差别,但初始分布的大小对于优化过程的结果和网络泛化能力都有很大影响。
    2. 高斯分布:高斯分布初始化:使用一个均值为 𝜇,方差为 𝜎2 的高斯分布 𝑁(𝜇,𝜎2) 对每个参数进行随机初始化,通常情况下,𝜇=0,并对生成的数乘上一个小数,把权重初始化为很小的随机数。比如:𝑤=0.01∗𝑛𝑝.𝑟𝑎𝑛𝑑𝑜𝑚.𝑟𝑎𝑛𝑑(𝐷,𝐻),这里选择乘以0.01初始化为一个很小的数是因为,如果最初随机到的 𝑤 值很大,当我们选择 sigmoid 或 tanh 激活函数时,函数值 𝑠𝑖𝑔𝑚𝑜𝑖𝑑(⋅) 或 𝑡𝑎𝑛ℎ(⋅) 会停留在一个很平坦的地方,激活值接近饱和,导致梯度下降时,梯度很小,学习变得缓慢。但也不是说权重值越小越好,如果权重值过小,会导致在反向传播时计算得到很小的梯度值,在不断的反向传播过程中,引起梯度消失。
    3. 均匀分布:均匀分布初始化:在一个给定区间 [−𝑟,𝑟] 内采取均匀分布进行初始化。假设随机变量在区间 [𝑎,𝑏] 内均匀分布,则其方差为。因此,当在 [−𝑟,𝑟] 的区间内均匀分布采样,并满足时,则有
    4. 上述两种基于固定方差的初始随机化方法中,关键点在于如何设置方差 𝜎2。过大或过小的方差都会导致梯度下降缓慢,网络训练效果不好等问题。为了降低固定方差对网络性能及优化效率的影响,基于固定方差的随机初始化一般要配合逐层归一化来使用。
  7. 基于方差缩放的参数初始化
    1. 方差缩放方法能够根据神经元的链接数量来自适应地调整初始化分布地方差,尽可能的保证每个神经元的输入和输出方差一致。那么,为什么要保证前后方差的一致性呢?这是因为如果输入空间和输出空间的方差差别较大,也就是说数据空间分布差异较大,那么在反向传播时可能会引起梯度消失或爆炸问题。比如,当输入空间稀疏,输出空间稠密时,将在输出空间计算得到的误差反向传播给输入空间时,这个误差可能会显得微不足道,从而引起梯度消失。而当输入空间稠密,输出空间稀疏时,将误差反向传播给输入空间,就可能会引起梯度爆炸,使得模型震荡。
    2. Xavier初始化
    3. Kaiming初始化
  8. 激活函数
    1. 作用:
      1. 如果不用激活函数,每一层输出都是上层输入的线性函数,无论神经网络有多少层,最终的输出都是输入的线性组合。 激活函数给神经元引入了非线性因素,使得神经网络可以任意逼近任何非线性函数。
    2. sigmoid:
      1. 优点:
        1. sigmoid 函数的输出映射在 (0,1) 之间,单调连续,输出范围有限,优化稳定,可以用作输出层;
        2. 求导容易;
      2. 缺点:
        1. 由于其软饱和性,一旦落入饱和区梯度就会接近于0,根据反向传播的链式法则,容易产生梯度消失,导致训练出现问题;
        2. Sigmoid函数的输出恒大于0。非零中心化的输出会使得其后一层的神经元的输入发生偏置偏移(Bias Shift),并进一步使得梯度下降的收敛速度变慢;
        3. 计算时,由于具有幂运算,计算复杂度较高,运算速度较慢。
    3. tanh
      1. 优点:
        1. tanh 比 sigmoid 函数收敛速度更快;
        2. 相比 sigmoid 函数,tanh 是以 0 为中心的;
      2. 缺点:
        1. 与 sigmoid 函数相同,由于饱和性容易产生的梯度消失;
        2. 与 sigmoid 函数相同,由于具有幂运算,计算复杂度较高,运算速度较慢。
    4. ReLU
      1. 优点:
        1. 收敛速度快;
        2. 相较于 𝑠𝑖𝑔𝑚𝑜𝑖𝑑 和 𝑡𝑎𝑛ℎ 中涉及了幂运算,导致计算复杂度高, ReLU​可以更加简单的实现;
        3. 当输入 𝑥>=0 时,ReLU​ 的导数为常数,这样可有效缓解梯度消失问题;
        4. 当 𝑥<0 时,ReLU​ 的梯度总是 0,提供了神经网络的稀疏表达能力;
      2. 缺点:
        1. ReLU​ 的输出不是以 0 为中心的;
        2. 神经元坏死现象,某些神经元可能永远不会被激活,导致相应参数永远不会被更新;
        3. 不能避免梯度爆炸问题;
    5. 激活函数的选择
      1. 浅层网络在分类器时,𝑠𝑖𝑔𝑚𝑜𝑖𝑑 函数及其组合通常效果更好。
      2. 由于梯度消失问题,有时要避免使用 𝑠𝑖𝑔𝑚𝑜𝑖𝑑 和 𝑡𝑎𝑛ℎ 函数。
      3. 𝑟𝑒𝑙𝑢 函数是一个通用的激活函数,目前在大多数情况下使用。
      4. 如果神经网络中出现死神经元,那么 𝑝𝑟𝑒𝑙𝑢 函数就是最好的选择。
      5. 𝑟𝑒𝑙𝑢 函数只能在隐藏层中使用。
      6. 通常,可以从 𝑟𝑒𝑙𝑢 函数开始,如果 𝑟𝑒𝑙𝑢 函数没有提供最优结果,再尝试其他激活函数。
    6. 激活函数相关问题
      1. 为什么 𝑟𝑒𝑙𝑢 不是全程可微/可导也能用于基于梯度的学习?
        1. 从数学的角度看 𝑟𝑒𝑙𝑢 在 0 点不可导,因为它的左导数和右导数不相等;但在实现时通常会返回左导数或右导数的其中一个,而不是报告一个导数不存在的错误,从而避免了这个问题。
      2. 为什么 𝑡𝑎𝑛ℎ 的收敛速度比 𝑠𝑖𝑔𝑚𝑜𝑖𝑑 快?
        1. 由上面两个公式可知 𝑡𝑎𝑛ℎ 引起的梯度消失问题没有 𝑠𝑖𝑔𝑚𝑜𝑖𝑑 严重,所以 𝑡𝑎𝑛ℎ 收敛速度比 𝑠𝑖𝑔𝑚𝑜𝑖𝑑 快。
      3. sigmoid 和 softmax 有什么区别?
        1. 二分类问题时 𝑠𝑖𝑔𝑚𝑜𝑖𝑑 和 𝑠𝑜𝑓𝑡𝑚𝑎𝑥 是一样的,都是求 𝑐𝑟𝑜𝑠𝑠 𝑒𝑛𝑡𝑟𝑜𝑝𝑦 𝑙𝑜𝑠𝑠 ,而 𝑠𝑜𝑓𝑡𝑚𝑎𝑥 可以用于多分类问题。
        2. 𝑠𝑜𝑓𝑡𝑚𝑎𝑥 是 𝑠𝑖𝑔𝑚𝑜𝑖𝑑 的扩展,因为,当类别数 𝑘=2 时,𝑠𝑜𝑓𝑡𝑚𝑎𝑥 回归退化为 𝑙𝑜𝑔𝑖𝑠𝑡𝑖𝑐 回归。
        3. 𝑠𝑜𝑓𝑡𝑚𝑎𝑥 建模使用的分布是多项式分布,而 𝑙𝑜𝑔𝑖𝑠𝑡𝑖𝑐 则基于伯努利分布。
        4. 多个 𝑙𝑜𝑔𝑖𝑠𝑡𝑖𝑐 回归通过叠加也同样可以实现多分类的效果,但是 𝑠𝑜𝑓𝑡𝑚𝑎𝑥 回归进行的多分类,类与类之间是互斥的,即一个输入只能被归为一类;多 𝑙𝑜𝑔𝑖𝑠𝑡𝑖𝑐 回归进行多分类,输出的类别并不是互斥的,即”苹果”这个词语既属于”水果”类也属于”3𝐶”类别。
  9. 评价指标
    1. F1
    2. PR曲线:(Recall,Precision)
    3. mAP:
      1. AP(Average Precision):某一类P-R曲线下的面积。
      2. mAP(mean Average Precision):所有类别的AP值取平均。
  10. 为什么交叉熵损失可以用于分类任务?
    1. https://www.cnblogs.com/shine-lee/p/12032066.html
    2. 损失函数的角度
      1. 损失函数是网络学习的指挥棒,它引导着网络学习的方向——能让损失函数变小的参数就是好参数。 所以,损失函数的选择和设计要能表达你希望模型具有的性质与倾向。 对比交叉熵和均方误差损失,可以发现,两者均在𝑦̂ =𝑦=1时取得最小值0,但在实践中𝑦̂ 𝑝只会趋近于1而不是恰好等于1,在𝑦̂ 𝑝<1的情况下, 交叉熵只与label类别有关,𝑦̂ 𝑝越趋近于1越好 均方误差不仅与𝑦̂ 𝑝有关,还与其他项有关,它希望𝑦̂ 1,…,𝑦̂ 𝑝−1,𝑦̂ 𝑝+1,…,𝑦̂ 𝐾越平均越好,即在1−𝑦̂ 𝑝𝐾−1时取得最小值 分类问题中,对于类别之间的相关性,我们缺乏先验。
      2. 虽然我们知道,与“狗”相比,“猫”和“老虎”之间的相似度更高,但是这种关系在样本标记之初是难以量化的,所以label都是one hot。 在这个前提下,均方误差损失可能会给出错误的指示,比如猫、老虎、狗的3分类问题,label为[1,0,0],在均方误差看来,预测为[0.8,0.1,0.1]要比[0.8,0.15,0.05]要好,即认为平均总比有倾向性要好,但这有悖我们的常识。 而对交叉熵损失,既然类别间复杂的相似度矩阵是难以量化的,索性只能关注样本所属的类别,只要𝑦̂ 𝑝越接近于1就好,这显示是更合理的。
    3. softmax反向传播角度
      1. 𝑦̂ 𝑝为正确分类的概率,为0时表示分类完全错误,越接近于1表示越正确。根据链式法则,按理来讲,对与𝑧𝑝相连的权重,损失函数的偏导会含有𝑦̂ 𝑝(1−𝑦̂ 𝑝)这一因子项,𝑦̂ 𝑝=0时分类错误,但偏导为0,权重不会更新,这显然不对——分类越错误越需要对权重进行更新。
      2. 对交叉熵损失,恰好将𝑦̂ 𝑝(1−𝑦̂ 𝑝)中的𝑦̂ 𝑝消掉,避免了上述情形的发生,且𝑦̂ 𝑝越接近于1,偏导越接近于0,即分类越正确越不需要更新权重,这与我们的期望相符。
      3. 而对均方误差损失,看偏导,仍会发生上面所说的情况——𝑦̂ 𝑝=0,分类错误,但不更新权重。
      4. 综上,对分类问题而言,无论从损失函数角度还是softmax反向传播角度,交叉熵都比均方误差要好。

卷积模型

  1. 相较于全连接网络,卷积在图像处理方面有什么样的优势?
    1. 保留空间信息
      1. 在卷积运算中,计算范围是在像素点的空间邻域内进行的,它代表了对空间邻域内某种特征模式的提取。对比全连接层将输入展开成一维的计算方式,卷积运算可以有效学习到输入数据的空间信息。
    2. 局部连接
      1. 在卷积操作中,每个神经元只与局部的一块区域进行连接。对于二维图像,局部像素关联性较强,这种局部连接保证了训练后的滤波器能够对局部特征有最强的响应,使神经网络可以提取数据的局部特征。
    3. 权重共享
      1. 卷积计算实际上是使用一组卷积核在图片上进行滑动,计算乘加和。因此,对于同一个卷积核的计算过程而言,在与图像计算的过程中,它的权重是共享的。这其实就大大降低了网络的训练难度
    4. 不同层级卷积提取不同特征
      1. 在CNN网络中,通常使用多层卷积进行堆叠,从而达到提取不同类型特征的作用。比如:浅层卷积提取的是图像中的边缘等信息;中层卷积提取的是图像中的局部信息;深层卷积提取的则是图像中的全局信息。
  2. 如何计算感受野?
    1. https://www.cnblogs.com/shine-lee/p/12069176.html
  3. 感受野中心计算?
  4. 1*1卷积的作用是什么?
    1. 实现信息的跨通道交互与整合。考虑到卷积运算的输入输出都是3个维度(宽、高、多通道),所以1×1 卷积实际上就是对每个像素点,在不同的通道上进行线性组合,从而整合不同通道的信息。
    2. 对卷积核通道数进行降维和升维减少参数量。经过1×1 卷积后的输出保留了输入数据的原有平面结构,通过调控通道数,从而完成升维或降维的作用。
    3. 利用1×1 卷积后的非线性激活函数,在保持特征图尺寸不变的前提下,大幅增加非线性
  5. 深度可分离卷积的计算方式以及意义是什么?
    1. 它不仅仅涉及空间维度,还涉及深度维度(即 channel 维度)
    2. 运算量相较标准卷积而言,计算量少了很多

预训练相关

  1. Multi-Head Attention时间复杂度?
    1. Self-Attention时间复杂度:𝑂(𝑛2⋅𝑑) (这里的2是表示平方) ,这里,n是序列的长度,d是embedding的维度。
    2. Self-Attention包括三个步骤:相似度计算,softmax和加权平均,它们分别的时间复杂度是:
    3. 相似度计算可以看作大小为(n,d)和(d,n)的两个矩阵相乘: (𝑛,𝑑)∗(𝑑,𝑛)=(𝑛2⋅𝑑),得到一个(n,n)的矩阵
    4. softmax就是直接计算了,时间复杂度为: 𝑂(𝑛2)
    5. 加权平均可以看作大小为(n,n)和(n,d)的两个矩阵相乘: (𝑛,𝑛)∗(𝑛,𝑑)=(𝑛2⋅𝑑),得到一个(n,d)的矩阵
    6. 因此,Self-Attention的时间复杂度是: 𝑂(𝑛2⋅𝑑)
  2. Transformer的权重共享?
    1. Encoder和Decoder间的Embedding层权重共享;
      1. Transformer被应用在机器翻译任务中,源语言和目标语言是不一样的,但它们可以共用一张大词表,对于两种语言中共同出现的词(比如:数字,标点等等)可以得到更好的表示,而且对于Encoder和Decoder,嵌入时都只有对应语言的embedding会被激活,因此是可以共用一张词表做权重共享的。
      2. Transformer词表用了bpe来处理,所以最小的单元是subword。英语和德语同属日耳曼语族,有很多相同的subword,可以共享类似的语义。而像中英这样相差较大的语系,语义共享作用可能不会很大。但是,共用词表会使得词表数量增大,增加softmax的计算时间,因此实际使用中是否共享可能要根据情况权衡。
    2. Decoder中Embedding层和FC层权重共享;
      1. Embedding层可以说是通过onehot去取到对应的embedding向量,FC层可以说是相反的,通过向量(定义为 x)去得到它可能是某个词的softmax概率,取概率最大(贪婪情况下)的作为预测值。
      2. 那哪一个会是概率最大的呢?在FC层的每一行量级相同的前提下,理论上和 x 相同的那一行对应的点积和softmax概率会是最大的(可类比本文问题1)。
      3. 因此,Embedding层和FC层权重共享,Embedding层中和向量 x 最接近的那一行对应的词,会获得更大的预测概率。实际上,Decoder中的Embedding层和FC层有点像互为逆过程。
  3. BERT, GPT, ELMO区别
  4. NSP和SOP的区别?

计算机视觉

  1. ResNet中Residual block解决了什么问题?
    1. 解决了网络退化的问题。在Resnet中,56层的深层网络,在训练集和测试集上的表现都不如20层的浅层网络。这种随着网络层数加深,accuracy逐渐饱和,然后出现急剧下降,具体表现为深层网络的训练效果反而不如浅层网络好的现象,被称为网络退化(degradation)。
    2. 为什么会引起网络退化呢?按照理论上的想法,当浅层网络效果不错的时候,网络层数的增加即使不会引起精度上的提升也不该使模型效果变差。但事实上非线性的激活函数的存在,会造成很多不可逆的信息损失,网络加深到一定程度,过多的信息损失就会造成网络的退化。
    3. 而残差连接就是让网络拥有恒等映射的能力,使每一次能够学到更细化的特征从而提高网络精度。
    4. 恒等映射即为 𝐻(𝑥)=𝑥,已有的神经网络结构很难做到这一点,但是如果我们将网络设计成 𝐻(𝑥)=𝐹(𝑥)+𝑥,即 𝐹(𝑥)=𝐻(𝑥)−𝑥,那么只需要使残差函数 𝐹(𝑥)=0,就构成了恒等映射 𝐻(𝑥)=𝐹(𝑥)。
    5. 残差结构的目的是,随着网络的加深,使 𝐹(𝑥) 逼近于0,使得深度网络的精度在最优浅层网络的基础上不会下降。看到这里你或许会有疑问,既然如此为什么不直接选取最优的浅层网络呢?这是因为最优的浅层网络结构并不易找寻,而ResNet可以通过增加深度,找到最优的浅层网络并保证深层网络不会因为层数的叠加而发生网络退化。
  2. 计算IOU
    1. 代码
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      def box_iou_xyxy(box1, box2):# 坐标轴左上角是原点,往下是y,往右是x
      x1min, y1min, x1max, y1max = box1[0], box1[1], box1[2], box1[3]
      x2min, y2min, x2max, y2max = box2[0], box2[1], box2[2], box2[3]
      s1 = (x1max - x1min + 1.) * (y1max - y1min + 1.)
      s2 = (x2max - x2min + 1.) * (y2max - y2min + 1.)

      xmin = np.maximum(x1min, x2min)
      xmax = np.minimum(x1max, x2max)
      ymin = np.maximum(y1min, y2min)
      ymax = np.minimum(y1max, y2max)

      inter = np.maximum(xmax - xmin + 1., 0) * np.maximum(ymax - ymin + 1., 0)
      union = s1 + s2 - inter
      iou = inter / union
      return iou
  3. 非极大值抑制(NMS)
    1. 主要用于在目标检测过程中,消除重叠较大的冗余预测框
    2. 基本思想是,如果有多个预测框都对应同一个物体,则只选出得分最高的那个预测框,剩下的预测框被丢弃掉。
    3. 如何判断两个预测框对应的是同一个物体呢,标准该怎么设置?
      1. 如果两个预测框的类别一样,而且他们的位置重合度比较大,则可以认为他们是在预测同一个目标。
      2. 非极大值抑制的做法是,选出某个类别得分最高的预测框,然后看哪些预测框跟它的IoU大于阈值,就把这些预测框给丢弃掉。这里IoU的阈值是超参数,需要提前设置,这里我们参考YOLOv3算法,里面设置的是0.5。
    4. 如果是多分类,就要对每个类别进行NMS
    5. 代码
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      def nms(bboxes, scores, score_thresh, nms_thresh):
      inds = np.argsort(scores)
      inds = inds[::-1] # 从大到小排序的下标
      keep_inds = []
      while (len(inds) > 0):
      cur_ind = inds[0]
      current_box = bboxes[cur_ind]
      cur_score = scores[cur_ind]
      if cur_score < score_thresh:
      break

      keep = True
      for ind in keep_inds:
      remain_box = bboxes[ind]
      iou = box_iou_xyxy(current_box, remain_box)

      if iou > nms_thresh:
      keep = False
      break
      if keep:
      keep_inds.append(cur_ind)
      inds = inds[1:]
      return np.array(keep_inds)
  4. 写中值滤波
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
       def padding_0(img):
    a = np.insert(img, 0, 0, 0)
    b = np.insert(a, 0, 0, 0)
    c = np.insert(b, 0, 0, 1)
    d = np.insert(c, 0, 0, 1)
    h_zeros = np.zeros((d.shape[0], 1))
    e = np.hstack((d, h_zeros))
    f = np.hstack((e, h_zeros))
    w_zeros = np.zeros((1, f.shape[1]))
    g = np.vstack((f, w_zeros))
    img = np.vstack((g, w_zeros))
    return img

    def middle_filter(img):
    img = padding_0(img)
    for i in range(2, img.shape[0] - 2):
    for j in range(2, img.shape[0] - 2):
    mat = img[i - 2:i + 3, j - 2:j + 3]
    middle = np.median(mat)
    img[i, j] = middle
    return img
  5. 根据要求写dataloader
    1. 自定义dataset,实现
      1. __init__初始化读入数据和label
      2. __len__返回数据集长度
      3. __getitem__返回index对应的数据
    2. 自定义Dataloader中的collate_fn,这个是对每个batch数据进行的操作。参考PyTorch实现自由的数据读取