赞
踩
如果只有元数据,那么可以使用one-hot编码,然后用密集连接网络来预测价格。如果只有文本描述,那么可以使用循环神经网络或一维卷积神经网络。如果只有图像,那么可以使用二维卷积神经网络。但是怎么才能同时使用这三种数据呢?一种朴素的方法是训练三个独立的模型,然后对三者的预测做加权平均。但是这种办法可能不是最优的,因为模型提取的信息可能存在冗余。更好的方法是使用一个可以同时查看所有可用的输入模态的模型,从而联合学习一个更加精确的数据模型---这个模型具有三个输入分支。
在多输入模型、多输出模型和类图模型的案例中,只用Keras中的Sequential模型类是无法实现的。但是还有另一种更加通用、更加灵活的使用Keras的方式,就是函数式API(functional API)。
使用函数式API,你可以直接操作张量,也可以把层当作函数来使用,接收张量并返回张量(因此得名函数式API)。
- from keras import Input,layers
-
- input_tensor = Input(shape=(32,)) /一个张量
-
- dense = layer.Dense(32, activation='relu') /一个层是一个函数
-
- output_tensor = dense(input_tensor) /可以在一个张量上调用一个层,它会返回一个张量
函数式API可用于构建具有多个输入的模型。通常情况下,这种模型会在某一时刻用一个可以组合多个张量的层讲不通的输入分支合并,张量组合方式可能是相加、连接等。这通常利用Keras的合并运算来实现,比如Keras.layers.add、Keras.layers.concatenate等。
利用相同的方法,我们还可以使用函数式API来构建具有多个输出(或多头)的模型。一个简单的例子就是一个网络试图同时预测数据的不同性质,比如一个网络,输入某个匿名人士的一系例社交媒体发帖,然后尝试预测那个人的属性,比如年龄、性别和收入水平。
重要的是,训练这种模型需要能够对网络的各个头指定不同的损失函数。但是,梯度下降要求将一个标量最小化,所以为了能够训练模型,我们必须将这些损失合并为单个标量。合并不同损失最简单的方法就是对所有损失求和。在Keras中,你可以在编译时使用损失组成的列表或字典来为不同输出指定不同损失,然后将得到的损失值相加得到一个全局损失,并在训练过程中将这个损失最小化。
注意,严重不平衡的损失贡献会导致模型表示针对单个损失值最大的任务优先进行优化,而不考虑其他任务的优化。为了解决这个问题,我们可以为每个损失值对最终损失的贡献分配不同大小的重要性。如果不同的损失值具有不同的取值范围,那么这一方法尤其有用。
利用函数式API,我们不仅可以构建多输入和多输出的模型,而且还可以实现具有复杂的内部拓扑结构的网络。Keras中的神经网络可以是层组成的任意有向无环图(directed acyclic graph)。无环(acyclic)这个限定词很重要,即这些图不能有循环。张量x不能成为生成x的某一层的输入。唯一允许的处理循环(即循环连接)是循环层的内部循环。
一些常见的神经网络组件都以图的形式实现。两个著名的组件是Inception模块和残差连接。
它是模型的堆叠,这些模块本身看起来像是小型的独立网络,被分为多个并行分支。Inception模块最基本的形式包含3~4个分支,首先是一个1*1的卷积,然后是一个3*3的卷积,最后将所得到的特征连接在一起。这种设置有助于网络分别学习空间特征和逐通道的特征,这比联合学习这两种特征更加有效。
1*1卷积的作用
我们已经知道,卷积能够在输入张量的每一个方块周围提取空间图块,并对所有图块应用相同的变换。极端情况是提取的图块只包含一个方块。这时卷积运算等价于让每个方块向量经过一个Dense层:它计算得到的特征能够将输入张量通道中的信息混合在一起,但不会将跨空间的信息混合在一起(因为它一次只查看一个方块。)这种1*1卷积[也叫作逐点卷积(pointwise convolution)]是Inception模块的特色,它有助于区分开通道特征学习和空间特征学习。
Xception模型也是Keras的applications模块的一部分。Xception代表极端Inception(extreme inception),它是一种卷积神经网络架构。Xception将分别进行通道特征学习与空间特征学习的想法推向逻辑上的极端,并将Inception模块替换为深度可分离卷积,其中包括一个逐深度卷积(即一个空间卷积,分别对每个输入通道进行处理)和后面的一个逐点卷积(即一个1*1卷积)。这个深度可分离卷积实际上是Inception模块的一种极端形式,其空间特征和通道特征被完全分离。
残差连接解决了所有大规模深度学习模型的两个共性问题:梯度消失和表示瓶颈。通常来说,向任何多于10层的模型中添加残差连接,都可能会有所帮助。
残差连接是让前面某层的输出作为后面某层的输入,从而在序列网络中有效地创造一条捷径。前面层的输出没有与后面层的激活连接在一起,而是与后面层的激活相加(这里假设两个激活的形状相同)。如果它们的形状不同,我们可以用一个线性变换将前面层的激活改变成目标形状。如果特征图的尺寸相同,在Keras中实现残差连接的方法用的是恒等残差连接(identity residual connection)。如果特征图的尺寸不同,实现残差连接的方法是线性残差连接(linear residual connection)。
深度学习中的表示瓶颈:
在Sequential模型中,每个连接的表示层都构建于前一层之上,这一位着它只能访问前一层激活中包含的信息。如果某一层太小(比如特征维度太低),那么模型将会受限于该层激活中能够塞入多少信息。
深度学习中的梯度消失:
反向传播是用于训练深度学习网络的主要算法,其工作原理是将来自输出损失的反馈信号向下传播到更底部的层。如果这个反馈信号的传播需要经过很多层,那么信号可能会变得非常微弱,甚至完全丢失,导致网络无法训练。这个问题被称为梯度消失(vanishing gradient)。
函数式API还有一个重要特性,那就是能够多次重复使用一个层实例。如果你对一个层实例调用两次,而不是每次调用都实例化一个新层,那么每次调用可以重复使用相同的权重。这样你可以构建具有共享分支的模型,即几个分支全部共享相同的知识并执行相同的运算。这就是说,这些分支共享相同的表示,并同时对不同的输入集合学习这些表示。
在函数式API中,可以像使用层一样使用模型。实际上,你可以将模型看作“更大的层”。Sequential类和Model类都是如此。这意味着你可以在一个输入张量上调用模型,并得到一个输出张量。
y = model(x)
如果模型具有多个输入张量和多个输出张量,那么应该用张量列表来调用模型。
y1, y2 = model([x1, x2])
在调用模型实例时,就是在重复使用模型的权重,正如在调用层实例时,就是在重复使用层的权重。
训练模型时,很多事情一开始都无法预测。尤其是你不知道需要多少轮才能得到最佳验证损失。通常的策略是训练足够多的轮次,这时模型已经开始过拟合,根据这第一次运行来确定训练所需要的正确轮次,然后使用这个最佳轮数从头开始再启动一次新的训练。当然,这种方法很浪费。
处理这个问题的更好方法是,当观测到验证损失不再改善时就停止训练。这可以使用Keras回调函数来实现。回调函数(callback)是在调用fit时传入模型的一个对象(即实现特定方法的类实例),它在训练过程中的不同时间点都会被模型调用。它可以访问关于模型状态与性能的所有可用数据,还可以采取行动:中断训练、保存模型、加载一组不同的权重或改变模型的状态。
回调函数的一些用法示例如下所示:
这是一个内置于TensorFlow中的基于浏览器的可视化工具,注意,只用当Keras使用TemsorFlow后端时,这一方法才能用于Keras模型。
TensorBoard的主要用途是,在训练过程中帮助你以可视化的方法监控模型内部发生的一切。如果你监控了除模型最终损失之外的更多信息,那么可以更清楚地了解模型做了什么、没做什么,并且能够更快地取得进展。TensorBoard具有下列巧妙地功能,都在浏览器中实现。
除了残差连接,还有另外两种设计模式:标准化和深度可分离卷积。这些模式在构建高性能深度卷积神经网络时特别重要,但在其他许多类型的架构中也很常见。
标准化(normalization)是一大类方法,用于让机器学习模型看到的不同样本彼此之间更加相似,这有助于模型的学习与对新数据的泛化。最常见的数据标准化形式就是:将数据减去其平均值使其中心为0,然后将数据除以其标准差使其标准差为1。实际上,这种做法假设数据服从正态分布(也叫高斯分布),并确保让该分布的中心为0,同时缩放到方差为1。
normalized_data = (data - np.mean(data, axis=...)) / np.std(data, axis=...)
批标准化(batch normalization)的主要效果是,它有助于梯度传播(这一点和残差连接很像),因此允许更深的网络。对于有些特别深的网络,只有包含多个BatchNormalization层时才能进行训练。
深度可分离卷积(depthwise separable convolution)层(SeparableConv2D)的作用:可以替代Conv2D,并且可以让模型更加轻量(即更少的课训练权重参数)、速度更快(即更少的浮点数运算),还可以让任务性能提高几个百分点。这个层对输入的每个通道分别执行空间卷积,然后通过逐点卷积(1*1卷积)将输出通道混合。这相当于将空间特征学习和通道特征学习分开,如果你假设输入中的空间位置高度相关,但不同的通道之间相对独立,那么这么做是很有意义的。它需要的参数要少很多,计算量也更小,因此可以得到更小、更快的模型。
如果只用有限的数据从头开始训练小型模型,这些优点就变得尤为重要。对于规模更大的模型,深度可分离卷积时Xception架构的基础,Xception时一个高性能的卷积神经网络,内置于Keras中。
超参数优化的过程通常如下所示:
这个过程的关键在于,给定许多组超参数,使用验证性能的历史来选择下一组需要评估的超参数的算法。
训练模型权重相对简单:在小批量数据上计算损失函数,然后用反向传播算法让权重向正确的方向移动。与此相反,更新超参数则非常具有挑战性。我们考虑以下两点:
通常情况下,随机搜索(随机选择需要评估的超参数,并重复这一过程)就是最好的解决方案,虽然这也是最简单的解决方案。
注意:在进行大规模超参数自动优化时,有一个重要的问题需要牢记,那就是验证集过拟合。因为你是使用验证数据计算出一个信号,然后根据这个信号更新超参数,所以你实际上是在验证数据上训练超参数,很快会对验证数据过拟合。
集成是指将一系列不同模型的预测结果汇集到一起,从而得到更好的预测结果。集成依赖于这样的假设,即对于独立训练的不同良好模型,它们表现良好可能是因为不同的原因:每个模型都从略有不同的角度观察数据来做出预测,得到了“真想”的一部分,但不是全部真相。借助盲人摸象的古代寓言来解释:每个人都得到了数据真想的一部分,但不是全部真相,将他们的观点汇集在一起,你可以得到对数据更加准确的描述。大象是多个部分的组合,每个盲人说的都不完全准确,但综合起来就成了一个相当准确的故事。
想要保证集成方法有效,关键在于在组分类器的多样性。如果所有盲人都只摸到大象的鼻子,那么他们会一致认为大象像蛇,并且永远不会知道大象的真实模样。是多样性让集成方法能够取得良好效果。用机器学习的术语来说,如果所有模型的偏差都在同一个方向上,那么集成也会保留同样的偏差。如果各个模型的偏差在不同方向上,那么这些偏差会彼此抵消,集成结果会更加稳定、更加准确。
因此,集成的模型应该尽可能好,同时尽可能不同。这通常意味着使用非常不同的架构,甚至使用不同类型的机器学习方法。有一件事情基本上是不值得做的,就是对相同的网络,使用不同的随机初始化多次独立训练,然后集成。如果模型之间的唯一区别是随机初始化和训练数据的读取顺序,那么集成的多样性很小,与单一模型相比只会有微小的改进。
集成不在于你的最佳模型有多好,而在于候选模型集合的多样性。
----今天不学习,明天变废物。----
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。