深度学习杂谈

深度学习杂谈

    • 一、关于TensorFlow
      • 1.熟悉TensorFlow的基本概念,graph、session、tensor等
      • 2.熟悉tensorflow调用gpu的方法,多GPU使用方法
      • 3.熟悉tensorflow的数据集tfrecord的构建及使用方法
      • 4.熟悉tensorflow的两种输入构建方法placeholder和dataset
      • 5.熟悉tensorflow的两种保存模型的方法ckpt和pb
    • 二、概念
      • 1.深度学习的一些基本概念,学习率、batch、epoch、optimizer、评价函数(损失函数)等
        • 1.1 学习率(Learning Rate)
        • 1.2 Batch(批次)
        • 1.3 Epoch(轮次)
        • 1.4 Optimizer(优化器)
          • 1.4.1 梯度下降法(Gradient Descent)
            • 1.4.1.1 标准梯度下降法(GD, Gradient Descent)
            • 1.4.1.2 批量梯度下降法(BGD)
            • 1.4.1.3 随机梯度下降法(SGD)
            • 1.4.1.4 小批量梯度下降法(Mini-batch Gradient Descent)
          • 1.4.2 动量优化法
            • 1.4.2.1 Momentum
            • 1.4.2.2 NAG(Nesterov accelerated gradient)
          • 1.4.3 自适应学习率优化算法
            • 1.4.3.1 AdaGrad
            • 1.4.3.2 AdaGrad
            • 1.4.3.3 RMSprop
            • 1.4.3.4 Adam: Adaptive Moment Estimation
        • 1.5 损失函数
          • 1.5.1 Regression loss
            • 1.5.1.1 Mean Square Error (MSE/ L2 Loss) ——均方误差
            • 1.5.1.2 Mean Absolute Error (MAE/ L1 loss) ——平均绝对误差
            • 1.5.1.3 MSE(L2 Loss)VS2 MAE(L1 Loss)
            • 1.5.1.4 Smooth Mean Absolute Error/ Huber Loss——平滑的平均绝对误差
            • 1.5.1.5 Log cosh loss ——Log-Cosh损失
            • 1.5.1.6 Quantile loss——分位数损失
          • 1.5.2 Regression loss Comparison
          • 1.5.3 Classifications loss
            • 1.5.3.1 Cross Entropy (交叉熵)
            • 1.5.3.2 Binary cross entropy or negative log likelihood (二元交叉熵或负对数似然)
            • 1.5.3.3 Focal loss (灶性损失)
            • 1.5.3.4 Hinge loss (合页损失)
            • 1.5.3.5 Square loss (平方损失)
            • 1.5.3.6 Logistic loss (逻辑回归损失)
            • 1.5.3.7 Exponential loss (指数损失)
            • 1.5.3.8 Kullback–Leibler divergence (相对熵)
          • 1.5.4 Classifications loss Comparison
            • 1.5.5.1 Hinge embedding criteria
            • 1.5.5.2 L1 Hinge embedding
            • 1.5.5.3 Cosine distance
          • 1.5.6 Miscelaneus losses
            • 1.5.6.1 Haversine distance
            • 1.5.6.2 Weighted average of muliple losses
      • 2.理解卷积的具体运算流程,输入层通过卷积得到输出层的细节
      • 3.卷积过程中,Padding,Stride是什么?选择valid和same的区别以及输出层的尺寸变化
      • 4.对池化、上采样、空洞卷积、反卷积的理解
      • 5.推导BP算法的全流程
      • 6.理解梯度消失和梯度爆炸的原因和解决方法
      • 7.对Batch Normalization、Group Normalization、Spectral Normalization、Layer normalization、 Instance Normalization的理解和如何使用
      • 8.对loss滑动平均的理解
      • 9.补充知识点
    • 三、架构
      • 1.熟悉vgg神经网络框架
      • 2.熟悉googlenet的inception结构
      • 3.熟悉resnet的residual结构
      • 4.熟悉densenet的跳接结构
      • 5.熟悉senet的结构
    • 四、其他
      • 1.熟悉样本不均衡的解决方法
      • 2.熟悉过拟合和欠拟合的解决方法
      • 3.熟悉常用正则化方法
      • 4.熟悉常用的几个优化器
      • 5.熟悉分类模型常用的几个评价指标,二分类和多分类
      • 6.对熵、条件熵、相对熵、交叉熵的理解
    • 五、实战
      • 1.完成一个图像分类任务的全流程,包含图像的前处理、训练、预测、后处理等

一、关于TensorFlow

1.熟悉TensorFlow的基本概念,graph、session、tensor等

  • 使用图 (graph) 来表示计算任务.
  • 在被称之为 会话 (Session) 的上下文 (context) 中执行图.
  • 使用 tensor 表示数据.
  • 通过 变量 (Variable) 维护状态.
  • 使用 feed 和 fetch 可以为任意的操作(arbitrary operation) 赋值或者从其中获取数据.

2.熟悉tensorflow调用gpu的方法,多GPU使用方法

3.熟悉tensorflow的数据集tfrecord的构建及使用方法

4.熟悉tensorflow的两种输入构建方法placeholder和dataset

5.熟悉tensorflow的两种保存模型的方法ckpt和pb

二、概念


1.深度学习的一些基本概念,学习率、batch、epoch、optimizer、评价函数(损失函数)等


1.1 学习率(Learning Rate)

学习率:是控制模型学习效率(步长)的权重。

学习率的大小区分

区别 学习率大 学习率小
学习速度
应用场合 训练初期 数次Epoch过后
缺点 1.容易损失过大 2.容易发生振荡 1.容易过拟合 2.收敛速度慢

学习率的设置

在训练过程中,一般根据训练轮数设置动态变化的学习率:
1.刚开始训练时:学习率以 0.01 ~ 0.001 为宜。
2.一定轮数过后:逐渐减缓。
3.接近训练结束:学习速率的衰减应该在100倍以上。

loss-Epoch图像

深度学习杂谈_第1张图片

理想情况下曲线应该是滑梯式下降,如图中的[绿线]:

  1. 曲线 初始时 上扬 [红线]: Solution:初始 学习率过大 导致 振荡,应减小学习率,并 从头 开始训练 。
  2. 曲线 初始时 强势下降 没多久 归于水平 [紫线]: Solution:后期 学习率过大 导致 无法拟合,应减小学习率,并 重新训练后面几轮
  3. 曲线 全程缓慢 [黄线]: Solution:初始 学习率过小 导致 收敛慢,应 增大学习率,并从头开始训练。

1.2 Batch(批次)

批量,即Batch,是深度学习中的一个重要概念。
批量通常指两个不同的概念——如果对应的是模型训练方法,那么批量指的是将所有数据处理完以后一次性更新权重或者参数的估计;如果对应的是模型训练中的数据,那么批量通常指的是一次输入供模型计算用的数据量。

基于批量概念的模型训练通常按照如下步骤进行:
处理所有数据
更新参数
初始化参数
得到新的权重
批量算法相对应的是递增算法,其步骤如下:
处理一个或者一组数据点
更新参数
初始化参数
得到新的权重

对比:

这里的主要区别是批量算法一次处理所有的数据;而在递增算法中,每处理一个或者数个观测值就要更新一次参数。
在后向传播算法中,“处理”对应的具体操作就是计算损失函数的梯度变化曲线。如果是批量算法,则计算平均或者总的损失函数的梯度变化曲线;而如果是递增算法,则计算损失函数仅在对应于该观测值或者数个观测值时的梯度变化曲线
“更新”则是从已有的参数值中减去梯度变化率和学习速率的乘积。

为什么要用batch?

batch可以大致理解为计算损失函数时需要用到的样本个数,以上两种不同的概念,仅是在样本个数差异上的不同体现。

1.遍历全部数据集算一次损失函数,然后算函数对各个参数的梯度,更新梯度。这称为Batch gradient descent,批梯度下降。这种方法缺点很明显,计算量大,吃内存,不适用于在线学习。

2.每输入一个数据就计算一次损失函数,进而求梯度并更新参数,称为随机梯度下降,stochastic gradient descent,这种方法速度较快,但由于迭代一次仅依靠单一样本,很容易在相邻的两次迭代计算中的产生梯度差距非常大,甚至方向相反,因此容易不收敛。

3.另一种就是将上述两种方法的折中,称为mini-batch gradient decent,将数据集分成一定数量的批,梯度不容易跑偏容易收敛,同时减少了一次处理的数据数量,因而计算量也小了很多,速度较快。

批量梯度下降法(BGD, Batch Gradient Descent)
随机梯度下降法(SGD, Stochastic Gradient Descent)
小批量梯度下降法(Mini-batch Gradient Descent)

深度学习杂谈_第2张图片
如上图所示,总结:

优点 缺点
1.相对于海量数据的大内存,Mini-batch只需要小内存 1.批次越小,梯度的估值不准确
2.速度更快 2.批次越小,越不容易收敛
3. 选取局部的梯度方向,较之全局的学习率简单 3.所有参数都是用同样的learning rate

当数据集较大时,并不是适合一次将所有样本批量输入进行训练,而应该使用一个合适的数量来训练,这个合适的数量又该如何选择?

batch_size如何选择?

在合理范围内增大batch_size:
1.能提高内存使用率。
2.减少Epoch迭代次数,提高训练速度。
3.一定范围内batch_size越大,确定的梯度下降方向越准确。

盲目增大batch_size:
1.内存不足。
2.Epoch迭代次数过少,要想达到相同的精度,时间花费增加,调参整体进度下降。
3.batch_size大到一定程度,梯度方向基本不改变。

总结:在硬件配置允许下,从小(也不能过小)增大batch_size,直至一个比较合适的数量,有人指出,将batch_size设置成2的次方倍能加快速度(未经考证)。


1.3 Epoch(轮次)

Epoch:使用训练集的全部数据对模型进行一次完整训练,也称为“一代训练”
Batch:使用数据集中的一小部分样本对模型权重进行一次方向传播的参数更新,这一小部分样本也称为“一批数据”;
Iteration:使用一个Batch数据对模型进行一次参数更新的过程,称之为“一次训练”;


1.4 Optimizer(优化器)

1.4.1 梯度下降法(Gradient Descent)

梯度下降法是最基本的一类优化器,目前主要分为三种梯度下降法:标准梯度下降法(GD, Gradient Descent)随机梯度下降法(SGD, Stochastic Gradient Descent)批量梯度下降法(BGD, Batch Gradient Descent)


1.4.1.1 标准梯度下降法(GD, Gradient Descent)
  • 假设要学习训练的模型参数为W,代价函数为J(W),则代价函数关于模型参数的偏导数即相关梯度为ΔJ(W),学习率为ηt,则使用梯度下降法更新参数为:
    W t + 1 = W t − η t Δ J ( W t ) Wt+1=Wt−ηtΔJ(Wt) Wt+1=WtηtΔJ(Wt)
    其中,Wt表示t时刻的模型参数。

  • 从表达式来看,模型参数的更新调整,与代价函数关于模型参数的梯度有关,即沿着梯度的方向不断减小模型参数,从而最小化代价函数。

  • 基本策略可以理解为”在当前视野寻找最快路径下山“,因此每走一步,参考当前位置最陡的方向(即梯度)进而迈出下一步。可以形象的表示为:

深度学习杂谈_第3张图片
标准梯度下降法主要有两个缺点:

  • 训练速度慢:每走一步都要要计算调整下一步的方向,下山的速度变慢。在应用于大型数据集中,每输入一个样本都要更新一次参数,且每次迭代都要遍历所有的样本。会使得训练过程及其缓慢,需要花费很长时间才能得到收敛解。
  • 容易陷入局部最优解:由于是在有限视距内寻找下山的反向。当陷入平坦的洼地,会误以为到达了山地的最低点,从而不会继续往下走。所谓的局部最优解就是鞍点,落入鞍点,梯度为0,使得模型参数不再继续更新。

1.4.1.2 批量梯度下降法(BGD)

深度学习杂谈_第4张图片


1.4.1.3 随机梯度下降法(SGD)

深度学习杂谈_第5张图片


1.4.1.4 小批量梯度下降法(Mini-batch Gradient Descent)

深度学习杂谈_第6张图片


1.4.2 动量优化法

动量优化方法引入物理学中的动量思想,加速梯度下降,一般有标准动量优化方法MomentumNAG(Nesterov accelerated gradient)动量优化方法;当我们将一个小球从山上滚下来,没有阻力时,它的动量会越来越大,但是如果遇到了阻力,速度就会变小,动量优化法就是借鉴此思想,使得梯度方向在不变的维度上,参数更新变快,梯度有所改变时,更新参数变慢,这样就能够加快收敛并且减少动荡。


1.4.2.1 Momentum

深度学习杂谈_第7张图片


1.4.2.2 NAG(Nesterov accelerated gradient)

深度学习杂谈_第8张图片
深度学习杂谈_第9张图片
NAG


1.4.3 自适应学习率优化算法

自适应学习率优化算法针对于机器学习模型的学习率,传统的优化算法要么将学习率设置为常数要么根据训练次数调节学习率。极大忽视了学习率其他变化的可能性。然而,学习率对模型的性能有着显著的影响,因此需要采取一些策略来想办法更新学习率,从而提高训练速度。
目前的自适应学习率优化算法主要有:AdaGrad算法RMSProp算法Adam算法以及AdaDelta算法


1.4.3.1 AdaGrad

思想:

  • adaGrad算法,独立地适应所有模型参数的学习率,缩放每个参数反比于其所有梯度历史平均值总和的平方根;具有代价函数最大梯度的参数相应地有个快速下降的学习率,而具有小梯度的参数在学习率上有相对较小的下降。

算法描述:

  • AdaGrad算法优化策略一般可以表示为:
    深度学习杂谈_第10张图片
  • 从表达式可以看出,对出现比较多的类别数据,Adagrad给予越来越小的学习率,而对于比较少的类别数据,会给予较大的学习率。因此Adagrad适用于数据稀疏或者分布不平衡的数据集。
  • Adagrad 的主要优势在于不需要人为的调节学习率,它可以自动调节;缺点在于,随着迭代次数增多,学习率会越来越小,最终会趋近于0。

缺点:

  • 仍需要手工设置一个全局学习率 δ \delta δ, 如果 δ \delta δ设置过大的话,会使regularizer过于敏感,中后期,分母上梯度累加的平方和也会越来越大,使得参数更新量趋近于0,使得训练提前结束,无法学习
  • Adagrad 的主要优势在于不需要人为的调节学习率,它可以自动调节;缺点在于,随着迭代次数增多,学习率会越来越小,最终会趋近于0。

1.4.3.2 AdaGrad

深度学习杂谈_第11张图片


1.4.3.3 RMSprop

深度学习杂谈_第12张图片


1.4.3.4 Adam: Adaptive Moment Estimation

深度学习杂谈_第13张图片


1.5 损失函数

1.5.1 Regression loss

1.5.1.1 Mean Square Error (MSE/ L2 Loss) ——均方误差

均方误差(MSE) 是最常用的回归损失函数,计算方法是求预测值与真实值之间距离的平方和,公式如下图所示:

公式:
M S E = ∑ i = 1 n ( y i − y i p ) 2 n MSE = \frac{\sum_{i=1}^n (y_i-y_i^p)^2}{n} MSE=ni=1n(yiyip)2

L 2 损 失 函 数 = M S E = ∑ i = 1 n ( y i − y i p ) 2 L_2损失函数=MSE = \sum_{i=1}^n (y_i-y_i^p)^2 L2=MSE=i=1n(yiyip)2

代码实现

#MSE function
def mse(true, pred):
    """
    true: array of true values
    pred: array of predicted values

    returns: mean square error loss
    """
    return np.sum((true - pred) ** 2)

fig, ax1 = plt.subplots(1,1, figsize = (7,5))

# array of same target value 10000 times
target = np.repeat(100, 10000) 
pred = np.arange(-10000,10000, 2)

loss_mse = [mse(target[i], pred[i]) for i in range(len(pred))]

# plot 
ax1.plot(pred, loss_mse)
ax1.set_xlabel('Predictions')
ax1.set_ylabel('Loss')
ax1.set_title("MSE Loss vs. Predictions")

# show
fig.tight_layout()
plt.show()

下图是MSE函数的图像,其中目标值是100,预测值的范围从-10000到10000,Y轴代表的MSE取值范围是从0到正无穷,并且在预测值为100处达到最小。

图像
深度学习杂谈_第14张图片

MSE损失(Y轴)-预测值(X轴)
优点 缺点
各点都连续光滑,方便求导,具有较为稳定的解 鲁棒性低,当函数的输入值距离中心值较远的时候,使用梯度下降法求解的时候梯度很大,可能导致梯度爆炸

备注
均方根误差,它是观测值与真值偏差的平方和观测次数n比值的平方根,在实际测量中,观测次数n总是有限的,真值只能用最可信赖(最佳)值来代替.均方误差对一组测量中的特大或特小误差反映非常敏感,所以,均方根误差能够很好地反映出测量的精密度。均方根误差,当对某一量进行甚多次的测量时,取这一测量列真误差的均方根差(真误差平方的算术平均值再开方),称为标准偏差,以σ表示。σ反映了测量数据偏离真实值的程度,σ越小,表示测量精度越高,因此可用σ作为评定这一测量过程精度的标准。

公式:

M S E = ∑ i = 1 n ( y i − y i p ) 2 MSE = \sqrt{\sum_{i=1}^n (y_i-y_i^p)^2} MSE=i=1n(yiyip)2

M S E = ∑ i = 1 n ( y i − y i p ) 2 n MSE = \sqrt\frac{\sum_{i=1}^n (y_i-y_i^p)^2}{n} MSE=ni=1n(yiyip)2


1.5.1.2 Mean Absolute Error (MAE/ L1 loss) ——平均绝对误差

平均绝对误差(MAE)是另一种用于回归模型的损失函数。MAE是目标值和预测值之差的绝对值之和,其只衡量了预测值误差的平均模长,而不考虑方向,取值范围也是从0到正无穷(如果考虑方向,则是残差/误差的总和——平均偏差(MBE))。

公式:
R M S E = ∑ i = 1 n ∣ y i − y i p ∣ n RMSE = \frac{ \sum_{i=1}^n |y_i-y_i^p|}{n} RMSE=ni=1nyiyip

R M S E = ∑ i = 1 n ∣ y i − y i p ∣ RMSE = \sum_{i=1}^n |y_i-y_i^p| RMSE=i=1nyiyip

代码实现

#MAE function
def mae(true, pred):
    """
    true: array of true values    
    pred: array of predicted values
    
    returns: mean absolute error loss
    """
    return np.sum(np.abs(true - pred))

fig, ax1 = plt.subplots(1,1, figsize = (7,5))

# array of same target value 10000 times
target = np.repeat(100, 10000) 
pred = np.arange(-10000,10000, 2)

loss_mae = [mae(target[i], pred[i]) for i in range(len(pred))]

# plot 
ax1.plot(pred, loss_mae)
ax1.set_xlabel('Predictions')
ax1.set_ylabel('Loss')
ax1.set_title("MAE Loss vs. Predictions")

# show
fig.tight_layout()
plt.show()

图像
深度学习杂谈_第15张图片

MAE损失(Y轴)-预测值(X轴)
优点 缺点
无论对于什么样的输入值,都有着稳定的梯度,不会导致梯度爆炸问题,具有较为稳健性的解 中心点是折点,不能求导,不方便求解

1.5.1.3 MSE(L2 Loss)VS2 MAE(L1 Loss)
类别 L1损失函数 L2损失函数
鲁棒性
稳定性 不稳定解 稳定解
鞍点 可能多个解 总是一个解

解释:

鲁棒性:与均方误差相比,平均绝对误差方法的鲁棒性更好,因此,它在许多场合都有应用。平均绝对误差方法之所以是鲁棒的,是因为它能处理数据中的异常值,这或许在那些异常值可能被安全地和有效地忽略的研究中很有用,如果需要考虑任一或全部的异常值,那么平均绝对误差方法是更好的选择。
从直观上说,因为L2范数将误差平方化(如果误差大于1,则误差会放大很多),模型的误差会比L1范数来得大(e.equal(e^2)),因此模型会对这个样本(异常值)更加敏感,这就需要调整模型来最小化误差,如果这个样本是一个异常值,模型就需要调整以适应单个的异常值,这会牺牲许多其它正常的样本,因为这些正常样本的误差比这单个的异常值的误差小。

稳定性平均绝对误差方法的不稳定性意味着,对于数据集的一个小的水平方向的波动,回归线也许会跳跃很大。在一些数据结构(data configurations)上,该方法有许多连续解;但是,对数据集的一个微小移动,就会跳过某个数据结构在一定区域内的许多连续解。(The method has continuous solutions for some data configurations; however, by moving a datum a small amount, one could “jump past” a configuration which has multiple solutions that span a region. )在跳过这个区域内的解后,平均绝对误差偏差线可能会比之前的线有更大的倾斜。相反地,均方误差方法的解是稳定的,因为对于一个数据点的任何微小波动,回归线总是只会发生轻微移动;也就说,回归参数是数据集的连续函数。

总而言之,处理异常点时,L1损失函数更稳定,但它的导数不连续,因此求解效率较低。L2损失函数对异常点更敏感,但通过令其导数为0,可以得到更稳定的封闭解。


1.5.1.4 Smooth Mean Absolute Error/ Huber Loss——平滑的平均绝对误差

Huber损失对数据中的异常点没有平方误差损失那么敏感,它在0也可微分。本质上,Huber损失是绝对误差,只是在误差很小时,就变为平方误差,误差降到多小时变为二次误差由超参数δ(delta)来控制。当Huber损失在[0-δ,0+δ]之间时,等价为MSE,而在[-∞,δ]和[δ,+∞]时为MAE。

公式:
L δ ( y , f ( x ) ) = { 1 2 ( y − f ( x ) ) 2 , f o r ∣ y − f ( x ) ∣ ≤ δ δ ∣ y − f ( x ) ∣ − 1 2 δ 2 , o t h e r w i s e . L_\delta(y,f(x))= \begin{cases} \frac{1}{2}(y-f(x))^2,for|y-f(x)|\leq\delta \\ \delta|y-f(x)|-\frac{1}{2}\delta^2,otherwise. \end{cases} Lδ(y,f(x))={21(yf(x))2foryf(x)δδyf(x)21δ2otherwise.
代码实现

#Hubei损失函数
def sm_mae(true, pred, delta):
    """
    true: array of true values
    pred: array of predicted values
    returns: smoothed mean absolute error loss
    """
    loss = np.where(np.abs(true - pred) < delta, 0.5 * ((true - pred) ** 2),
                    delta * np.abs(true - pred) - 0.5 * (delta ** 2))
    return np.sum(loss)

fig, ax1 = plt.subplots(1,1, figsize = (7,5))
target = np.repeat(0, 1000)
pred = np.arange(-10,10, 0.02)
delta = [0.1, 1, 10]
losses_huber = [[sm_mae(target[i], pred[i], q) for i in range(len(pred))] for q in delta]

# plot
for i in range(len(delta)):
    ax1.plot(pred, losses_huber[i], label = delta[i])
ax1.set_xlabel('Predictions')
ax1.set_ylabel('Loss')
ax1.set_title("Huber Loss/ Smooth MAE Loss vs. Predicted values (Color: Deltas)")
ax1.legend()
ax1.set_ylim(bottom=-1, top = 15)

# show
fig.tight_layout()
plt.show()

图像
深度学习杂谈_第16张图片

Huber损失(Y轴)与预测值(X轴)

备注:
这里超参数delta的选择非常重要,因为这决定了你对与异常点的定义。当残差大于delta,应当采用L1(对较大的异常值不那么敏感)来最小化,而残差小于超参数,则用L2来最小化。

Huber损失的评价:

使用MAE训练神经网络最大的一个问题就是不变的大梯度,这可能导致在使用梯度下降快要结束时,错过了最小点。而对于MSE,梯度会随着损失的减小而减小,使结果更加精确

优点 缺点
会由于梯度的减小而落在最小值附近,比起 M S E MSE MSE,它对异常点更加鲁棒 需要不断调整超参数 δ \delta δ(选择合适的 δ \delta δ

总结:
从上面可以看出,Huber函数实际上就是一个分段函数,在 [ ≤ δ ] [\leq\delta] [δ]之间实际上就是L2损失,这样解决了L1的不光滑问题,在区间外,实际上就是L1损失,这样就解决了离群点梯度爆炸的问题。


1.5.1.5 Log cosh loss ——Log-Cosh损失

Log-Cosh损失(对数双曲余弦),是一种比L2更为平滑的损失函数,利用双曲余弦来计算预测误差。

公式:

L ( y , y p ) = ∑ i = 1 n log ⁡ ( c o s h ( y i p − y i ) ) L(y,y^p)=\sum_{i=1}^n\log(cosh(y_i^p-y_i)) L(yyp)=i=1nlog(cosh(yipyi))

代码实现

#logcosh损失
def logcosh(true, pred):
    loss = np.log(np.cosh(pred - true))
    return np.sum(loss)

fig, ax1 = plt.subplots(1,1, figsize = (7,5))

target = np.repeat(0, 1000)
pred = np.arange(-10,10, 0.02)

loss_logcosh = [logcosh(target[i], pred[i]) for i in range(len(pred))]

# plot
ax1.plot(pred, loss_logcosh)
ax1.set_xlabel('Predictions')
ax1.set_ylabel('Loss')
ax1.set_title("Log-Cosh Loss vs. Predictions")

# show
fig.tight_layout()
plt.show()

图像
深度学习杂谈_第17张图片

Log-cosh损失(Y轴)与预测值(X轴)

Log-cosh损失的评价

优点 缺点
对于较小的 x x x log ⁡ ( c o s h ( y i p − y i ) ) \log(cosh(y_i^p-y_i)) log(cosh(yipyi))近似等于 x 2 2 \frac{x^2}{2} 2x2,对于较大的 x x x,近似等于 a b s ( x ) − log ⁡ ( 2 ) abs(x)-\log(2) abs(x)log(2)。这意味着Log-cosh基本类似于均方误差,但不易受到异常点的影响,它具有Huber损失所有的优点,但不同于Huber损失的是,Log-cosh二阶处处可微。 误差很大的时,一阶梯度和Hessian会变成定值

1.5.1.6 Quantile loss——分位数损失

在大多数现实世界预测问题中,我们通常希望了解预测中的不确定性,即清楚预测的范围区间而非仅是估计的点,对许多商业问题的决策很有帮助。
分位数损失函数在我们关注区间预测时,能派上很大用场。大致是,使用最小二乘回归进行区间预测,基于的假设是残差 ( y − y ^ ) (y-\hat y) yy^是独立变量,且方差保持不变。
一旦违背了这条假设,那么线性回归模型就不成立,但是我们也不能因此就认为使用非线性函数或基于树的模型更好,而放弃将线性回归模型作为基线方法。这时,分位数损失和分位数回归就派上用场了,因为即便对于具有变化方差或非正态分布的残差,基于分位数损失的回归也能给出合理的预测区间。

公式:
L γ ( y , y p ) = ∑ i : y i < y i p ( 1 − γ ) ∣ y i − y i p ∣ + ∑ i : y i ≥ y i p γ ∣ y i − y i p ∣ L_\gamma(y,y^p)=\sum_{i:y_iLγ(yyp)=i:yi<yip(1γ)yiyip+i:yiyipγyiyip

代码实现

y = np.arange(1,25, 0.25)
# linear relationship with contant variance of residual
x1 = y.copy() + np.random.randn(96)
# non contant variance with residuals
x2 = y.copy()
y2 = x2 + np.concatenate((np.random.randn(20)*0.5,
                                np.random.randn(20)*1,
                                np.random.randn(20)*4,
                               np.random.randn(20)*6,
                               np.random.randn(16)*8), axis=0)

fig, (ax1,ax2) = plt.subplots(1,2 , figsize = (12,5.5) )

#具有恒定的残差方差
ax1.plot(x1, y, 'o')
ax1.set_xlabel('X1')
ax1.set_ylabel('Y')
ax1.set_title('Contant variance of residuals')

#异方差
ax2.plot(x2, y2, 'o')
ax2.set_xlabel('X2')
ax2.set_ylabel('Y')
ax2.set_title('Non contant variance of residuals')

# show
fig.tight_layout()
plt.show()

深度学习杂谈_第18张图片

#用最小二乘进行评估
lr = LinearRegression()
lr.fit(x1.reshape(-1,1),y.reshape(-1,1))
lr2 = LinearRegression()
lr2.fit(x2.reshape(-1,1),y.reshape(-1,1))

fig, (ax1,ax2) = plt.subplots(1,2 , figsize = (12,5.5) )

ax1.plot(x1, y, 'o')
ax1.set_xlabel('X1')
ax1.set_ylabel('Y')
ax1.set_title('Contant variance of residuals')
ax1.plot(x1, lr.predict(x1.reshape(-1,1)))

ax2.plot(x2, y2, 'o')
ax2.set_xlabel('X2')
ax2.set_ylabel('Y')
ax2.set_title('Non contant variance of residuals')
ax2.plot(x2, lr2.predict(x2.reshape(-1,1)))

fig.tight_layout()
plt.show()

深度学习杂谈_第19张图片
上图是两种不同的数据分布,其中左图是残差的方差为常数的情况,而右图则是残差的方差变化的情况。我们利用正常的最小二乘对上述两种情况进行了估计,其中橙色线为建模的结果,但是我们却无法得到取值的区间范围,这时候就需要分位数损失函数来提供。

data = pd.DataFrame(data={'X': x2, 'Y':y2})
mod = smf.quantreg('Y ~ X', data)
res = mod.fit(q=.5)
quantiles = np.array((0.05, 0.95))

def fit_model(q):
    res = mod.fit(q=q)
    return [q, res.params['Intercept'], res.params['X']] + \
           res.conf_int().loc['X'].tolist()

models = [fit_model(x) for x in quantiles]
models = pd.DataFrame(models, columns=['q', 'a', 'b', 'lb', 'ub'])
ols = smf.ols('Y ~ X', data).fit()
ols_ci = ols.conf_int().loc['X'].tolist()
ols = dict(a=ols.params['Intercept'],
           b=ols.params['X'],
           lb=ols_ci[0],
           ub=ols_ci[1])

xn = np.arange(data.X.min(), data.X.max(), 2)
get_y = lambda a, b: a + b * xn

fig, ax = plt.subplots(figsize=(8, 6))

for i in range(models.shape[0]):
    yn = get_y(models.a[i], models.b[i])
    ax.plot(xn, yn, linestyle='dotted', color='grey')

yn = get_y(ols['a'], ols['b'])

ax.plot(xn, yn, color='red', label='OLS')

ax.scatter(data.X, data.Y, alpha=.2)
legend = ax.legend()
ax.set_xlabel('X', fontsize=16)
ax.set_ylabel('Y', fontsize=16)
ax.set_title('Quantile regression with 0.05 and 0.95 quantiles')

fig.tight_layout()
plt.show()

深度学习杂谈_第20张图片
上图中上下两条虚线基于0.05和0.95的分位数损失得到的取值区间,从图中可以清晰地看到建模后预测值得取值范围。分位数回归的目标在于估计给定预测值的条件分位数。实际上分位数回归就是平均绝对误差的一种拓展(当分位数为第50个百分位时其值就是平均绝对误差)。


#Quantile损失
def quan(true, pred, theta):
    loss = np.where(true >= pred, theta*(np.abs(true-pred)), (1-theta)*(np.abs(true-pred)))
    return np.sum(loss)

fig, ax1 = plt.subplots(1,1, figsize = (7,5))

target = np.repeat(0, 1000) 
pred = np.arange(-10,10, 0.02)

quantiles = [0.25, 0.5, 0.75]

losses_quan = [[quan(target[i], pred[i], q) for i in range(len(pred))] for q in quantiles]

# plot 
for i in range(len(quantiles)):
    ax1.plot(pred, losses_quan[i], label = quantiles[i])
ax1.set_xlabel('Predictions')
ax1.set_ylabel('Quantile Loss')
ax1.set_title("Loss with Predicted values (Color: Quantiles)")
ax1.legend()

# show
fig.tight_layout()
plt.show()

图像
深度学习杂谈_第21张图片

分位数损失(Y轴)与预测值(X轴)

1.5.2 Regression loss Comparison

通过函数曲线,来对比各个回归损失函数。

代码实现

fig, ax1 = plt.subplots(1,1, figsize = (10,6.5))

target = np.repeat(0, 1000) 
pred = np.arange(-10,10, 0.02)

# calculating loss function for all predictions. 
loss_mse = [mse(target[i], pred[i]) for i in range(len(pred))]
loss_mae = [mae(target[i], pred[i]) for i in range(len(pred))]
loss_sm_mae1 = [sm_mae(target[i], pred[i], 5) for i in range(len(pred))]
loss_sm_mae2 = [sm_mae(target[i], pred[i], 10) for i in range(len(pred))]
loss_logcosh = [logcosh(target[i], pred[i]) for i in range(len(pred))]
loss_quan1 = [quan(target[i], pred[i], 0.25) for i in range(len(pred))]

losses = [loss_mse, loss_mae, loss_sm_mae1, loss_sm_mae2, loss_logcosh, loss_quan1]
names = ['MSE', 'MAE','Huber (5)', 'Huber (10)', 'Log-cosh', 'Quantile (0.25)']
cmap = ['#d53e4f',
'#fc8d59',
'#fee08b',
'#e6f598',
'#99d594',
'#3288bd']

for lo in range(len(losses)):
    ax1.plot(pred, losses[lo], label = names[lo], color= cmap[lo])
ax1.set_xlabel('Predictions')
ax1.set_ylabel('Loss')
ax1.set_title("Loss with Predicted values")
ax1.legend()
ax1.set_ylim(bottom=0, top=40)

# fig.savefig('/Users/princegrover/Documents/msan/Machine-Learning/images/all_regression.png' )

图像
深度学习杂谈_第22张图片
结论

  • MAE损失模型的预测结果受脉冲噪声的影响较小,而MSE损失函数的预测结果受此影响略有偏移。
  • Huber损失模型预测结果对所选超参数不敏感。
  • 分位数损失模型在合适的置信水平下能给出很好的估计。

1.5.3 Classifications loss

1.5.3.1 Cross Entropy (交叉熵)

交叉熵(Cross Entropy)是Shannon信息论中一个重要概念,主要用于度量两个概率分布间的差异性信息

交叉熵可在神经网络(机器学习)中作为损失函数,p表示真实标记的分布,q则为训练后的模型的预测标记分布,交叉熵损失函数可以衡量p与q的相似性。交叉熵作为损失函数还有一个好处是使用sigmoid函数在梯度下降时能避免均方误差损失函数学习速率降低的问题,因为学习速率可以被输出的误差所控制。

在特征工程中,可以用来衡量两个随机变量之间的相似度。

在语言模型中(NLP)中,由于真实的分布p是未知的,在语言模型中,模型是通过训练集得到的,交叉熵就是衡量这个模型在测试集上的正确率。


给定两个概率分布p和q,通过q来表示p的交叉熵为:
H ( p , q ) = − ∑ x p ( x ) log ⁡ q ( x ) H(p,q) = -\sum_xp(x)\log q(x) H(pq)=xp(x)logq(x)

注意,交叉熵刻画的是两个概率分布之间的距离,或可以说它刻画的是通过概率分布q来表达概率分布p的困难程度,p代表正确答案,q代表的是预测值,交叉熵越小,两个概率的分布约接近。


假设原始的神经网络的输出为 y 1 , y 2 , y 3 . . . y n y_1,y_2,y_3...y_n y1,y2,y3...yn,那么经过Softmax回归处理之后的输出为:
S o f t m a x ( y i ) = e y i ∑ j = 1 n e y j Softmax(y_i)=\frac{e^{y_i}}{\sum_{j=1}^ne^{y_j}} Softmax(yi)=j=1neyjeyi

经常会用Softmax回归把神经网络的输出变成一个概率分布,进而通过交叉熵来计算预测的概率分布和真实答案的概率分布之间的距离


1.5.3.2 Binary cross entropy or negative log likelihood (二元交叉熵或负对数似然)

公式:
l o s s = − ∑ i = 1 n y ^ i log ⁡ y i + ( 1 − y ^ i ) log ⁡ ( 1 − y ^ i ) loss = -\sum_{i=1}^n{\hat y_i}{\log y_i}+(1-{\hat y_i}){\log {(1-{\hat y_i})} } loss=i=1ny^ilogyi+(1y^i)log(1y^i)

代码实现:

def bin_ce(true, pred):
    """
    true: array of true values
    pred: array of predicted values

    returns: binary cross entropy loss
    """
    loss = np.where(true == 1, np.log(pred), np.log(1 - pred))
    return -np.sum(loss)
    
fig, ax1 = plt.subplots(1,1)

# array of same target value 10000 times
target = np.repeat(1, 10000) # considering prediction to be 1
pred = np.arange(0,1, 0.0001) # all predictions b/w 0 and 1 for 10k values

# calculating loss function for all predictions.
loss_bin_ce = [bin_ce(target[i], pred[i]) for i in range(len(pred))]

# plot for binary cross entropy
ax1.plot(pred, loss_bin_ce)
ax1.set_xlabel('Predictions')
ax1.set_ylabel('Binary Cross Entropy Loss/ Log Loss')
ax1.set_title("Loss with Predicted values")

fig.tight_layout()
plt.show()

图像
深度学习杂谈_第23张图片
结论
Binary cross entropy是针对概率之间的损失函数, 只有在 y i y_i yi y ^ i \hat y_i y^i是相等时,loss才会为0,否则loss就为一个正数,而且,概率相差越大,loss就越大。


1.5.3.3 Focal loss (灶性损失)

1.5.3.4 Hinge loss (合页损失)

1.5.3.5 Square loss (平方损失)

1.5.3.6 Logistic loss (逻辑回归损失)

1.5.3.7 Exponential loss (指数损失)

1.5.3.8 Kullback–Leibler divergence (相对熵)

1.5.4 Classifications loss Comparison

1.5.5.1 Hinge embedding criteria

1.5.5.2 L1 Hinge embedding

1.5.5.3 Cosine distance

1.5.6 Miscelaneus losses

1.5.6.1 Haversine distance

1.5.6.2 Weighted average of muliple losses

2.理解卷积的具体运算流程,输入层通过卷积得到输出层的细节

卷积:在泛函分析中,卷积、旋积或摺积(英语:Convolution)是通过两个函数 f f f g g g生成第三个函数的一种数学算子,表征函数 f f f g g g经过翻转和平移的重叠部分的面积。

数学定义
设: f ( x ) f(x) f(x), g ( x ) g(x) g(x) R 1 R1 R1上的两个可积函数,作积分:
∫ − ∞ ∞ f ( τ ) g ( x − τ ) d τ {\displaystyle \int}_{-\infty}^{\infty}f(\tau)g(x-\tau)d\tau f(τ)g(xτ)dτ

直观过程

卷积核(kernel)重复这个过程知道遍历了整张图片,将一个二维矩阵转换为另一个二维矩阵。输出特征实质上是在输入数据相同位置上的加权和(权值是卷积核本身的值)


运算过程
上图,从5×5的输入层矩阵X,与kernel卷积核卷积运算,得到一个3×3的输出层矩阵Y。
其中以输出层第(0,0)个元素“12.0”为例,运算过程为:
Y ( 0 , 0 ) = X 0 , 0 × Y 0 , 0 + X 0 , 1 × Y 0 , 1 + X 0 , 2 × Y 0 , 2 + X 1 , 0 × Y 1 , 0 + X 1 , 1 × Y 1 , 1 + X 1 , 2 × Y 1 , 2 + X 2 , 0 × Y 2 , 0 + X 2 , 1 × Y 2 , 1 + X 2 , 2 × Y 2 , 2 = 3 × 1 + 2 × 2 + 1 × 1 + 2 × 2 = 12 \begin{aligned} Y_{(0,0)} & = X_{0,0}×Y_{0,0}+X_{0,1}×Y_{0,1}+X_{0,2}×Y_{0,2}\\ & +X_{1,0}×Y_{1,0}+X_{1,1}×Y_{1,1}+X_{1,2}×Y_{1,2} \\ & +X_{2,0}×Y_{2,0}+X_{2,1}×Y_{2,1}+X_{2,2}×Y_{2,2} \\ & = 3×1+2×2+1×1+2×2 =12\\ \end{aligned} Y(0,0)=X0,0×Y0,0+X0,1×Y0,1+X0,2×Y0,2+X1,0×Y1,0+X1,1×Y1,1+X1,2×Y1,2+X2,0×Y2,0+X2,1×Y2,1+X2,2×Y2,2=3×1+2×2+1×1+2×2=12
卷积的应用
用Kernel与图像输入进行卷积,对于图像上的每一个像素点,Kernel与之一一对应,然后把Kernel上的点和图像上对应的点相乘,再把各点的乘积相加,进而得到该点的卷积值。
卷积是一种积分运算,用来求两个曲线重叠区域面积。可以看作加权求和,可以用来消除噪声、特征增强、图像滤波。


3.卷积过程中,Padding,Stride是什么?选择valid和same的区别以及输出层的尺寸变化

在卷积过程中,有这么一个的问题:卷积后所得的结果矩阵,尺寸会缩小。
如上图所示,从5×5的输入层矩阵X,与kernel卷积核卷积运算,得到一个3×3的输出层矩阵Y,输出尺寸较之输入减少。
而在实际应用中,我们并不想丢失任何有价值的数据,这时,Padding操作,能给我们一些帮助。

Padding:用额外的「假」像素(通常值为 0,因此经常使用的术语「零填充」)填充边缘。这样,在滑动时的卷积核可以允许原始边缘像素位于其中心,同时延伸到边缘之外的假像素,从而产生与输入相同大小的输出。

当然,当我们需要,将输入层尺寸,缩小为我们希望的尺寸时,我们也可以应用设置参数Striding(步长),来实现。

Stride:是改变卷积核的移动步长跳过一些像素。Stride 是 1 表示卷积核滑过每一个相距是 1 的像素,是最基本的单步滑动,作为标准卷积模式。Stride 是 2 表示卷积核的移动步长是 2,跳过相邻像素,图像缩小为原来的 1/2。Stride 是 3 表示卷积核的移动步长是 3,跳过 2 个相邻像素,图像缩小为原来的 1/3。

在应用到一张RGB格式的图像输入,卷积操作,通常会每个通道独立进行,再将结果重叠。

深度学习杂谈_第24张图片

滤波器的每个卷积核在各自的输入通道上「滑动」,产生各自的计算结果。一些内核可能比其他内核具有更大的权重,以便比某些内核更强调某些输入通道(例如,滤波器的红色通道卷积核可能比其他通道的卷积核有更大的权重,因此,对红色通道特征的反应要强于其他通道)。

然后将每个通道处理的结果汇在一起形成一个通道。滤波器的卷积核各自产生一个对应通道的输出,最后整个滤波器产生一个总的输出通道。



也可以通过对每个输出滤波器增加偏置项来实现耦合。

在TensorFlow中,对于输出层尺寸大小的设置,可以通过两个参数Valid和Same来实现。

Padding = ‘VALID’ 时,没有填充,因此输出的size总比原图的size小。
如图,3×3的kernel作用在7×7的图像上,当步长stride为1时:

深度学习杂谈_第25张图片

由于没有填充,最终得到的就是虚线中的灰色区域即5×5大小。

Padding = ‘SAME’ 时,用0填充边界.能覆盖原图所有像素,不会舍弃边上的元素;当步长stride为1时,输出和原图size一致。
如图,3×3的kernel作用在7×7的图像上,当步长stride为1时:

深度学习杂谈_第26张图片
由于有0填充边界,最终得到的就是虚线中的灰色区域即7×7大小。
5×5的kernel作用在7×7的图像上,步长stride为1时:
深度学习杂谈_第27张图片
计算公式


4.对池化、上采样、空洞卷积、反卷积的理解

什么是池化?
答:也称下采样层,会压缩输入的特征图,一方面减少了特征,参数减少,简化计算 复杂度;另一方面在某种意义上(旋转、平移、伸缩等)保持不变性。
有几种池化操作?
1.平均池化(区域内求平均值)2.最大池化(区域内取最大值)
具体的作用?
1.特征不变形:池化操作是模型更加关注是否存在某些特征而不是特征具体的位置。
2.特征降维:池化相当于在空间范围内做了维度约减,从而使模型可以抽取更加广范围的特征。同时减小了下一层的输入大小,进而减少计算量和参数个数。
3.在一定程度上防止过拟合,更方便优化。
4.扩大感受野。


注意项:
下采样和池化应该是包含关系,池化属于下采样,而下采样不局限于池化,如果卷积 stride=2,此时也可以把这种卷积叫做下采样。


什么是上采样?
答:池化(下采样层)更像是获取缩略图,反之,上采样更像是放大图像。
有哪些常用方法?
1.双线性插值
2.转置卷积(反卷积)
3.反池化(unpooling)


什么是空洞卷积?


什么是反卷积?
答:反卷积是一种特殊的正向卷积,先按照一定的比例通过补0来扩大输入图像的尺寸,接着旋转卷积核,再进行正向卷积。


5.推导BP算法的全流程

6.理解梯度消失和梯度爆炸的原因和解决方法


一.为什么会出现梯度消失或梯度爆炸?

梯度消失和梯度爆炸本质上是一样的,都是因为网络层数太深而引发的梯度反向传播中的连乘效应。

二.解决方法有哪些?

  1. 改变激活函数(Relu、LeakyRelu、Elu等)
  2. BatchNormalization
  3. ResNet残差结构
  4. LSTM结构
  5. 预训练加finetunning
  6. (针对梯度爆炸)梯度剪切、正则

7.对Batch Normalization、Group Normalization、Spectral Normalization、Layer normalization、 Instance Normalization的理解和如何使用


一.什么是Batch Normalization?

对于每个隐层神经元,把逐渐向非线性函数映射后向取值区间极限饱和区靠拢的输入分布强制拉回到均值为0方差为1的比较标准的正态分布,使得非线性变换函数的输入值落入对输入比较敏感的区域,以此避免梯度消失问题。

附上一个讲解得较为清晰的博客链接

二.如何使用BN?

深度学习杂谈_第28张图片

三.为什么用Group Normalization?什么是Group Normalization?

BN存在的问题:BN全名是Batch Normalization,是以batch的维度做归一化,过小的batch size会导致其性能下降,一般来说每GPU上batch设为32最合适;但是对于一些其他深度学习任务batch size往往只有1-2,比如目标检测,图像分割,视频分类上,输入的图像数据很大,较大的batch size性能下降,误差增大。

Group Normalization(GN)是一种新的深度学习归一化方式,可以替代BN。

四.什么是LN、IN?

深度学习杂谈_第29张图片
深度网络中的数据维度一般是[N, C, H, W]或者[N, H, W,C]格式,N是batch size,H/W是feature的高/宽,C是feature的channel,压缩H/W至一个维度,其三维的表示如上图,假设单个方格的长度是1,那么其表示的是[6, 6,*, * ]

  1. BN在batch的维度上norm,归一化维度为[N,H,W],对batch中对应的channel归一化;
  2. LN避开了batch维度,归一化的维度为[C,H,W];
  3. IN 归一化的维度为[H,W];
  4. 而GN介于LN和IN之间,其首先将channel分为许多组(group),对每一组做归一化,及先将feature的维度由[N, C, H, W]reshape为[N, G,C//G , H, W],归一化的维度为[C//G , H, W];

注:事实上,GN的极端情况就是LN和IN,分别对应G等于C和G等于1,作者在论文中给出G设为32较好。

补充知识点:

什么是LRN?

LRN全称为Local Response Normalization,即局部响应归一化层,LRN函数类似DROPOUT和数据增强作为relu激励之后防止数据过拟合而提出的一种处理方法。这个函数很少使用,基本上被类似DROPOUT这样的方法取代,见最早的出处AlexNet论文对它的定义, 《ImageNet Classification with Deep ConvolutionalNeural Networks》

8.对loss滑动平均的理解

什么是滑动平均?

滑动平均(exponential moving average),或者叫做指数加权平均(exponentially weighted moving average),可以用来估计变量的局部均值,使得变量的更新与一段时间内的历史取值有关。

为什么使用滑动平均?

  1. 相对于计算全局的loss平均值占用内存与计算成本较低。
  2. 一定程度上提高模型权重鲁棒性。

References:理解滑动平均

9.补充知识点

1.什么是"感受野"?

2.全连接层的定义是什么?

3.为什么输入数据需要归一化(Normalized Data)?

归一化后有什么好处呢?原因在于神经网络学习过程本质就是为了学习数据分布,一旦训练数据与测试数据的分布不同,那么网络的泛化能力也大大降低;另外一方面,一旦每批训练数据的分布各不相同(batch 梯度下降),那么网络就要在每次迭代都去学习适应不同的分布,这样将会大大降低网络的训练速度,这也正是为什么我们需要对数据都要做一个归一化预处理的原因。

对于深度网络的训练是一个复杂的过程,只要网络的前面几层发生微小的改变,那么后面几层就会被累积放大下去。一旦网络某一层的输入数据的分布发生改变,那么这一层网络就需要去适应学习这个新的数据分布,所以如果训练过程中,训练数据的分布一直在发生变化,那么将会影响网络的训练速度。

4.什么是GAP?

GAP,全称Global Average Pooling,概念出自于 Network In Network,主要是用来解决全连接的问题,其主要是是将最后一层的特征图进行整张图的一个均值池化,形成一个特征点,将这些特征点组成最后的特征向量进行softmax中进行计算。


三、架构

1.熟悉vgg神经网络框架

详细架构配置:
深度学习杂谈_第30张图片
深度学习杂谈_第31张图片

参考:VGG详解


2.熟悉googlenet的inception结构

为什么用Inception Module?什么是Inception Module?

GoogLeNet是2014年的分类比赛冠军,网络达到了22层,参数量为5M,核心就是Inception模块,这次的版本通常称其为Inception V1。

问题:

  1. 由于信息位置的巨大差异,为卷积操作选择合适的卷积核大小就比较困难。信息分布更全局性的图像偏好较大的卷积核,信息分布比较局部的图像偏好较小的卷积核。
  2. 非常深的网络更容易过拟合。将梯度更新传输到整个网络是很困难的。
  3. 简单地堆叠较大的卷积层非常消耗计算资源。

Inception Module的架构图如下所示:
深度学习杂谈_第32张图片
Inception Module基本组成结构有四个成分。1X1卷积,3X3卷积,5X5卷积,3X3最大池化。最后对四个成分运算结果进行通道上组合,这就是Inception Module的核心思想。通过多个卷积核提取图像不同尺度的信息,最后进行融合,可以得到图像更好的表征。

深度学习杂谈_第33张图片
在Inception结构中,大量采用了1x1的矩阵,主要是两点作用:1)对数据进行降维;2)引入更多的非线性,提高泛化能力,因为卷积后要经过ReLU激活函数。

GoogLeNet 有9个线性堆叠的Inception模块。它有 22 层(包括池化层的话是 27 层)。该模型在最后一个 inception 模块处使用全局平均池化。

为了阻止该网络中间部分梯度的「消失」过程,作者引入了两个辅助分类器。它们对其中两个 Inception 模块的输出执行 softmax 操作,然后在同样的标签上计算辅助损失。总损失即辅助损失和真实损失的加权和。

References:一文概览Inception家族的「奋斗史」


1*1卷积核的作用有哪些?

  1. 降维
  2. 升维
  3. 跨通道信息交互(channal 的变换):使用1X1卷积核,实现降维和升维的操作其实就是channel间信息的线性组合变化,3X3X64channels的卷积核后面添加一个1X1X28channels的卷积核,就变成了3X3X28channels的卷积核,原来的64个channels就可以理解为跨通道线性组合变成了28channels,这就是通道间的信息交互。
    注意:只是在channel维度上做线性组合,W和H上是共享权值的sliding window
  4. 增加非线性特性:1*1卷积核,可以在保持feature map尺度不变的(即不损失分辨率)的前提下大幅增加非线性特性(利用后接的非线性激活函数),把网络做的很deep。

Inception V2和Inception V3如何改进?

Inception V2解决的问题:

  1. 减少特征的表征性瓶颈。直观上来说,当卷积不会大幅度改变输入维度时,神经网络可能会执行地更好。过多地减少维度可能会造成信息的损失,这也称为「表征性瓶颈」。
  2. 使用更优秀的因子分解方法,卷积才能在计算复杂度上更加高效。

解决方案:

  • 将 5×5 的卷积分解为两个 3×3 的卷积运算以提升计算速度。尽管这有点违反直觉,但一个 5×5 的卷积在计算成本上是一个 3×3 卷积的 2.78 倍。所以叠加两个 3×3 卷积实际上在性能上会有所提升,如下图所示:
    深度学习杂谈_第34张图片
  • 此外,作者将 n*n 的卷积核尺寸分解为 1×n 和 n×1 两个卷积。例如,一个 3×3 的卷积等价于首先执行一个 1×3 的卷积再执行一个 3×1 的卷积。他们还发现这种方法在成本上要比单个 3×3 的卷积降低 33%,这一结构如下图所示:
    深度学习杂谈_第35张图片
  • 模块中的滤波器组被扩展(即变得更宽而不是更深),以解决表征性瓶颈。如果该模块没有被拓展宽度,而是变得更深,那么维度会过多减少,造成信息损失。如下图所示:
    深度学习杂谈_第36张图片

Inception V3解决的问题:

  • 作者注意到辅助分类器直到训练过程快结束时才有较多贡献,那时准确率接近饱和。作者认为辅助分类器的功能是正则化,尤其是它们具备 BatchNorm 或 Dropout 操作时。
  • 是否能够改进 Inception v2 而无需大幅更改模块仍需要调查。

解决方案:
Inception Net v3 整合了前面 Inception v2 中提到的所有升级,还使用了:

  • RMSProp 优化器;
  • Factorized 7x7 卷积;
  • 辅助分类器使用了 BatchNorm;
  • 标签平滑(添加到损失公式的一种正则化项,旨在阻止网络对某一类别过分自信,即阻止过拟合)。

References:一文概览Inception家族的「奋斗史」


3.熟悉resnet的residual结构

什么是残差?

  • "残差在数理统计中是指实际观察值与估计值(拟合值)之间的差。"
  • "如果回归模型正确的话, 我们可以将残差看作误差的观测值。"

更准确地,假设我们想要找一个 ,使得 ()=,给定一个 的估计值 0,残差(residual)就是 −(0),同时,误差就是 −0。

即使 不知道,我们仍然可以计算残差,只是不能计算误差。

为什么需要残差网络(residual结构)?

  • 梯度消失问题:很深的网络层,由于参数初始化一般更靠近0,这样在训练的过程中更新浅层网络的参数时,很容易随着网络的深入而导致梯度消失,浅层的参数无法更新。
  • 网络退化问题(Degradation Problem):假设已经有了一个最优化的网络结构,是18层。当我们设计网络结构的时候,我们并不知道具体多少层次的网络时最优化的网络结构,假设设计了34层网络结构。那么多出来的16层其实是冗余的,我们希望训练网络的过程中,模型能够自己训练这五层为恒等映射,也就是经过这层时的输入与输出完全一样。但是往往模型很难将这16层恒等映射的参数学习正确,那么就一定会不比最优化的18层网络结构性能好,这就是随着网络深度增加,模型会产生退化现象。它不是由过拟合产生的,而是由冗余的网络层学习了不是恒等映射的参数造成的。

什么是残差网络(Residual Networks,ResNets)?

  • ResNet使用了一个新的思想,ResNet的思想是假设我们涉及一个网络层,存在最优化的网络层次,那么往往我们设计的深层次网络是有很多网络层为冗余层的。那么我们希望这些冗余层能够完成恒等映射,保证经过该恒等层的输入和输出完全相同。具体哪些层是恒等层,这个会有网络训练的时候自己判断出来。
    深度学习杂谈_第37张图片
    可以看到x是这一层残差块的输入,也称作F(x)为残差,x为输入值,F(x)是经过第一层线性变化并激活后的输出,该图表示在残差网络中,第二层进行线性变化之后激活之前,F(x)加入了这一层输入值x,然后再进行激活后输出。在第二层输出值激活前加入x,这条路径称作Shortcut Connections。

References:残差网络(Residual Network)


4.熟悉densenet的跳接结构

为什么有DenseNet?

  • DenseNet模型,它的基本思路与ResNet一致,但是它建立的是前面所有层与后面层的密集连接(dense connection),它的名称也是由此而来。DenseNet的另一大特色是通过特征在channel上的连接来实现特征重用(feature reuse)。这些特点让DenseNet在参数和计算成本更少的情形下实现比ResNet更优的性能。

深度学习杂谈_第38张图片
DenseNet提出了一个更激进的密集连接机制:即互相连接所有的层,具体来说就是每个层都会接受其前面所有层作为其额外的输入。DenseNet中,每个层都会与前面所有层在channel维度上连接(concat)在一起(这里各个层的特征图大小是相同的,后面会有说明),并作为下一层的输入。对于一个L层的网络,DenseNet共包含L(L+1)/2个连接,相比ResNet,这是一种密集连接。而且DenseNet是直接concat来自不同层的特征图,这可以实现特征重用,提升效率,这一特点是DenseNet与ResNet最主要的区别。

DenseNet网络结构是怎样的?

CNN网络一般要经过Pooling或者stride>1的Conv来降低特征图的大小,而DenseNet的密集连接方式需要特征图大小保持一致。为了解决这个问题,DenseNet网络中使用DenseBlock+Transition的结构,其中DenseBlock是包含很多层的模块,每个层的特征图大小相同,层与层之间采用密集连接方式。而Transition模块是连接两个相邻的DenseBlock,并且通过Pooling使特征图大小降低。下图给出了DenseNet的网路结构,它共包含4个DenseBlock,各个DenseBlock之间通过Transition连接在一起。

深度学习杂谈_第39张图片

优势有哪些?
DenseNet的优势主要体现在以下几个方面:

  • 由于密集连接方式,DenseNet提升了梯度的反向传播,使得网络更容易训练。由于每层可以直达最后的误差信号,实现了隐式的“deep supervision”;
  • 参数更小且计算更高效,这有点违反直觉,由于DenseNet是通过concat特征来实现短路连接,实现了特征重用,并且采用较小的growth rate,每个层所独有的特征图是比较小的;
  • 由于特征复用,最后的分类器使用了低级特征。

References:DenseNet:比ResNet更优的CNN模型


5.熟悉senet的结构

什么是SeNet?

Squeeze-and-Excitation Networks(简称 SENet),采用了一种全新的「特征重标定」策略,显式地建模特征通道之间的相互依赖关系,具体来说,就是通过学习的方式来自动获取到每个特征通道的重要程度,然后依照这个重要程度去提升有用的特征并抑制对当前任务用处不大的特征。

网络结构是怎样的?

深度学习杂谈_第40张图片

  • 左边为 C’×H’×W’ 的特征图,经过一系列卷积,pooling 操作 Ftr 之后,得到 C×H×W 大小的特征图。接下来进行一个 Sequeeze and Excitation block。

  • Sequeeze:对 C×H×W 进行 global average pooling,得到 1×1×C 大小的特征图,这个特征图可以理解为具有全局感受野。

  • Excitation :这里的Excitation用的是 全连接层->Relu激活->全连接层,第一个全连接层将特征维度降低到原来的1/r,第二个全连接层将维度升回原来的大小。这里使用两个而不是一个全连接层的原因是:
    (1) 增加更多的非线性,可以更好地拟合通道间复杂的相关性
    (2) 尽可能减少参数量和计算量

  • 特征重标定:使用 Excitation 得到的结果作为权重,乘到输入特征上。

参考:轻量级模块SENet与SKNet详解
参考:后ResNet时代:SENet与SKNet


四、其他

1.熟悉样本不均衡的解决方法

2.熟悉过拟合和欠拟合的解决方法

3.熟悉常用正则化方法

4.熟悉常用的几个优化器

5.熟悉分类模型常用的几个评价指标,二分类和多分类

6.对熵、条件熵、相对熵、交叉熵的理解

五、实战

1.完成一个图像分类任务的全流程,包含图像的前处理、训练、预测、后处理等

你可能感兴趣的:(深度学习杂谈)