深度学习相关经验和笔记

超参数调试

  • 可以多做交叉实验
  • 超参数的设置需要尝试和经验
    • 测试时随机选择一批超参数
    • 从粗到细的范围进行选择
    • 有的参数(学习率)应该用对数坐标随机取值
    • 至少每几个月评估一次超参数设置
    • 当资源不够时,可以一直调试一个模型(panda,babysitting one model)
    • 当资源足够,可以并行测试多个超参数模型(caviar)
  • 超参数的最优值可能会随时间变化
  • 一般可以优先考虑学习率、batch_size
  • 还可以考虑冲量因子(momentum beta)、学习率衰减、网络结构(节点数、层数)等
  • 深度学习是一个迭代的过程 想法->实验->结果->新的想法,需要快速建立第一个简单的系统,然后迭代

激活函数

  • 非线性激活函数是必须的(要不然神经网络只是在做线性映射,不能捕捉XY之间的非线性关系)(除非是做线性回归)
  • sigmoid做激活函数时很慢(梯度小),一般用在二分类的最后输出节点
  • tanh比sigmoid几乎总是效果更好 且其均值是0 有数据中心化的效果
  • 在输入很大或者很小的时候 tanh和sigmoid的斜率都很小 梯度下降会比较慢
  • Relu/leakyRelu 修正线性单元,一般可以作为默认选择
    • 优缺点:
    • 解决了梯度消失、爆炸的问题
    • 计算方便,计算速度快
    • 加速了网络的训练
    • 由于负数部分恒为0,会导致一些神经元无法激活(可通过设置小学习率部分解决)
    • 输出不是以0为中心的
  • sigmoid的导数a(1-a) tanh:1-a^2 relu/leaky relu:easy
  • softmax激活函数:适用于多分类的输出层,当类别数目为2时,与sigmoid等价,cost函数可以由binary entropy推广而来

损失函数

  • 关于模型参数的用来表达(对于特定的数据)模型效果有多好的函数
  • Loss Function 对单个样本的度量
  • Cost Function 全体样本的损失函数的均值 对全体的度量
  • rmse容易产生局部最小值
  • 一般用交叉熵(binary class)
  • 可以根据问题特点自定义损失函数

特征选择与降维

  • 获得一组特征的主要相关变量
  • 优点:
    • 剔除冗余特征,减小存储和计算的压力
    • 降维到2、3维,便于可视化
    • 过多的特征容易导致过拟合
  • 降维:PCA、t-SNE
  • 特征选择:卡方检测、信息量
    • 覆盖度
    • 取值方差
    • 熵:
      • H(X) = 对X的多个取值求和(-plog2p)
      • 越混乱越不可预测熵值越大
    • 条件熵
      • H(X|Y) = 对Y的多个取值求和(p(y)H(X|Y=y))
    • 信息增益:
      • 信息增益就是熵和特征条件熵的差,描述的是不确定性减少的程度
      • entropy(前) - entropy(后)
      • g(D, A) = H(D) - H(D|A)
      • 缺点:信息增益偏向取值较多的特征,因为当特征的取值较多时,根据此特征划分更容易得到纯度更高的子集,因此划分之后的熵更低,信息增益更高。
    • 信息增益比
      • gr(D, A) = g(D, A) / Ha(D)
      • Ha(D)的作用是作为惩罚项,特征取值多时Ha(D)更小,所以信息增益比会更大,会偏向取值较少的特征
      • Ha(D),是对于样本集合D,将当前特征A作为随机变量(分群的依据是特征A的各个特征值,而不是D的label值),求得的经验熵。
      • 并不直接选择信息增益率最大的特征,而是现在候选特征中找出信息增益高于平均水平的特征,然后在这些特征中再选择信息增益率最高的特征。
    • 基尼指数(基尼不纯度)
      • 表示在样本集合中随机选中的样本被分错的概率,集合越纯被分错的概率越小
      • 基尼指数 = 样本被选中的概率 * 样本被分错的概率
      • Gini(p) = 求和(p(1 - p)) = 1 - 求和(pk^2)
      • 二分类时 Gini(p) = 2p(1-p)
      • 基于特征A划分样本集合D的基尼指数
        • Gini(D, A) = 对A的多个取值求和(piGino(Di))

数据规范化

  • 数据规范化是十分重要的预处理步骤,用于重新调整特征的取值范围,能够保证反向传播学习的速度和效果
  • 如果没有进行规范化,波动范围更大的特征将在损失函数中获得更大的权重,对于波动较小的特征学习速度会偏慢
  • 最大最小归一
  • 对数归一
  • 分桶归一
  • 正态分布数据:零均值化 归一化方差

优化算法

  • mini-batch梯度下降:batch_size一般取64~512
  • Batch GD(小数据集适用<2000):单次迭代时间太长,可能内存放不下 速度太慢(大样本数据集情况下)
  • SGD(batch_size=1,在线训练):失去向量化带来的批次计算的加速效果,可能受样本质量影响比较大,优化过程容易震荡
  • momentum:计算参数梯度的移动平均数,依此做梯度下降,增加了超参数beta,可以取0.9
    • 指数移动加权平均 ave_n = beta * ave_n-1 + (1 - beta) * value_n,大致相当于前1/(1 - beta)个值的平均值
    • 偏差修正:ave_0 = 0, ave_n = ave_n / (1 - beta ^ n) ,一般不会用
  • Adagrad: 除以梯度的累计平方和,对于经常更新的参数,我们已经积累了大量关于它的知识,不希望被单个样本影响太大,希望学习速率慢一些;对于偶尔更新的参数,我们了解的信息太少,希望能从每个偶然出现的样本身上多学一些,即学习速率大一些,总体上可以加快学习速度,减少摆动;缺点在于梯度累计平方和单调递增,梯度更新会越来越慢。
  • RMSprop:计算参数梯度的平方移动均值,梯度下降时除以这个均值的平方根,可以减少摆动,加快较小梯度变化的参数更新
  • Adam:结合RMSprop和momentum,超参数beta1=0.9, beta2=0.999,可以优先选择adam作为默认优化方法
  • 学习率衰减: 减小mini_batch末段不收敛引起的摆动, alpha = 1 / (1 + decay_rate * epoch_num) * alpha0,或者alpha = decay_rate ^ epoch_num * alpha0

几种网络/层的结构

cnn(conv net)

  • 用卷积操作来提取(一般是图像中的)特征

  • padding

    • 卷积的缺点:1. 图像缩小 2. 边角的信息在卷积过程中利用得少
    • 在图像周围填充0 解决上面的问题
    • same padding:padding size = (f - 1) / 2 使得图片大小不变(图片尺寸 n filter尺寸 f)
    • valid padding:不进行padding
  • 深度cnn 图像越来越小 channel越来越多

  • 池化(pooling)

    • 提取特征,缩小数据量,最大池化比较常用 平均池化用得较少,常用2*2的池化层, 有助于平移不变性
    • 缩小图片,在不丢失过多信息的同时减小了计算量
    • 有助于高一些的层提取更大粒度的空间特征
  • 卷积的优点

    • 卷积层参数少的特点:参数共享(在图像中特征提取可以通用)、稀疏连接(图像的某一小部分的性质与其他部分关系不大,不用全连接)
    • 卷积层具有很好的平移不变性(即图像平移也会输出高度相似的特征,与滑动窗口卷积和池化有关)
    • 一般使用3*3的卷积核,较小的卷积核意味着更少的参数和计算,能够引入更多的过滤器,提升特征提取能力
  • 网络中的网络(1*1的卷积层):对于图中的每一个位置,等同于对所有通道做了全连接层,图片大小不变,输入size是通道数,输出是过滤器数量,可以用来压缩通道数

  • inception网络:将各种size的卷积层和池化层堆叠起来,不需要人为指定卷积层大小,网络自动学习

  • 对于图像问题,多采用开源的结构和参数权重,进行finetuning,修改上层网络结构,视情况冻结底层特征层

  • 图像数据扩增:镜像翻转、随机裁剪、平移、旋转、色彩转换

  • 例子:LeNet-5、AlexNet、VGG-16

  • 目标检测

    • 目标定位:假定图片里最多只有一个待检测物体,输出格式:
    • pc:0/1 是否存在物体
    • c one-hot 物体类别
    • bx by bw bh 0~1 物体boundingbox的位置和大小
  • 特征点识别

    • 识别物体特征点 例如人脸的眼角、鼻头、嘴角等 人体的手、腰部等
    • 输出为n个bx、by,n为不同的特征点的个数
  • 滑动窗口目标检测

    • 选用不同大小的窗口,在整个图片上滑动,检测是否含有物体
    • 滑动窗口时有许多卷积计算可以重用,所以可以将整张图片当做输入,而不是先进行裁剪,再输入到cnn当中(需要将fc层转换为conv层)
  • YOLO算法:you only look once

    • 将原始输入分成很多个小网格,对每个网格使用目标定位检测物体(假定最多只有一个物体)
    • 将物体分配到bounding box中点所在的网格(bx,by在0~1之间,bw,bh可能大于1)
    • 单次卷积实现(计算共享)
    • 交并比(intersection over union,IOU):bouding box交集和并集的比
    • 非极大值抑制:找出检测中pc最大的矩形,抑制与这个矩形IOU高的矩形,避免同一个物体被多次检测出
    • anchor box:每个物体都被分配到中点所在的网格下与其交并比最高的anchor box,能够识别不同物体在同一个网格的情况,anchor box可以手动指定,也可以使用kmeans聚类
  • 残差网络

  • 残差网络ResNet:增加捷径,有助于训练很深的神经网络

  • 有助于缓解梯度消失或者梯度爆炸

RNN

  • 几种模型

    • XY长度相等的多对多 实体词识别
    • XY长度不相等的多对多 翻译
    • 多对一 情感倾向
    • 一对多 音乐序列生成
  • GRU(Gated Recurrent Unit,门控循环单元)

    • 增加记忆细胞c
    • 门控单元: 更新门决定记忆细胞是否更新、更新多少(移动加权平均)
    • 记忆细胞作为循环的输入输出
  • LSTM

    • 门控单元更复杂更强力
    • 更新门、遗忘门、输出门
  • 双向RNN(BRNN)

    • 适用于有完整序列内容,且需要为序列每个位置做预测
    • 使用LSTM的BRNN往往是首选
  • Deep RNN

    • 下层RNN的序列输出提供给上层RNN

attention

  • 序列编码
    • RNN 递归式进行,无法并行进行,没有长期记忆
    • CNN 窗口式遍历,容易捕捉局部信息,通过层叠增大感受野
    • Attention 直接获取全局信息
  • 定义
    • Attention(Q, K, V) = softmax(QK^t / sqrt(dk))V
    • 维度:Q∈Rn×dk,K∈Rm×dk,V∈Rm×dv 最后结果:n×dv
    • 将n×dk的序列Q编码成了一个新的n×dv的序列,对于单个query,通过与key内积并softmax的方式得到q与各个key的相似度,然后依据相似度对value进行加权求和,得到query所对应的输出
    • 其中sqrt(dk)因子起到调节作用,使内积不会太大,保证softmax后不会非0即1
  • Multi-Head Attention
    • headi=Attention(QWqi,KWki,VWvi)
    • MultiHead(Q,K,V)=Concat(head1,...,headh)
    • 把QKV通过参数矩阵进行变换之后再做attention,重复h次之后拼接到一起,多头之间参数不共享
    • 类似CNN中的channel(filter数目)
  • 一般K=V,当Q=K=V时,就是自注意力机制(Self Attention)
  • 单纯的Attention并不能捕捉序列的顺序信息,Google通过位置向量来引入位置信息(sin,cos编码)
  • transformer
    • Encoder: 由N=6个相同的layers组成, 每一层包含两个sub-layers. 第一个sub-layer 就是多头注意力层(multi-head attention layer)然后是一个简单的全连接层。 其中每个sub-layer都加了residual connection(残差连接)和normalisation(归一化)
    • Decoder: 由N=6个相同的Layer组成,但这里的layer和encoder不一样, 这里的layer包含了三个sub-layers, 其中有一个self-attention layer, encoder-decoder attention layer 最后是一个全连接层。前两个sub-layer 都是基于multi-head attention layer。这里有个特别点就是masking, masking 的作用就是防止在训练的时候 使用未来的输出的单词。比如训练时,第一个单词是不能参考第二个单词的生成结果的。Masking就会把这个信息变成0,用来保证预测位置 i 的信息只能基于比 i 小的输出。

BERT、GPT、ERNIE

  • 预训练产生词向量

deepFM

CRF(条件随机场)

CRNN

NLP

  • 词嵌入:将词嵌入到多维特征空间的单点上
  • 与encoding类似
  • 比one-hot维度更少
  • 学习到词的多维特征,能表达词之间的关系
  • 降维方法:t-SNE算法,将多维特征映射到二维空间,方便查看嵌入效果
  • 词嵌入可以用大量无标注的文本内容学习,然后迁移到需要标注内容的任务上(也可以下载预训练的词嵌入模型)
  • 可以用余弦相似度求向量之间的相似程度
  • 词向量学习
    • skip gram:对一个词 取其前后N个词中的词作为目标词训练
    • CBOW:用周围的词预测中间的词
  • seq2seq
    • 翻译:rnn对输入编码之后rnn解码输出
    • beam search:集束搜索,从很大的树状搜索空间中搜索最优结果,可以看做是每一步选择多个的贪心算法,它比BFS、DFS更快,但不能保证找到最优解
    • 文本生成精确度:BLEU score(机器翻译、图片描述,不适用于机器语音转录)

视频检测

  • slowfast
  • 3d ResNet

一些经验和思考

结构化与非结构化

  • 结构化数据(能够很好地用数据库存储的数据,有很好的结构化定义)
  • 非结构化数据,文字 图像 语音等等
  • 结构化训练数据是一种很重要的能力,这个过程一般是数据预处理、特征提取和选择,能够大幅提升机器学习的效果
  • 对于非结构化输出,可以尝试进行结构化
  • 比起传统的机器学习方法,深度学习能够更好地处理非结构化数据
  • DNN的知识来自于两个方面,一个是带标记的数据集,另一个就是手工工程,当数据量较少时,手工工程就更加重要,包括数据结构化、特征工程、精心设计的网络结构等

关于计算图

  • 图的终点是损失函数,需要最小化损失函数
  • 前向计算值 反向计算导数(关于网络参数的偏导)
  • 推导得出网络参数的更新公式
  • 对于监督学习 输入X是固定的 网络参数参数w、b是变化的 通过反向传播求导来计算梯度
  • 随机初始化所有参数 将W初始化为很小的随机数 b可以设为0

梯度爆炸、梯度消失

  • 较低层(靠近输入的层)参数的偏导依赖于高层激活函数的导数的级联乘积
  • 当训练一个较深的网络,梯度计算层层传导可能出现梯度爆炸或者梯度消失,使得loss不再变化或者loss不断变大
  • 从深层网络角度来讲,不同的层学习的速度差异很大,表现为网络中靠近输出的层学习的情况很好,靠近输入的层学习的很慢
  • 可以使用梯度裁剪或者残差网络(增加shortcut)尝试解决
  • 正则项对于梯度爆炸可能有用(因为会抑制w的增长)
  • 使用relu作为激活函数可以有效控制梯度消失问题(导数不会趋近于0)
  • batchnorm对于梯度消失和爆炸也有抑制作用(规范化每层的输出,消除放大缩小的影响)

数据划分

  • 数据一般分为训练集train、开发集dev(交叉验证集)和训练集test来防止过拟合
  • 训练集和开发集都输入模型,但开发集不参与训练,只是提供实时的模型评价,测试集用于离线测试,会进行更多评价标准的测试
  • 经验做法是6:2:2或者8:1:1,随着数据量越来越大,dev和test占比可以更小
  • 三个数据集尽量要来自同一分布

过拟合与欠拟合

  • 偏差指的是算法在大型 训练集上的错误率;方差指的是算法在测试集上的表现低于训练集的程度。当使用均方误差(MSE )作为误差度量指标时,你可以写下偏差和方差对应的两个公式,并且证明总误差=偏差+方差。但在 处理机器学习问题时,此处给出的偏差和方差的非正式定义已经足够。

  • 欠拟合(高偏差、训练集表现不好)

    • 模型未能很好地捕捉训练集数据中的信息
    • 做更多的特征工程,使得训练集中的信息更容易被学习到
    • 可能网络结构无法承载和表达训练集的信息,采用新的更大的网络和调整优化方法
    • 进行更长时间的训练
    • 调整超参数
    • 不断降低偏差,直到能较好地你拟合训练集,再观察方差
  • 过拟合(高方差、dev集表现不好)

正则化

  • 正则项 在损失函数中给参数w增加一定的权重,使得模型倾向于更简单化,避免学习出过于复杂的模型从而造成过拟合,优先选用L2正则项
  • dropout 训练时在某些层随机使得一些节点失活,预测时使用全部信息,dropout能够使节点更加独立,不过多依赖其他节点进行预测,只使用部分信息也能有较好的效果,提升了模型的健壮性和泛化能力。
  • 在过拟合之前提前终止(early stopping)也是好的正则化方法

batchnorm

  • 痛点:每一层的输出的分布可能会变化,不利于后面层的学习(参考数据规范化部分)
  • 对一个batch的每层的每个feature都做normalization
  • 存在前面层学习到的信息丢失的可能,可以使用缩放和平移变量γ和β ,计算归一化后的值(并不一定做标准归一化)
  • 缩放和平移变量γ和β是对总体期望和方差的估计,每一个批次使用移动加权平均计算,这样以后既能较好地凸显一个batch内的相对关系(更有区分度),也不丢失相对总体的信息
  • 减小batch内不同数据分布的差异,使得梯度更加均匀
  • 对于像sigmoid或者tanh这样的激活函数来说,归一化的输入也更友好
  • 优点:batchnorm本身有助于正则化(对参数分布有规范化的作用);收敛较快,可以使用更大的学习率;有更好的泛化能力,可以不用或者少用其他的正则方式;batch size应该设大一些,也有助于加速训练
  • 测试和线上预估时可以使用样本总体的均值和方差,一般采用移动平均得到,预估和训练时打分不一致是正常的

神经网络调优流程

  • 首先要拟合训练集
  • 然后拟合dev和test数据集(减小方差)
  • 最后在真实世界表现提升
  • 偏差/方差分析:用人类水平(贝叶斯最优)做标杆来决定采用减小偏差还是减小方差的策略,bayes error -> training error -> dev error
  • 做误差分析:人工标记出错的类, 集中处理较常出现的误差类型

度量方法

  • 查准率(precision,P)标记为真的,多少是真样本?
  • 查全率(recall, R)对于所有为真的样本,有多少被标记了?
  • F1 score:查准率和查全率的调和平均数 1/(1/P + 1/R),单一数值评价指标
  • roc、auc: 图像纵横坐标分别是真阳率(True Positive Rate, TPR)和假阳率(False Positive Rate, FPR),在模型对于正负预测阈值的选择上,我们希望TPR尽量高,而FPR尽量低,roc的auc大于0.5,体现了在一批预测结果中正样本排在负样本前的概率
  • 多个指标的情况下,选择一个作为优化指标,选择其他的作为满足指标

迁移学习和多任务学习

  • 迁移学习:当任务A和任务B拥有相同的输入格式,且A的数据量远远大于B时,训练B数据的网络时可以将训练A数据得到的网络做fine tuning,其中的低层次特征可能会对提升B的效果有帮助
  • 多任务学习:训练单个网络处理多任务,一个样本对应多个标签,损失函数为多个任务损失函数的和,当不同任务可以共享底层特征、数据量相近时适用
  • 可以训练更大更深的网络来应对多任务

最优化问题

  • 凸函数:一个函数是凸函数是它存在最优解的充要条件
  • 约束问题
    • 无约束优化 直接对f(X)求导,得到最优解
    • 等式约束优化 拉格朗日乘数法
    • 不等式约束优化 最优解必须满足KKT条件
  • 如果损失函数不平滑(L1正则),则在不可导处使用次梯度(subgradient)代替梯度进行梯度下降
  • 稀疏性很重要,是一个主要的追求目标,除了特征选择的作用以外,稀疏性可以使得预测计算的复杂度降低
  • 在online模式下,由于W不是沿着全局梯度更新,而是一个近似随机的更新过程,即使使用L1正则也很难产生稀疏解
  • 在线最优化算法
    • 截断梯度法(TG)
    • FOBOS
    • RDA
    • FTRL

负采样

  • 主要是为了解决样本选择偏差问题,适用于比较大的物料库的情况 (经验上 >10w,可以开始尝试),如果物料库比较小,直接学精排样本可能会更好
  • 常规负采样,因为正样本里高热item是统治性的,所以要对热门item做过采样,具体按照曝光热度、点击热度还是其他需要尝试,理论上使用点击热度应该更好,因为更贴合正样本分布,样本也更难
  • 难负例构造,纯用负采样的话任务太简单,模型学不出太多有价值的东西,需要人为给样本增加难度,方法很多,一般可以尝试下面一些方式
    • 同一个request 采精排排在不上不下位置的 (100 ~ 500)
    • 用曝光未点击
    • 同一个batch 采其他用户的正样本item中打分比较高的
    • 用item相关性较高的 (比如同类目、同店铺)
posted @ 2019-01-19 15:43  排骨zzz  阅读(582)  评论(0编辑  收藏  举报