Keras之函数式(Functional)模型

函数式(Functional)模型

我们起初将Functional一词译作泛型,想要表达该类模型能够表达任意张量映射的含义,但表达的不是很精确,在Keras2里我们将这个词改移为“函数式”,函数式模型称作Functional,但它的类名是Model,因此有时候也用Model来代表函数式模型。

Keras函数式模型接口是用户定义多输出模型、非循环有向模型或具有共享层的模型等复杂模型的途径。一句话,只要你的模型不是类似VGG一样一条路走到黑的模型,或者你的模型需要多于一个的输出,那么你总应该选择函数式模型。函数式模型是最广泛的一类模型,序贯(Sequential)模型只是它的一种特殊情况。

第一个模型:全连接网络

Sequential当然是实现全连接网络的最好方式,但我们从简单的全连接网络开始,有助于我们学习这部分的内容。在开始前,有几个概念需要澄清:

  1. 层对象接受张量作为参数,返回一个张量。
  2. 输入是张量,输出也是张量的一个框架就是一个模型,通过Model定义。
  3. 这样的模型可以向Keras的Sequential一样被训练
from keras.layer import Input,Dense
from keras.models import Model

#This returns a tensor
inputs = Input(shape=(784,))

#a Layer instance is callable on a tensor , and returns a tensor
x = Dense(64 , activation=‘relu‘)(inputs)
x = Dense(64,activation=‘relu‘)(x)
predictions = Dense(10,activation=‘softmax‘)(x)

#This creates a model that includes
#the Input layer and three Dense layers
model = Model(inputs=inputs,outputs=predictions)
model.compile(optimizer=‘rmsprop‘,loss=‘categorical_crossentropy‘,metrics=[‘accuracy‘])
model.fit(data,labels) #starts training

所有的模型都是可调用的,就像层一样

利用函数式模型的接口,我们可以很容易的重用已经训练好的模型:你可以把模型当做一个层一样,通过提供一个tensor来调用它。注意当你调用一个模型时,你不仅仅重用了它的结构,也重用了它的权重。

x = Input(shape=(784,))
#This works, and returns the 10-way softmax we defined above
y = model(x)

这种方式可以允许你快速的创建能处理序列信号的模型,你可以很快将一个图像分类的模型变为一个对视屏分类的模型,只需要一行代码:

from keras.layers import TimeDistributed

#Input tensor for sequences of 20 timesteps
#each containing a 784-dimensional vector

input_sequences = Input(shape=(20,784))

#This applies our previous model to every timestep in the input sequences.
#the output of the previous model was a 10-way softmax
#so the output of the layer below will be a sequence of 20 vectors of size 10.

processed_sequences = TimeDistributed(model)(input_sequences)

多输入和多输出模型

使用函数式模型的一个典型场景是搭建多输入、多输出的模型。

考虑这样一个模型。我们希望预测Twitter上一条新闻会被转发和点赞多少次。模型的主要输入是新闻本身,也就是一个词语的序列。但我们还可以拥有额外的输入,如新闻发布的日期等。这个模型的损失函数将有两部分组成,辅助的损失函数评估仅仅基于新闻本身做出预测的情况,主损失函数评估基于新闻的额外信息的预测的情况,即使来自主损失函数的梯度发生弥散,来自辅导损失函数的信息也能够训练Embedding和LSTM层。在模型中早点使用主要的损失函数是对于深度网络的一个良好的正则方法。总而言之,该模型的框图如下:

让我们用函数式模型来实现这个框图

主要的输入接收新闻本身,即一个整数的序列(每个整数编码了一个词)。这些整数位于1到10,000之间(即我们的字典有10,000)个词。

from keras.layer import Input , Embedding , LSTM , Dense
from keras.models import Model

#Headline input: meant to receive sequences of 100 integers ,between 1 and 10000.
#Note that we can name any layer by passing it a "name" argument.
main_input = Input(shape=(100,), dtype=‘int32‘ , name=‘main_input‘)

#This embedding layer will encode the input Sequence
#into a sequence of dense 512-dimensional vectors
x = Embedding(output_dim=512, input_dim=10000, input_length=100)(main_input)

#A LSTM will transform the vector sequence into a single vector,
#containing information about the entire sequence
lstm_out = LSTM(32)(x)

然后,我们插入一个额外的损失,使得即使在主损失很高的情况下,LSTM和Embedding层也可以平滑的训练。

auxiliary_output = Dense(1, activation=‘sigmoid‘ name=‘aux_output‘)(lstm_out)

再然后,我们将LSTM与额外的输入数据串联起来组成输入,送入模型中:

auxiliary_input  = Input(shape(5,),name=‘aux_input‘)
x = keras.layers.concatenate([lstm_out, auxiliary_input])

#We stack a deep densely-connected network on top
x = Dense(64,activation=‘relu‘)(x)
x = Dense(64,activation=‘relu‘)(x)
x = Dense(64,activation=‘relu‘)(x)

#And finally we add the main logistic regression layer
main_output = Dense(1,activation=‘sigmoid‘, name=‘main_output‘)(x)

最后,我们定义整个2输入,2输出的模型:

model = Model(inputs=[main_input,auxiliary_input], outputs=[main_output, auxiliary_output])

模型的定义完毕,下一步编译模型。我们给额外的损失赋0.2的权重。我们可以通过关键字参数loss_weights或loss来为不同的输出设置不同的损失函数或权值。这两个参数均可以为python的列表或字典。这里我们给loss传递单个损失函数,这个损失函数会被应用于所有输出上。

model.compile(optimizer=‘rmsprop‘ , loss=‘binary_crossentropy‘,loss_weights=[1.,0.2])

编译完成后,我们通过传递训练数据和目标值训练该模型:

model.fit([headline_data, additional_data],[labels,labels],epochs=50,batch_size=32)

因为我们的输入和输出时被命名过的(在定义时传递了“name”参数,我们也可以用下面的方式编译和训练模型)

model.compile(optimizer=‘rmsprop‘,loss={‘main_output‘: ‘binary_crossentropy‘,‘aux_output‘:‘binary_crossentropy‘},loss_weights={‘main_output‘:1.,‘aux_output‘:0.2})

#And trained it via:
model.fit({‘main_input‘: headline_data,‘aux_input‘: addtional_data},{‘main_output‘:labels,‘aux_output‘:labels},epochs=50,batch_size=32)

共享层

另一个使用函数式模型的场合是使用共享层的时候。

考虑微博数据,我们希望建立模型来判别两条微博是否是来自同一个用户,这个需求同样可以用来判断一个用户的两条微博的相似性。

一种实现方式是,我们建立一个模型,它分别将两条微博的数据映射到两个特征向量上,然后将该特征向量串联并加一个logistic回归曾,输出她们来自同一个用户的概率。这种模型的训练数据是一度对的微博。

因为这个问题是对称的,所以处理第一条微博的模型当然也能冲用于处理第二条微博,所以这里我们使用一个共享LSTM层来进行映射。

首先,我们将微博的数据转为(140,256)的矩阵,即每条微博有140个字符,每个单词的特征由256维的词向量表示,向量的每个元素为1表示某个字符出现,为0表示不出现,这是一个one-hot编码。之所以是(140,256),是因为一条微博最多有140个字符,而扩展的ASCII码表编码了常见的256个字符。如果考虑中文字符,那一个单词的词向量就不止256了,此处的微博应为Twitter

import keras
from keras.layers import Input , LSTM,Dense
from keras.models import Model

tweet_a = Input(shape=(140,256))
tweet_b = Input(shape=(140,256))

若要对不同的输入共享同一层,就初始化该层一次,然后多次调用它

#This Layer can take as input a matrix
#and will return a vector of size 64
shared_lstm = LSTM(64)

#When we reuse the same layer instance
#multiple times, the weights of the layer
#are also being reused
#(it is effectively * the same * layer)
encode_a = shared_lstm(tweet_a)
encode_b = shared_lstm(tweet_b)

#we can then concatenate the two vectors:
merget_vector = keras.layers.cocatenate([encoded_a,encodd_b], axis=-1)

# And add a logistic regression on top
predictions = Dense(1, activation=‘sigmoid‘)(merged_vector)

# We define a trainable model linking the
# tweet inputs to the predictions
model = Model(inputs=[tweet_a, tweet_b], outputs=predictions)

model.compile(optimizer=‘rmsprop‘,
              loss=‘binary_crossentropy‘,
              metrics=[‘accuracy‘])
model.fit([data_a, data_b], labels, epochs=10)
时间: 2024-08-25 04:16:35

Keras之函数式(Functional)模型的相关文章

【tensorflow2.0】高阶api--主要为tf.keras.models提供的模型的类接口

下面的范例使用TensorFlow的高阶API实现线性回归模型. TensorFlow的高阶API主要为tf.keras.models提供的模型的类接口. 使用Keras接口有以下3种方式构建模型:使用Sequential按层顺序构建模型,使用函数式API构建任意结构模型,继承Model基类构建自定义模型. 此处分别演示使用Sequential按层顺序构建模型以及继承Model基类构建自定义模型. 一,使用Sequential按层顺序构建模型[面向新手] import tensorflow as

keras: 在构建LSTM模型时,使用变长序列的方法

众所周知,LSTM的一大优势就是其能够处理变长序列.而在使用keras搭建模型时,如果直接使用LSTM层作为网络输入的第一层,需要指定输入的大小.如果需要使用变长序列,那么,只需要在LSTM层前加一个Masking层,或者embedding层即可. from keras.layers import Masking, Embedding from keras.layers import LSTM model = Sequential() model.add(Masking(mask_value=

【Keras篇】---利用keras改写VGG16经典模型在手写数字识别体中的应用

一.前述 VGG16是由16层神经网络构成的经典模型,包括多层卷积,多层全连接层,一般我们改写的时候卷积层基本不动,全连接层从后面几层依次向前改写,因为先改参数较小的. 二.具体 1.因为本文中代码需要依赖OpenCV,所以第一步先安装OpenCV 因为VGG要求输入244*244,而数据集是28*28的,所以需要通过OpenCV在代码里去改变. 2.把模型下载后离线放入用户的管理目录下面,这样训练的时候就不需要从网上再下载了 3.我们保留的是除了全连接的所有层. 4.选择数据生成器,在真正使用

Keras Sequential顺序模型

keras是基于tensorflow封装的的高级API,Keras的优点是可以快速的开发实验,它能够以TensorFlow, CNTK, 或者 Theano 作为后端运行. 模型构建 最简单的模型是 Sequential 顺序模型,它由多个网络层线性堆叠.对于更复杂的结构,你应该使用 Keras 函数式 API,它允许构建任意的神经网络图. 用Keras定义网络模型有两种方式, Sequential 顺序模型 Keras 函数式 API模型 1.Sequential 顺序模型 from kera

Java多线程-并发编程模型

以下内容转自http://ifeve.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B%E6%A8%A1%E5%9E%8B/: 并发系统可以采用多种并发编程模型来实现.并发模型指定了系统中的线程如何通过协作来完成分配给它们的作业.不同的并发模型采用不同的方式拆分作业,同时线程间的协作和交互方式也不相同.这篇并发模型教程将会较深入地介绍目前(2015年,本文撰写时间)比较流行的几种并发模型. 并发模型与分布式系统之间的相似性 本文所描述的并发模型类似于分布式系统中使

4.并发编程模型

并发系统可以采用多种并发编程模型来实现.并发模型指定了系统中的线程如何通过协作来完成分配给它们的作业.不同的并发模型采用不同的方式拆分作业,同时线程间的协作和交互方式也不相同.这篇并发模型教程将会较深入地介绍目前(2015年,本文撰写时间)比较流行的几种并发模型. 并发模型与分布式系统之间的相似性 本文所描述的并发模型类似于分布式系统中使用的很多体系结构.在并发系统中线程之间可以相互通信.在分布式系统中进程之间也可以相互通信(进程有可能在不同的机器中).线程和进程之间具有很多相似的特性.这也就是

Keras学习手册(一),开篇-使用 Python3 的Deep Learning 库

感谢作者分享-http://bjbsair.com/2020-04-07/tech-info/30656.html === 你恰好发现了 Keras. Keras 是一个用 Python 编写的高级神经网络 API,它能够以 TensorFlow, CNTK, 或者 Theano 作为后端运行.Keras 的开发重点是支持快速的实验.能够以最小的时延把你的想法转换为实验结果,是做好研究的关键. 如果你在以下情况下需要深度学习库,请使用 Keras: 允许简单而快速的原型设计(由于用户友好,高度模

javaScript函数式编程-包含闭包、链式优化及柯里化

本文着重介绍个人理解的函数式编程. 函数式编程个人理解为:以函数为主要载体的编程方式. 好处: 语义更加清晰 可复用性高 可维护性好 作用域局限.副作用少 基本函数式编程: //实现数组中每个单词首字母大写 //一般写法 const arr = ['apple','orange','pear']; for(const i in arr) { const c = arr[i][0]; arr[i] = c.toUpperCase() + arr[i].slice(1); //slice()从已有的

上手Keras

Keras的核心数据是"模型",模型是一种组织网络层的方式.Keras中主要的模型是Sequential模型,Sequential是一系列网络层按顺序构成的栈. Sequential模型如下: from Keras.models import Sequential model = Sequential() 将网络层通过.add()堆叠起来,就构成了一个模型: from Keras.layers import Dense, Activation model.add(Dense(units