Python深度学习(不用 Sequential 模型的解决方案:Keras 函数式 API)--学习笔记(十五)

本文介绍了Keras函数式API在深度学习中的应用,包括构建多输入、多输出模型以及处理非线性网络拓扑结构,如Inception模块和残差连接。函数式API允许模型以有向无环图的形式存在,适用于多模态输入、多目标输出和复杂网络结构的场景,如问答模型、多任务学习和共享权重的模型。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第7章 高级的深度学习最佳实践

7.1 不用Sequential模型的解决方案:Keras函数式API

  • 到目前为止,介绍的所有神经网络都是用Sequential模型实现的。Sequential模型假设,网络只有一个输入和一个输出,而且网络是层的线性堆叠。
  • 这是一个经过普遍验证的假设。这种网络配置非常常见,以至于前面只用Sequential模型类就能够涵盖许多主题和实际应用。但有些情况下这种假设过于死板。有些网络需要多个独立的输入,有些网络则需要多个输出,而有些网络在层与层之间具有内部分支,这使得网络看起来像是层构成的图(graph),而不是层的线性堆叠。
  • 例如,有些任务需要多模态(multimodal)输入。这些任务合并来自不同输入源的数据,并使用不同类型的神经层处理不同类型的数据。假设有一个深度学习模型,试图利用下列输入来预测一件二手衣服最可能的市场价格:用户提供的元数据(比如商品品牌、已使用年限等)、用户提供的文本描述与商品照片。如果你只有元数据,那么可以使用one-hot编码,然后用密集连接网络来预测价格。如果你只有文本描述,那么可以使用循环神经网络或一维卷积神经网络。如果你只有图像,那么可以使用二维卷积神经网络。但怎么才能同时使用这三种数据呢?一种朴素的方法是训练三个独立的模型,然后对三者的预测做加权平均。但这种方法可能不是最优的,因为模型提取的信息可能存在冗余。更好的方法是使用一个可以同时查看所有可用的输入模态的模型,从而联合学习一个更加精确的数据模型。
  • 同样,有些任务需要预测输入数据的多个目标属性。给定一部小说的文本,你可能希望将它按类别自动分类(比如爱情小说或惊悚小说),同时还希望预测其大致的写作日期。当然,你可以训练两个独立的模型:一个用户划分类别,一个用于预测日期。但由于这些属性并不是统计无关的,你可以构建一个更好的模型,用这个模型来学习同时预测类别和日期。这种联合模型将有两个输出,或者说两个头(head)。因为类别和日期之间具有相关性,所以知道小说的写作日期有助于模型在小说类别的空间中学到丰富而又准确的表示,反之亦然。
  • 此外,许多最新开发的神经架构要求非线性的网络拓扑结构,即网络结构为有向无环图。比如,Inception系列网络(由Google的Szegedy等人开发)依赖于Inception模块,其输入被多个并行的卷积分支所处理,然后将这些分支的输出合并为单个张量。最近还有一种趋势是向模型中添加残差连接(residual connection),它最早出现于ResNet系列网络(由微软的何凯明等人开发)。残差连接是将前面的输出张量与后面的输出张量相加,从而将前面的表示重新诸如下游数据流中,这有助于防止信息处理流程中的信息损失。
  • 这三个重要的使用案例(多输入模型、多输出模型和类图模型),只用Keras中的Sequential模型类是无法实现的。但是还有另一种更加通用、更加灵活的使用Keras的方式,就是函数式API(function API)。
7.1.1 函数式API简介
  • 使用函数式API,你可以直接操作张量,也可以把层当作函数来使用,接收张量并返回张量(因此得名函数式API)。
from keras import Input, layers

input_tensor = Input(shape=(32,)) # 一个张量

dense = layers.Dense(32, activation='relu') # 一个层是一个函数

output_tensor = dense(input_tensor) # 可以在一个张量上调用一个层,它会返回一个张量
from keras.models import Sequential, Model
from keras import layers
from keras import Input

seq_model = Sequential() # 前面学过的Sequential模型
seq_model.add(layers.Dense(32, activation='relu', input_shape=(64, )))
seq_model.add(layers.Dense(32, activation='relu'))
seq_model.add(layers.Dense(10, activation='softmax'))

print(seq_model.summary())

# 对应的函数式API实现
input_tensor = Input(shape=(64,))
x = layers.Dense(32, activation='relu')(input_tensor)
x = layers.Dense(32, activation='relu')(x)
output_tensor = layers.Dense(10, activation='softmax')(x)

# Model类将输入张量和输出张量转换为一个模型
model = Model(input_tensor, output_tensor)

print(model.summary())
  • 这里只有一点可能看起来有点神奇,就是将Model对象实例化只用了一个输入张量和一个输出张量。Keras会在后台检索从input_tensor到output_tensor所包含的每一层,并将这些层组合成一个类图的数据结构,即一个Model。当然,这种方法有效的原因在于,output_tensor是通过对input_tensor进行多次变换得到的。如果你试图利用不相关的输入和输出来构建一个模型,那么会得到RuntimeError。
  • 对这种Model实例进行编译、训练或评估时,其API与Sequential模型相同。
model.compile(optimizer='rmsprop', loss='categorical_crossentropy') # 编译模型

import numpy as np

# 生成用于训练的虚构Numpy数据
x_train = np.random.random((1000, 64))
y_train = np.random.random((1000, 10))

# 训练10轮模型
model.fit(x_train, y_train, epochs=10, batch_size=128)

score = model.evaluate(x_train, y_train)
7.1.2 多输入模型
  • 函数API可用于构建具有多个输入的模型。通常情况下,这种模型会在某一时刻用一个可以组合多个张量的层将不同的输入分支合并,张量组合方式可能是相加、连接等。这通常利用Keras的合并运算来实现,比如keras.layers.add、keras.layers.concatenate等。我们来看一个非常简单的多输入模型示例-一个问答模型。
  • 典型的问答模型有两个输入:一个自然语言描述的问题和一个文本片段(比如新闻文章),后者提供用于回答问题的信息。然后模型要生成一个回答,在最简单的情况下,这个回答只包含一个词,可以通过对某个预定义的词表做softmax得到。
  • 设置两个分支,首先将文本输入和问题输入分别编码为表示向量,然后连接这些向量,最后,在连接好的表示上添加一个softmax分类器。
# 用函数式API实现双输入问答模型
from keras.models import Model
from keras import layers
from keras import Input

text_vocabulary_size = 10000
question_vocabulary_size = 10000
answer_vocabulary_size 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值