详细笔记地址: http://www.ai-start.com/dl2017/ 这里只是做些自己的摘抄与理解
吴恩达(英语:Andrew Ng)是斯坦福大学计算机科学系和电气工程系的客座教授,曾任斯坦福人工智能实验室主任。他还与达芙妮·科勒一起创建了在线教育平台Coursera。 吴恩达老师的机器学习课程可以说是入门机器学习的同学最先接触的课程,当然后续的deeplearning.ai是更深入的课程。对在线教育,以及人工智能领域的发展提供了很大的帮助,感谢。
1 神经网络与深度学习
1.1什么是神经网络
输入层输入的是特征,什么是特征,与预测或处理物体息息相关的事情都可以考虑作为特征,只是特征有轻有重,不同的特征对应的权重不一样,所以需要神经网络去学习特征前的权重参数。 给予足够多的训练样本有关𝑥 和𝑦,神经网络非常擅长计算从𝑥到𝑦的精准映射函数。
1.2 神经网络的监督学习
- 监督学习:表明你的数据不仅只有特征,还有标签
- 结构化数据:结构化数据意味着数据的基本数据库。例如有专门的几列数据告诉你卧室的大小和数量,这就是结构化数据。
- 非结构化数据:非结构化数据是指比如音频,原始音频或者你想要识别的图像或文本中的内容。这里的特征可能是图像中的像素值或文本中的单个单词。 神经网络算法对于结构化和非结构化数据都有用处
1.3 为什么深度学习会兴起
传统的算法面对大数据时候性能有瓶颈 对于神经网络而言,得益于大数据的发展以及计算性能的提升,再次得到发展。 想要获得较高的性能体现,那么你有两个条件要完成,第一个是你需要训练一个规模足够大的神经网络,以发挥数据规模量巨大的优点 小型网络、中型网络以及大型网络对应的数据量以及其性能
另外就是算法上的创新
- 激活函数
- 网络结构
- 快速的迭代
2 神经网络的编程基础
2.1 二分类(Binary Classification)
在电脑的眼里,图片是用矩阵的形式表示 这里将矩阵转化为列向量后作为神经网络的输入
2.2 逻辑回归
为什么用逻辑回归而不是线性回归,因为线性回归wx+b的输出值比1大,或者是比 0小,无法比较输出类别的概率大小,因此使用sigmoid函数对其进行非线性激活,将范围变为0-1之间
2.4 逻辑函数的损失函数
损失函数:用来衡量预测输出值和实际值有多接近 逻辑回归不实用mse均方误差这类损失函数是由于其不是凸函数,只能找到多个局部最优值,梯度下降法很可能找不到全局最优值。 在逻辑回归中用到的损失函数是二元交叉熵损失函数: 𝐿(𝑦^ , 𝑦) = −𝑦log(𝑦^) − (1 − 𝑦)log(1 − 𝑦^)
- 当𝑦 = 1时损失函数𝐿 = −log(𝑦^) ,如果想要损失函数𝐿尽可能得小,那么𝑦^就要尽可能大,因为 sigmoid 函数取值[0,1],所以𝑦^会无限接近于 1。
- 当𝑦 = 0时损失函数𝐿 = −log(1 − 𝑦^) ,如果想要损失函数𝐿尽可能得小,那么𝑦^就要尽可能小,因为 sigmoid 函数取值[0,1],所以𝑦^会无限接近于 0。 损失函数只适用于像这样的单个训练样本,而代价函数是参数的总代价。这里总容易将损失函数与代价函数混为一谈,损失函数关心个体,代价函数关心总的样本。
2.4 梯度下降算法
用于更新参数的一种训练方法,这里不作过多的介绍
2.5 计算图
一个神经网络的计算,都是按照前向或反向传播过程组织的。首先我们计算出一个新的网络的输出(前向过程),紧接着进行一个反向传输操作。
2.6 使用计算图求导数
链式法则反向求J对变量a、b、c的偏导数
2.7 逻辑回归的计算题求解梯度下降
以单样本为例,损失函数L为 -(ylog(a) + (1-y)log(1-a)) y是标签,a是激活值 求解得到 dl/da = (-y/a + (1-y)/(1-a)) dl/dz = dl/da * da/dz = (-y/a + (1-y)/(1-a)) * a(1-a) = a-y dl/dw1 = dl/da * da/dz * dz/dw1 = (a-y) * x1
2.8 向量化(Vectorization)
向量化是非常基础的去除代码中 for 循环的艺术 用向量操作替换循环元素处理
2.9 向量化逻辑回归(Vectorizing Logistic Regression)
numpy 广播机制
- axis=0: 沿着列进行处理
- axis=1: 沿着行进行处理 建议不使用一维数组, 总是使用 𝑛 × 1维矩阵(基本上是列向量),或者 1 × 𝑛 维矩阵(基本上是行向量)表示n个元素。 或者用assert来判断其形状assert(a.shape == (5, 1))
3 浅层神经网络
3.1 神经网络概述
可以把许多sigmoid 单元堆叠起来形成一个神经网络
3.2 神经网络的表示
输入层:传递输入 隐藏层:线性加权求和,再通过激活函数激活 输出层:预测值
向量化表示
3.3 激活函数的类型
sigmoid:输出范围是0~1
tanh: 输出范围是-1~1
注意:
- tanh 函数或者双曲正切函数是总体上都优于 sigmoid 函数的激活函数。tanh 函数是 sigmoid 的向下平移和伸缩后的结果。对它进行了变形后,穿过了(0,0)点。
- sigmoid和tanh共同的缺点是,在𝑧特别大或者特别小的情况下,导数的梯度或者函数的斜率会变得特别小,最后就会接近于 0,导致降低梯度下降的速度。
ReLU: 输出范围0~+∞
正数的导数为1,负数的导数为0,神经元此时不会训练,易导致稀疏性。
Leaky Relu:输出范围 -∞ ~ + ∞
避免了ReLU负数阶段的导数为0,以一个非常小的数作为梯度值。 总结
- ReLu 激活函数神经网络通常会比使用 sigmoid 或者 tanh 激活函数学习的更快;
- sigmoid 和 tanh 函数的导数在正负饱和区的梯度都会接近于 0,这会造成梯度弥散,而 Relu 和 Leaky ReLu 函数大于 0 部分都为常数,不会产生梯度弥散现象。(同时应该注意到的是,Relu 进入负半区的时候,梯度为 0,神经元此时不会训练,产生所谓的稀疏性,而 Leaky ReLu 不会有这问题)
- sigmoid 激活函数:除了输出层是一个二分类问题基本不会用它。
- tanh 激活函数:tanh 是非常优秀的,几乎适合所有场合。
- ReLu 激活函数:最常用的默认函数,如果不确定用哪个激活函数,就使用 ReLu 或者Leaky ReLu。
如果不确定哪一个激活函数效果更好,可以把它们都试试,然 后在验证集或者发展集上进行评价。然后看哪一种表现的更好,就去使用它。
3.4 为什么使用非线性激活函数
如果隐藏层使用的是线性函数的话就没有意义,等价于逻辑回归时候,中间的多个隐藏层可以直接由一个线性函数表示。 对于神经网络而言,就是需要使用非线性激活函数来获得有意思的函数映射。 但是对于回归问题,其输出层可以使用线性激活函数。唯一可以用线性激活函数的通常就是输出层。
3.5 激活函数的导数
- sigmoid
- tanh
- ReLU 和leaky ReLU *
3.6 神经网络的梯度下降算法
梯度下降算法用于更新网络中的参数w和偏置b,基于输出值与预期值之间的误差函数来进行反向传播来更新的。
- 正向传播(forward): 从左到右
- 方向传播(back propagation): 从右到左
3.7 随机初始化
当你训练神经网络时,权重随机初始化是很重要的。如果你把权重或者参数都初始化为 0,那么梯度下降将不会起作用。 对于𝑊可以随机初始化,𝑏可以初始化为 0。
通常倾向于初始化为很小的随机数, 你用 tanh 或者sigmoid 激活函数,或者说只在输出层是 sigmoid,如果(数值)波动太大,当计算激活值时,如果𝑊很大,𝑧就会很大。𝑧的激活值𝑎就会很大或者很小,这种情况下很可能停在 tanh/sigmoid 函数的平坦的地方,这些地方梯度很小也就意味着梯度下降会很慢,因此学习也就很慢。
4 深层神经网络
4.1 深层神经网络
- 严格上来说逻辑回归也是一个一层的神经网络,而上边右图一个深得多的模型,浅与深仅仅是指一种程度。
- 算神经网络的层数时,不算输入层,只算隐藏层和输出层。
到有一些函数,只有非常深的神经网络能学会,而更浅的模型则学不到。尽管对于任何给定的问题很难去提前预测到底需要多深的神经网络,所以先去尝试逻辑回归,尝试一层然后两层隐含层,然后把隐含层的数量看做是另一个可以自由选择大小的超参数,然后再保留交叉验证数据上评估,或者用你的开发集来评估。
4.2 深层神经网络反向传播
-
前向传播
-
反向传播
4.3 为什么使用深层表示
深度神经网络的这许多隐藏层中,较早的前几层能学习一些低层次的简单特征,等到后几层,就能把简单的特征结合起来,去探测更加复杂的东西。
1 深度学习实践
1.1 训练集、验证集、测试集(Train / Dev / Test sets)
对训练执行算法,通过验证集或简单交叉验证集选择最好的模型。 在机器学习发展的小数据量时代,常见做法是将所有数据三七分,就是人们常说的 70%验证集,30%测试集,如果没有明确设置验证集,也可以按照 60%训练,20%验证和 20%测试集来划分。
- 假设我们有 100 万条数据,其中 1 万条作为验证集,1 万条作为测试集,100 万里取 1 万,比例是 1%,即:训练集占 98%,验证集和测试集各占 1%。对于数据量过百万的应用,训练集可以占到 99.5%,验证和测试集各占 0.25%,或者验证集占 0.4%,测试集占 0.1%
- 通常将样本分成训练集,验证集和测试集三部分,数据集规模相对较小,适用传统的划分比例,数据集规模较大的,验证集和测试集要小于数据总量的 20%或 10%
- 要确保验证集和测试集的数据来自同一分布
1.2 偏差与方差
- 欠拟合:高偏差 high bias
- 过拟合:高方差 high variance
1.3 机器学习基础
- 高偏差解决方法:欠拟合,增大网络模型、更多的时间训练、更好的优化方法
- 高方差解决方法:过拟合,增加训练数据、减小网络模型、加入正则化
1.4 正则化
深度学习可能存在过拟合问题——高方差,有两个解决方法,一个是正则化,另一个是准备更多的数据。但准备更多的数据比较耗时耗力。 以逻辑回归损失函数为例:
- L0正则:参数为零的个数,难求解
- L1正则:各个参数绝对值之和,侧重于让其为0(LASSO)
- L2正则: 各个参数的平方的和的开方值,侧重于让参数稀疏化(Ridge)
实现参数的稀疏有什么好处吗?
- 可以简化模型,避免过拟合。因为一个模型中真正重要的参数可能并不多,如果考虑所有的参数起作用,那么可以对训练数据可以预测的很好,但是对测试数据就不行了
- 参数变少可以使整个模型获得更好的可解释性
参数值越小代表模型越简单吗?
- 是的。为什么参数越小,说明模型越简单呢,这是因为越复杂的模型,越是会尝试对所有的样本进行拟合,甚至包括一些异常样本点,这就容易造成在较小的区间里预测值产生较大的波动,这种较大的波动也反映了在这个区间里的导数很大,而只有较大的参数值才能产生较大的导数。因此复杂的模型,其参数值会比较大。
总结
- L1会趋向于产生少量的特征,而其他的特征都是0,而L2会选择更多的特征,这些特征都会接近于0。Lasso在特征选择时候非常有用,而Ridge就只是一种规则化而已
- 在所有特征中只有少数特征起重要作用的情况下,选择Lasso L1比较合适,因为它能自动选择特征。而如果所有特征中,大部分特征都能起作用,而且起的作用很平均,那么使用Ridge L2也许更合适
- 一般倾向于选择L2正则
𝜆是正则化参数,通常使用验证集或交叉验证集来配置这个参数,尝试各种各样的数据,寻找最好的参数,要考虑训练集之间的权衡,把参数设置为较小值,这样可以避免过拟合
如果正则化参数𝜆变得很大,参数𝑊很小,𝑧也会相对变小,此时忽略𝑏的影响,𝑧会相对变小,实际上,𝑧的取值范围很小,曲线函数𝑡𝑎𝑛ℎ会相对呈线性,整个神经网络会计算离线性函数近的值,这个线性函数非常简单,并不是一个极复杂的高度非线性函数,不会发生过拟合。
1.5 dropout正则化
实现方式:反向随机失活(inverted dropout) 在测试阶段,当我们评估一个神经网络时,也就是用绿线框标注的反向随机失活方法,使测试阶段变得更容易 反向随机失活(inverted dropout)方法通过除以 keep-prob,确保激活值a的期望值不变。 在测试阶段,并未使用 dropout,自然也就不用抛硬币来决定失活概率,以及要消除哪些隐藏单元,因为在测试阶段进行预测时,不期望输出结果是随机的。
dropout好处:
- 不要依赖于任何一个特征,因为该单元的输入可能随时被清除, 将产生收缩权重的平方范数的效果。将产生收缩权重的平方范数的效果。
- 每个单元,它不能依靠任何特征,因为特征都有可能被随机清除,或者说该单元的输入也都可能被随机清除,将产生收缩权重的平方范数的效果。
dropout缺点:
- 代价函数𝐽不再被明确定义
使用经验:
- dropout 是一种正则化方法,它有助于预防过拟合。
- 因此除非算法过拟合,不然是不会使用 dropout 的,所以它在其它领域应用得比较少,主要存在于计算机视觉领域
只有存在过拟合时,才决定是否使用dropout。如果不存在过拟合,使用它并不一定能够提升模型性能。
1.6 其它正则化方法
1.数据扩增(data augmentation)
方法:水平垂直翻转、随机裁剪、随机放大裁剪、轻微形变
2.early stopping
验证集性能有多少次迭代都没有变化时,使用early stop,在此时停止。
优点:
- 只运行一次梯度下降,可以找出𝑤的较小值,中间值和较大 值,而无需尝试𝐿2正则化超级参数𝜆的很多值
缺点:
- 不能独立地处理这两个问题,因为提早停止梯度下降,也就是停止了优化代价函数𝐽,因为现在你不再尝试降低代价函数𝐽,所以代价函数𝐽的值可能不够小。
建议还是使用L2正则化来代替early stopping。
1.7 归一化输入
标准化
标准化需要两个步骤:
- 零均值
- 归一化方差 确保所有特征都在相似范围内,通常可以帮助学习算法运行得更快。
1.8 梯度消失/爆炸
训练神经网络,尤其是深度神经所面临的一个问题就是梯度消失或梯度爆炸,导数或坡度有时会变得非常大,或者非常小,甚至于以指数方式变小,这加大了训练的难度。
1.9 神经网络的权重初始化
-
随机高斯 初始化变量,然后除以每层节点数的平方根
-
设置的权重矩阵既不会增长过快,也不会太快下降到 0,从而训练出一个权重或梯度不会增长或消失过快的深度网络,也可以加快收敛速度。
2 优化方法
2.1 mini-batch gradient descent
batch: 每次都拿全部的样本进行梯度更新来训练网络,导致速度很慢。 mini-batch: 把训练集分割为小一点的子集,然后用子集进行训练。
- batch: 训练耗时,曲线更平滑
- mini-batch: 训练更快,曲线有噪声,增大mini-batch数,曲线会平滑些
mini-batch = m ----> batch mini-batch = 1 ----> sgd
2.2 指数加权平均数
做偏差修正,可以让平均数运算更加准确。初始时候预测结果不准确,导致前期结果有一段不准确。使用偏差修正能够解决这类问题。
2.3 动量梯度下降算法 Momentum
计算梯度的指数加权平均数,并利用该梯度更新权重。比一般的梯度下降算法要快。 等高线纵轴方向波动小些,横轴方向移动快些。
2.4 RMSprop
root mean square prop 减缓𝑏方向的学习,即纵轴方向,同时加快,至少不是减缓横轴方向的学习。 与动量梯度下降有些相似,但是偏导数的平方项,且在进行参数更新的时候,除以开方数。
在横轴方向或者在例子中的𝑊方向,我们希望学习速度快,而在垂直方向,也就是例子中的𝑏方向,希望减缓纵轴上的摆动,所以有了𝑆𝑑𝑊和𝑆𝑑𝑏,我们希望𝑆𝑑𝑊会相对较小,所以我们要除以一个较小的数,而希望𝑆𝑑𝑏又较大,所以要除以较大的数字,这样就可以减缓纵轴上的变化。
2.5 Adam优化算法
Adam 优化算法基本上就是将 Momentum 和 RMSprop 结合在一起。
2.6 学习率衰减
加快学习算法的一个办法就是随时间慢慢减少学习率,将之称为学习率衰减。 减少𝑎的本质在于,在学习初期,能承受较大的步伐,但当开始收敛的时候,小一些的学习率能步伐小一些
3 超参数调试
3.1 参数选择
- 区域网格搜索
- 尺度范围搜索 用对数标尺搜索超参数的方式会更合理,因此这里不使用线性轴,分别依次取0.0001,0.001,0.01,0.1,1,在对数轴上均匀随机取点。
3.2 超参数调试实践
- 熊猫方式:每次只训练一个或几个模型,然后参数优化
- 鱼籽方式:每次训练多个模型,每个模型参数不同 这两种方式的选择,是由你拥有的计算资源决定的,如果你拥有足够的计算机去平行试验许多模型,那绝对采用鱼子酱方式,尝试许多不同的超参数,看效果怎么样
3.3 batch normal
Batch归一化会使你的参数搜索问题变得很容易,使神经网络对超参数的选择更加稳定,超参数的范围会更加庞大,工作效果也很好,也会是你的训练更加容易
- 加快学习速度: 类似于逻辑回归输入归一化
- 隐藏层:以就会影响𝑤, 𝑏的训练。简单来说,这就是 Batch 归一化的作用。尽管严格来说,真正归一化的不是𝑎,而是𝑧,深度学习文献中有一些争论,关于在激活函数之前是否应该将值𝑧归一化,或是否应该在应用激活函数𝑎后再规范值。实践中,经常做的是归一化𝑧,就是卷积层之后,激活函数之前。 Batch 归一化的作用是它适用的归一化过程,不只是输入层,甚至同样适用于神经网络中的深度隐藏层。应用 Batch 归一化了一些隐藏单元值中的平均值和方差,不过训练输入和这些隐藏单元值的一个区别是,也许不想隐藏单元值必须是平均值 0 和方差 1,标准化后还可以加两个参数alpha与beta进行调节,也可以调节其均值与方差值不再是标准的0与1。
为什么有效:
- 归一化可以加快学习速度
- 可以使权重比网络更滞后或更深层,减少了“Covariate shift”的问题(前一层参数改变影响后面的层)。Batch 归一化减少了输入值改变的问题,它的确使这些值变得更稳定,减弱了前层参数的作用与后层参数的作用之间的联系,它使得网络每层都可以自己学习,稍稍独立于其它层,这有助于加速整个网络的学习
- 轻微正则化的效果:在 mini-batch 计算中,由均值 和方差缩放的,因为在 mini-batch 上计算的均值和方差,而不是在整个数据集上,均值和方差有一些小的噪声,对每一层的激活值加了少许噪声。正则化效果,因为给隐藏单元添加了噪音,这迫使后部单元不过分依赖任何一个隐藏单元。
总结:
- 在训练时,𝜇和𝜎2是在整个 mini-batch 上计算出来的包含了像是 64 或28 或其它一定数量的样本
- 在测试时,可能需要逐一处理样本,方法是根据训练集估算𝜇和𝜎2,估算的方式有很多种,理论上可以在最终的网络中运行整个训练集来得到𝜇和𝜎2,但在实际操作中,我通常运用指数加权平均来追踪在训练过程中你看到的𝜇和𝜎2的值。训练时候每个batch计算一个均值与方差,再基于指数加权平均的形式(优化算法中之前用到过)跟踪最新的均值与方差。
3.4 Softmax分类器
Softmax将逻辑回归推广到C类上,当C==2时,等同于逻辑回归。 输出是多维向量,维度与类别数一致,表明属于每一类的概率值,相加为1。 softmax激活函数分为以下步骤:
- 线性激活 --> z=wx+b
- 求幂指数 --> tmp = e^z
- 归一化 --> a = tmp / total(tmp) 训练Softmax:
- 训练样本标签 类似于hardmax形式,属于哪一类,那个维度向量的index为1
- 损失函数为类似于逻辑回归的损失函数 -y log y’ 损失函数所做的就是它找到训练集中的真实类别,然后试图使该类别相应的概率尽可能地高。这就是统计学中的极大似然估计。
3.5 深度学习框架
挑选原则:
- 便于编程
- 运行速度要快,训练等
- 是否真的开放:不仅需要开源,而且需要良好的管理
- 对应的编程语言:Python,Java 还是 C++
- 对应的任务应用:计算机视觉、自然语言处理或者线上广告
1 机器学习策略
在机器学习中,可以观察你的系统,然后说这一部分是错的,它在训练集上做的不好、在开发集上做的不好、它在测试集上做的不好,或者它在测试集上做的不错,但在现实世界中不好,这就很好。必须弄清楚到底是什么地方出问题了,然后刚好有对应的旋钮,或者一组对应的旋钮,刚好可以解决那个问题,那个限制了机器学习系统性能的问题。
1.2 单一数字评测指标
一般做法:
- 有想法,编程序,跑实验,看看效果如何,然后使用这些实验结果来改善想法,然后继续走这个循环,不断改进算法
有这样一个开发集,加上单实数评估指标,迭代速度肯定会很快,它可以加速改进机器学习算法的迭代过程
有一个单实数评估指标真的可以提高效率,或者提高团 队做出这些决策的效率
1.3 满足和优化指标
准确度与时间上面的综合权衡 考虑𝑁个指标,有时候选择其中一个指标做为优化指标是合 理的。所以你想尽量优化那个指标,然后剩下𝑁 − 1个指标都是满足指标,意味着只要它们达到一定阈值,例如运行时间快于 100 毫秒,但只要达到一定的阈值,你不在乎它超过那个门槛之后的表现,但它们必须达到这个门槛。
1.4 训练集 验证集 测试集的划分
用训练集训练不同的模型,然后使用开发集来评估不同的思路,然后选择一个,然后不断迭代去改善开发集的性能,直到最后你可以得到一个令你满意的成本,然后你再用测试集去评估 注意:
- 开发集和测试集来自同一分布,将所有数据随机洗牌,放入开发集和测试集
- 针对目标收集数据集
划分比例:
- 机器学习早期: 全部数据用 70/30 比例分成训练集和测试集。或者如果你必须设立训练集、开发集和测试集,分 60%训练集,20%开发集,20%测试集。(数据集小的时候,几千-1w)
- 深度学习时代:百万级别数据,98%作为训练集,1%开发集,1%测试集
改变数据集:
- 如果你当前的指标和当前用来评估的数据和你真正关心必须做好的事情关系不大,那就应该更改你的指标或者你的开发测试集,让它们能更够好地反映你的算法需要处理好的数据
- 对于错分的样本需要加大损失权重
1.5 提升模型的性能
好的模型就两件事:
- 算法对训练集的拟合很好,这可以看成是你能做到可避免偏差很低
- 在训练集中做得很好,然后推广到开发集和测试集也很好,这就是说方差不是太大
偏差上的提升(欠拟合):
- 使用规模更大的模型,
- 训练更久
- 使用更好的优化算法,比如说加入 momentum 或者RMSprop、 Adam
- 更好的新神经网络架构
- 更好的超参数:激活函数、隐藏层数、隐藏节点数
方差上的提升(过拟合):
- 收集更多数据
- 尝试正则化,包括𝐿2正则化,dropout 正则化
- 数据增强。
- 不同的神经网络架构
- 超参数搜索
2 机器学习策略
2.1 进行误差分析
搭建应用系统,那这个简单的人工统计步骤,错误分析,可以节省大量时间,可以迅速决定什么是最重要的,或者最有希望的方向
进行错误分析,应该找一组错误样本,可能在开发集里或者测试集里,观察错误标记的样本,看看假阳性(false positives)和假阴性(false negatives),统计属于不同错误类型的错误数量 如果这些标记错误严重影响了你在开发集上评估算法的能力,那么就应该去花时间修正错误的标签。如果它们没有严重影响到你用开发集评估成本偏差的能力,那么可能就不应该花宝贵的时间去处理。
在构造实际系统时,通常需要更多的人工错误分析,更多的人类见解来架构这些系统,尽管深度学习的研究人员不愿意承认这点
2.2 快速搭建你的第一个系统,并进行迭代
应该尽快建立你的第一个系统原型,然后快速迭代 主要目标是弄出能用的系统,并不是发明全新的机器学习算法。可以从现有大量学术文献为基础出发,一开始就搭建比较复杂的系统。
2.3 使用来自不同分布的数据进行训练和测试
越来越多的团队都用来自和开发集、测试集分布不同的数据来训练,这里有一些微妙的地方,一些最佳做法来处理训练集和测试集存在差异的情况。 这是由于项目任务所针对的图片类型决定的,比如手机app要识别的是用户手机拍摄的猫,而这类数据集少,网上爬虫的数据集大,但与任务的数据不是同一个分布,将其混合起来再划分这样的方法并不好,这是由于混一起后验证集、测试集中任务所要针对的图片占的比例很低。
开发集和测试集都是手机图。而训练集包含了来自网页的 20 万张图片,还有 5000 张来自应用的图片,开发集就是 2500 张来自应用的图片,测试集也是 2500 张来自应用的图片。这样将数据分成训练集、开发集和测试集的好处在于,现在你瞄准的目标就是你想要处理的目标。
有助于提高你的学习算法的性能,但是,潜在问题就不只是偏差和方差问题,这样做会引入第三个潜在问题,数据不匹配。 将训练集划分为训练集与训练-验证集(不用来训练,只测试)来看偏差与方差的关系。
2.4 处理数据不匹配问题
- 对训练数据与开发数据进行错误分析,把训练集变得更像开发集
- 尽可能地收集到相似的训练数据
- 人工数据合成(注意过拟合)
存在数据不匹配问题,建议你做错误分析,或者看看训练集,或者看看开发集,试图找出,试图了解这两个数据分布到底有什么不同,然后看看是否有办法收集更多看起来像开发集的数据作训练。
2.5 迁移学习
把神经网络最后的输出层拿走,就把它删掉,还有进入到最后一层的权重删掉,然后为最后一层重新赋予随机权重,然后让它在放射诊断数据上训练。
如果你有足够多的数据,你可以重新训练神经网络中剩下的所有层。经验规则是,如果你有一个小数据集,就只训练输出层前的最后一层,或者也许是最后一两层。
- 预训练:拿通用数据训练网络模型
- 微调:固定之前的层,拿专用数据只训练后面的一层
优点: 需要的数据少,学得快
2.6 多任务学习
在多任务学习中,同时开始学习的,试图让单个神经网络同时做几件事情,然后希望这里每个任务都能帮到其他所有任务。 什么时候可以使用多任务学习:
- 第一,如果你训练的一组任务,可以共用低层次特征。
- 第二,这个准则没有那么绝对,所以不一定是对的。如果想要从多任务学习得到很大性能提升,那么其他任务加起来必须要有比单个任务大得多的数据量
- 第三,一些场合:训练一个足够大的神经网络,那么多任务学习肯定不会或者很少会降低性能,我们都希望它可以提升性能,比单独训练神经网络来单独完成各个任务性能要更好。
多任务学习能让你训练一个神经网络来执行许多任务,这可以给你更高的性能,比单独完成各个任务更高的性能
2.7 端到端的深度学习
以前有一些数据处理系统或者学习系统,它们需要多个阶段的处理。那么端到端深度学习就是忽略所有这些不同的阶段,用单个神经网络代替它。
输入数据,构建网络模型,直接得到结果。这需要大量的数据以及好的应用场景。 如果不好一步到位,使用分任务的方式将其串起来也是很好的解决方案。
优点:
- 端到端学习真的只是让数据说话,可能更能够捕获数据中的任何统计信息,而不是被迫引入人类的成见。
- 所需手工设计的组件更少,所以这也许能够简化设计工作流程,不需要花太多时间去手工设计功能,手工设计这些中间表示方式
缺点:
- 可能需要大量的数据
- 排除了可能有用的手工设计组件
1卷积神经网络
1 计算机视觉
应用:
- 图片分类
- 图片识别
- 目标检测
- 风格迁移
- … …
1.2 边缘检测
边缘检测算子中的数字用于进行边缘检测 计算机视觉不一定要去使用那些研究者们所选择的这九个数字,而是将这 9 个数字当成学习参数
1.3 padding
valid: 不填充,卷积后尺寸变小 same: 填充,卷积后尺寸不变
这也是为什么通常将卷积核设置为奇数的充分原因
1.4 步长
卷积操作:向下取整
1.5 三维卷积
按照计算机视觉的惯例,当你的输入有特定的高宽和通道数时,你的过滤器可以有不同的高,不同的宽,但是必须一样的通道数。
注意:
- 多个卷积核的情况,结果数与卷积核的数量一致。
- 两个过滤器,也就是有两个特征(检测两个特征)。
参数计算: (每个卷积核的参数+1个bias) * 卷积核的个数
1.6 简单例子
逐层提取特征,在最后一层进行特征展开,为一个向量,输入到逻辑回归或者softmax分类器,得到最终分类结果。
1.7 池化层pooling
除了卷积层,卷积网络也经常使用池化层来缩减模型的大小,提高计算速度,同时提高所提取特征的鲁棒性。
-
最大池化: max pooling 输出的每个元素都是其对应颜色区域中的最大元素值。 最大化运算的实际作用就是,如果在过滤器中提取到某个特征,那么保留其最大值。如果没有提取到这个特征,可能在右上象限中不存在这个特征,那么其中的最大值也还是很小,这就是最大池化的直观理解。
-
平均池化: 选取的不是每个过滤器的最大值,而是平均值
-
一般而言,最大池化比平均池化要常用些,但例外就是深度很深的神经网络,可以用平均池化来分解规模为 7×7×1000 的网络的表示层,在整个空间内求平均值,得到1×1×1000,取代全连接层。
-
输入通道与输出通道个数相同,因为我们对每个通道都做了池化。
-
池化过程中没有需要学习的参数。执行反向传播时,反向传播没有参数适用于最大池化。
池化层的反向传播 需要保证传递的loss(或者梯度)总和不变
- mean pooling: 把一个patch中的值求取平均来做pooling,那么反向传播的过程也就是把某个元素的梯度等分为n份分配给前一层,这样就保证池化前后的梯度(残差)之和保持不变
- max pooling: 把梯度直接传给前一层某一个像素,而其他像素不接受梯度,也就是为0
1.8 卷积神经网络例子
- 人们在计算神经网络有多少层时,通常只统计具有权重和参数的层。因为池化层没有权重和参数,只有一些超参数。这里,我们把 CONV1和 POOL1 共同作为一个卷积,并标记为Layer1
- 常规做法是,尽量不要自己设置超参数,而是查看文献中别人采用了哪些超参数,选一个在别人任务中效果很好的架构,那么它也有可能适用于自己的应用程序
- 找到整合基本构造模块最好方法就是大量阅读别人的案例
1.9 为什么使用卷积
和只用全连接层相比,卷积层的两个主要优势在于参数共享和稀疏连接。
- 参数共享:每个特征检测器以及输出都可以在输入图片的不同区域中使用同样的参数,以便提取垂直边缘或其它特征
- 稀疏连接:依赖于这个 3×3 的输入的单元格,右边这个输出单元(元素 0)仅与 36 个输入特征中 9 个相连接。而且其它像素值都不会对输出产生任影响。
2 实例探究
在计算机视觉任务中表现良好的神经网络框架往往也适用于其它任务, 完全可以借鉴别人的神经网络框架来解决自己的问题。
2.1 经典网络
- LeNet-5 的网络结构 左往右看,随着网络越来越深,图像的高度和宽度在缩小,从最初的 32×32 缩小到 28×28,再到 14×14、10×10,最后只有 5×5。与此同时,随着网络层次的加深,通道数量一直在增加,从 1 增加到 6 个,再到 16 个。 一种模式至今仍然经常用到,就是一个或多个卷积层后面跟着一个池化层,然后又是若干个卷积层再接一个池化层,然后是全连接层,最后是输出,这种排列方式很常用。
*** AlexNet**
-
这些层分别拆分到两个不同的 GPU 上,同时还专门有一个方法用于两个 GPU 进行交流
-
叫作“局部响应归一化层”(Local Response Normalization),即 LRN 层
-
VGG VGG16在这个网络中包含 16 个卷积层和全连接层
-
padding都是same,conv层输出的尺寸没有变化。
-
由 64 翻倍变成 128,再到 256 和 512。作者可能认为 512 已经足够大了,所以后面的层就不再翻倍了。无论如何,每一步都进行翻倍,或者说在每一组卷积层进行过滤器翻倍操作,正是设计此种网络结构的另一个简单原则。
-
随着网络的加深,图像的高度和宽度都在以一定的规律不断缩小,每次池化后刚好缩小一半,而通道数量在不断增加,而且刚好也是在每组卷积操作后增加一倍。
2.2 残差网络ResNet
在残差网络中有一点变化,我们将𝑎[𝑙]直接向后,拷贝到神经网络的深层,在 ReLU 非线性激活函数前加上𝑎[𝑙],这是一条捷径。𝑎[𝑙]的信息直接到达神经网络的深层,不再沿着主路径传递。 𝑎[𝑙+2] = 𝑔(𝑧[𝑙+2] + 𝑎[𝑙])
- 使用残差块能够训练更深的神经网络
- 这种方式确实有助于解决梯度消失和梯度爆炸问题,让我们在训练更深网络的同时,又能保证良好的性能
为什么效果好:
- 残差块最差的效果是与原有的一样(w、b为0),只是多了几层
- 隐藏层单元学到一些有用信息,那么它可能比学习恒等函数表现得更好
- ResNets 使用了许多 same 卷积,所以这个𝑎[𝑙]的维度等于这个输出层的维度。之所以能实现跳跃连接是因为 same 卷积保留了维度,所以很容易得出这个捷径连接,并输出这两个相同维度的向量
2.3 为 1×1 卷积、 Network in Network
作用:
- 1×1 卷积是压缩或增加通道数量,并减少计算量
- 提供非线性函数功能
2.4 inception网络
使用 same 卷积,保持维度不变
- 基本思想是 Inception 网络不需要人为决定使用哪个过滤器或者是否需要池化,而是由网络自行确定这些参数,你可以给网络添加这些参数的所有可能值,然后把这些输出连接起来,让网络自己学习它需要什么样的参数,采用哪些过滤器组合。 28×28×256 的输出。通道连接实际就是把所有方块连接在一起的操作。
- GoogleLeNet
2.5 数据增强
当训练计算机视觉模型的时候,数据增强会有所帮助。
- 垂直镜像
- 随机裁剪
- 旋转
- 扭曲变形
- 局部弯曲
- 彩色转换: R、G 和 B 三个通道上加上不同的失真值
2.6 计算机视觉现状
- 数据量少:传统机器学习方法,手工特征工程,迁移学习等
- 数据量大:深度学习方法
提升基准测试或者竞赛:
- 集成:训练多个分类器,取均值
- multi-crop:对同一张图随机裁剪10次,得到10张图,然后取平均结果
3 目标检测
3.1 目标定位
算法判断图片中是不是一辆汽车,还要在图片中标记出它的位置,用边框或红色方框把汽车圈起来,这就是定位分类问题 目标检测在原有的图像分类基础上又增加了几个输出:边界框𝑏𝑥,𝑏𝑦, 𝑏ℎ和𝑏𝑤,这四个数字是被检测对象的边界框的参数化表示。 标签 : 第一个组件𝑝𝑐表示是否含有对象,如果对象属于前三类(行人、汽车、摩托车),则𝑝𝑐 = 1,如果是背景,则图片中没有要检测的对象,则𝑝𝑐 = 0。我们可以这样理解𝑝𝑐,它表示被检测对象属于某一分类的概率,背景分类除外。
𝑝𝑐 = 1,同时输出𝑐1、𝑐2和𝑐3,表示该对象属于 1-3 类中的哪一类。 损失函数:
3.2 特征点检测
神经网络可以通过输出图片上特征点的(𝑥, 𝑦)坐标来实现对目标特征的识别 准备一个卷积网络和一些特征集,将人脸图片输入卷积网络,输出 1 或 0, 1 表示有人脸,0 表示没有人脸,然后输出(𝑙1𝑥,𝑙1𝑦)……直到(𝑙64𝑥,𝑙64𝑦)。这里我用𝑙代表一个特征,这里有129 个输出单元,其中1表示图片中有人脸,因为有64个特征,64×2=128,所以最终输出 128+1=129 个单元
人体姿态检测,你还可以定义一些关键特征点,如胸部的中点,左肩,左肘,腰等。然后通过神经网络标注人物姿态的关键特征点,再输出这些标注过的特征点,就相当于输出了人物的姿态动作。
3.3 目标检测
滑动窗检测: 滑动窗口目标检测算法接下来会继续处理第二个图像,即红色方框稍向右滑动之后的区域,并输入给卷积网络,因此输入给卷积网络的只有红色方框内的区域,再次运行卷积网络,然后处理第三个图像,依次重复操作,直到这个窗口滑过图像的每一个角落。
- 优点:表现良好
- 缺点:计算成本太高,因为在图片中剪切出太多小方块,卷积网络要一个个地处理。如果间隔步伐太大,显然会减少输入卷积网络的窗口个数,但是粗糙间隔尺寸可能会影响性能
3.4 滑动窗口的实现
不需要把输入图像分割成四个子集,分别执行前向传播, 而是把它们作为一张图片输入给卷积网络进行计算,其中的公共区域可以共享很多计算。
3.5 bound box预测
在滑动窗口法中,你取这些离散的位置集合,然后在它们上运行分类器,在这种情况下,这些边界框没有一个能完美匹配汽车位置。 yolo算法可以获得准确的方格。在图像上放一个网格。基本思路是使用图像分类和定位算法。对于每个格子都指定一个标签y 普通的卷积网络,卷积层,最大池化层等等,最后你会有这个,选择卷积层和最大池化层,这样最后就映射到一个 3×3×8 输出尺寸。所以你要做的是,有一个输入𝑥,就是这样的输入 图像,然后你有这些 3×3×8 的目标标签𝑦。
优点在于神经网络可以输出精确的边界框,但是每个格子只能有一个对象
注意:
- 这和图像分类和定位算法非常像
- 卷积实现,运行速度快,可以达到实时
读不懂研究论文的时候,必须去读源代码,或者联系作者之类的才能弄清楚这些算法的细节
3.6 交叉比IOU
一般约定,在计算机检测任务中,如果𝑙𝑜𝑈 ≥ 0.5,就说检测正确,如果预测器和实际边界框完美重叠,loU 就是 1,因为交集就等于并集。但一般来说只要𝑙𝑜𝑈 ≥ 0.5,那么结果是可以接受的,看起来还可以。
3.7 非极大值抑制
非极大值抑制这个方法可以确保你的算法对每个对象只检测一次 会对同一个对象做出多次检测,所以非极大值抑制做的就是清理这些检测结果。这样一辆车只检测一次,而不是每辆车都触发多次检测。 pc*c1、c2、c3 先用阈值丢弃一些结果 然后去掉所有剩下的边界框,任何没有达到输出标准的边界框,之前没有抛弃的边界框,把这些和输出边界框有高重叠面积和上一步输出边界框有很高交并比的边界框全部抛弃
3.8 anchor boxes
预先定义两个不同形状的 anchor box,或者 anchor box 形状,你要做的是把预测结果和这两个 anchor box 关联起来。 观察哪一个 anchor box 和实际边界框(编号1,红色框)的交并比更高,不管选的是哪一个,这个对象不只分配到一个格子,而是分配到一对,即(grid cell,anchor box)对,这就是对象在目标标签中的编码方式。所以现在输出 𝑦 就是 3×3×16,上一张幻灯片中你们看到 𝑦 现在是 16 维的,或者你也可以看成是3×3×2×8,因为现在这里有 2 个 anchor box,而 𝑦 是 8 维的。 anchor box 这个概念,是为了处理两个对象出现在同一个格子的情况
对于每个类别单独运行非极大值抑制,处理预测结果所属类别的边界框,用非极大值抑制来处理行人类别,用非极大值抑制处理车子类别,然后对摩托车类别进行非极大值抑制,运行 三次来得到最终的预测结果。所以算法的输出最好能够检测出图像里所有的车子,还有所有的行人
3.9 候选区域
4 特殊应用
4.1 人脸识别
人脸验证与人脸识别的区别 人脸验证问题:如果你有一张输入图片,以及某人的 ID 或者是名字,这个系统要做的是,验证输入图片是否是这个人。有时候也被称作 1 对 1 问题,只需要弄明白这个人是否和他声称的身份相符 人脸识别问题:比人脸验证问题难很多,是1对k的问题
4.2 one-shot 学习
需要通过单单一张图片或者单单一个人脸样例就能去识别这个人, 训练样本只有一个。 不再是分类问题,而是要学习一个能够衡量二者区别的函数
4.3 siamese 网络(孪生网络)
输入不再是一个图片,而是图片对。输出二者的维度为128维,然后比较二者的距离。 损失函数可以:
- Contrastive Loss
- cosine更适用于词汇级别的语义相似度度量
- exp更适用于句子级别、段落级别的文本相似性度量
4.4 Triplet loss
应用三元组损失函数,你需要比较成对的图像。一个 Anchor图片,想让 Anchor 图片和 Positive 图片(Positive 意味着是同一个人)的距离很接近。然而,当 Anchor 图片与 Negative图片(Negative 意味着是非同一个人)对比时,会想让其距离离得更远一点。 anchor与正样本之间的距离小于anchor与负样本之间的距离 为了确保网络对于所有的编码不会总是输出 0,也为了确保它不会把所有的编码都设成互相相等的 𝑎是另一个超参数,这个就可以阻止网络输出无用的结果。 损失函数:
如何构建训练样本:
- 随机选择的话太容易满足约束条件
- 尽可能选择难训练的三元组APN 𝐴、𝑃和𝑁的选择使得𝑑(𝐴, 𝑃)很接近𝑑(𝐴, 𝑁),即𝑑(𝐴, 𝑃) ≈ 𝑑(𝐴, 𝑁),这样学习算法会竭尽全力使右边这个式子变大(𝑑(𝐴, 𝑁)),或者使左边这个式子(𝑑(𝐴, 𝑃))变小,这样左右两边至少有一个𝑎的间隔。
4.5 人脸验证与而分类
最后两个特征进行相减后,再送入logist回归,输出0/1
4.6 神经风格迁移
将使用𝐶来表示内容图像,𝑆表示风格图像,𝐺表示生成的图像
代价函数:
- 内容代价:衡量c与g内容的相似性
- 风格代价:衡量s与g风格的相似性 模型:
- 1.随机生成生成图片G像素矩阵
- 2.利用损失函数更新G像素矩阵值 𝐺: = 𝐺 − 𝜕𝐽(𝐺)/𝜕G
内容代价函数:
- 使用预训练的cnn网络模型抽特征,计算二者的特征距离,将其作为内容代价。
风格代价函数 利用风格矩阵表示各自的风格,然后计算二者矩阵差,求和求均值