目录:

  • 目录:
  • 函数式(Functional)模型
  • 第一个模型:全连接网络
  • 多输入和多输出模型
  • 让我们用函数式模型来实现这个框图
  • 共享层
  • 更多的例子
  • inception模型
  • 卷积层的残差连接
  • 共享视觉模型
  • 视觉问答模型
  • 视频问答模型

本系列参考官方文档官方文档
这就是keras可以参考前篇:这就是keras
学习笔记 Keras:一些基本概念 一些基本概念
Keras:常见问题学习笔记:Keras常见问题
Windows 下Keras安装和配置指南:Windows 下Keras安装和配置指南
Keras:序列式模型 keras :序列式模型

函数式(Functional)模型

最开始将Functional一词译作泛型,想要表达该类模型能够表达任意映射的含义,但表达的不是很精确,在Keras 2里将这个词改译为“函数式”,对函数式编程有所了解的同学应能够快速get到该类模型想要表达的含义。例如,MapReduce这个超好用的工具,函数式模型称作Functional,但它的类名是Model,因此我们有时候也用Model来代表函数式模型。

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

这部分的文档假设你已经对Sequential模型已经比较熟悉

让我们从简单一点的模型开始

第一个模型:全连接网络

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

层对象接受张量作为输入参数,返回一个张量。输入是张量,输出也是张量的一个框架就是一个模型,通过Model定义。这样的模型可以被像Keras的Sequential一样被训练
from keras.layers 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上一条新闻会被转发和点赞多少次。模型的主要输入是新闻本身,也就是一个词语的序列。但我们还可以拥有额外的输入,如新闻发布的日期等。这个模型的损失函数将由两部分组成,辅助的损失函数评估仅仅基于新闻本身做出预测的情况,主损失函数评估基于新闻和额外信息的预测的情况,即使来自主损失函数的梯度发生弥散,来自辅助损失函数的信息也能够训练Embeddding和LSTM层。在模型中早点使用主要的损失函数是对于深度网络的一个良好的正则方法。总而言之,该模型框图如下:

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

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

from keras.layers 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': additional_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个字符。原文中此处为Tweet,所以对外国人而言这是合理的。如果考虑中文字符,那一个单词的词向量就不止256了。

import keras
from keras.layers import Input, LSTM, Dense
from keras.models import Modeltweet_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)
encoded_a = shared_lstm(tweet_a)
encoded_b = shared_lstm(tweet_b)# We can then concatenate the two vectors:
merged_vector = keras.layers.concatenate([encoded_a, encoded_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)

先暂停一下,看看共享层到底输出了什么,它的输出数据shape又是什么
层“节点”的概念

无论何时,当你在某个输入上调用层时,你就创建了一个新的张量(即该层的输出),同时你也在为这个层增加一个“(计算)节点”。这个节点将输入张量映射为输出张量。当你多次调用该层时,这个层就有了多个节点,其下标分别为0,1,2…

在上一版本的Keras中,你可以通过layer.get_output()方法来获得层的输出张量,或者通过layer.output_shape获得其输出张量的shape。这个版本的Keras你仍然可以这么做(除了layer.get_output()被output替换)。但如果一个层与多个输入相连,会出现什么情况呢?

如果层只与一个输入相连,那没有任何困惑的地方。.output将会返回该层唯一的输出

a = Input(shape=(140, 256))lstm = LSTM(32)
encoded_a = lstm(a)assert lstm.output == encoded_a

但当层与多个输入相连时,会出现问题

a = Input(shape=(140, 256))
b = Input(shape=(140, 256))lstm = LSTM(32)
encoded_a = lstm(a)
encoded_b = lstm(b)lstm.output

上面这段代码会报错

>> AssertionError: Layer lstm_1 has multiple inbound nodes,
hence the notion of "layer output" is ill-defined.
Use `get_output_at(node_index)` instead.

通过下面这种调用方式即可解决

assert lstm.get_output_at(0) == encoded_a
assert lstm.get_output_at(1) == encoded_b

对于input_shape和output_shape也是一样,如果一个层只有一个节点,或所有的节点都有相同的输入或输出shape,那么input_shape和output_shape都是没有歧义的,并也只返回一个值。但是,例如你把一个相同的Conv2D应用于一个大小为(32,32,3)的数据,然后又将其应用于一个(64,64,3)的数据,那么此时该层就具有了多个输入和输出的shape,你就需要显式的指定节点的下标,来表明你想取的是哪个了

a = Input(shape=(32, 32, 3))
b = Input(shape=(64, 64, 3))conv = Conv2D(16, (3, 3), padding='same')
conved_a = conv(a)# Only one input so far, the following will work:
assert conv.input_shape == (None, 32, 32, 3)conved_b = conv(b)
# now the `.input_shape` property wouldn't work, but this does:
assert conv.get_input_shape_at(0) == (None, 32, 32, 3)
assert conv.get_input_shape_at(1) == (None, 64, 64, 3)

更多的例子

代码示例依然是学习的最佳方式,这里是更多的例子

inception模型

inception的详细结构参见Google的这篇论文:Going Deeper with Convolutions

from keras.layers import Conv2D, MaxPooling2D, Inputinput_img = Input(shape=(256, 256, 3))tower_1 = Conv2D(64, (1, 1), padding='same', activation='relu')(input_img)
tower_1 = Conv2D(64, (3, 3), padding='same', activation='relu')(tower_1)tower_2 = Conv2D(64, (1, 1), padding='same', activation='relu')(input_img)
tower_2 = Conv2D(64, (5, 5), padding='same', activation='relu')(tower_2)tower_3 = MaxPooling2D((3, 3), strides=(1, 1), padding='same')(input_img)
tower_3 = Conv2D(64, (1, 1), padding='same', activation='relu')(tower_3)output = keras.layers.concatenate([tower_1, tower_2, tower_3], axis=1)

卷积层的残差连接

残差网络(Residual Network)的详细信息请参考这篇文章:Deep Residual Learning for Image Recognition

from keras.layers import Conv2D, Input# input tensor for a 3-channel 256x256 image
x = Input(shape=(256, 256, 3))
# 3x3 conv with 3 output channels (same as input channels)
y = Conv2D(3, (3, 3), padding='same')(x)
# this returns x + y.
z = keras.layers.add([x, y])

共享视觉模型

该模型在两个输入上重用了图像处理的模型,用来判别两个MNIST数字是否是相同的数字

from keras.layers import Conv2D, MaxPooling2D, Input, Dense, Flatten
from keras.models import Model# First, define the vision modules
digit_input = Input(shape=(27, 27, 1))
x = Conv2D(64, (3, 3))(digit_input)
x = Conv2D(64, (3, 3))(x)
x = MaxPooling2D((2, 2))(x)
out = Flatten()(x)vision_model = Model(digit_input, out)# Then define the tell-digits-apart model
digit_a = Input(shape=(27, 27, 1))
digit_b = Input(shape=(27, 27, 1))# The vision model will be shared, weights and all
out_a = vision_model(digit_a)
out_b = vision_model(digit_b)concatenated = keras.layers.concatenate([out_a, out_b])
out = Dense(1, activation='sigmoid')(concatenated)classification_model = Model([digit_a, digit_b], out)

视觉问答模型

在针对一幅图片使用自然语言进行提问时,该模型能够提供关于该图片的一个单词的答案

这个模型将自然语言的问题和图片分别映射为特征向量,将二者合并后训练一个logistic回归层,从一系列可能的回答中挑选一个。

from keras.layers import Conv2D, MaxPooling2D, Flatten
from keras.layers import Input, LSTM, Embedding, Dense
from keras.models import Model, Sequential# First, let's define a vision model using a Sequential model.
# This model will encode an image into a vector.
vision_model = Sequential()
vision_model.add(Conv2D(64, (3, 3), activation='relu', padding='same', input_shape=(224, 224, 3)))
vision_model.add(Conv2D(64, (3, 3), activation='relu'))
vision_model.add(MaxPooling2D((2, 2)))
vision_model.add(Conv2D(128, (3, 3), activation='relu', padding='same'))
vision_model.add(Conv2D(128, (3, 3), activation='relu'))
vision_model.add(MaxPooling2D((2, 2)))
vision_model.add(Conv2D(256, (3, 3), activation='relu', padding='same'))
vision_model.add(Conv2D(256, (3, 3), activation='relu'))
vision_model.add(Conv2D(256, (3, 3), activation='relu'))
vision_model.add(MaxPooling2D((2, 2)))
vision_model.add(Flatten())# Now let's get a tensor with the output of our vision model:
image_input = Input(shape=(224, 224, 3))
encoded_image = vision_model(image_input)# Next, let's define a language model to encode the question into a vector.
# Each question will be at most 100 word long,
# and we will index words as integers from 1 to 9999.
question_input = Input(shape=(100,), dtype='int32')
embedded_question = Embedding(input_dim=10000, output_dim=256, input_length=100)(question_input)
encoded_question = LSTM(256)(embedded_question)# Let's concatenate the question vector and the image vector:
merged = keras.layers.concatenate([encoded_question, encoded_image])# And let's train a logistic regression over 1000 words on top:
output = Dense(1000, activation='softmax')(merged)# This is our final model:
vqa_model = Model(inputs=[image_input, question_input], outputs=output)# The next stage would be training this model on actual data.

视频问答模型

在做完图片问答模型后,我们可以快速将其转为视频问答的模型。在适当的训练下,你可以为模型提供一个短视频(如100帧)然后向模型提问一个关于该视频的问题,如“what sport is the boy playing?”->“football”

from keras.layers import TimeDistributedvideo_input = Input(shape=(100, 224, 224, 3))
# This is our video encoded via the previously trained vision_model (weights are reused)
encoded_frame_sequence = TimeDistributed(vision_model)(video_input)# the output will be a sequence of vectors
encoded_video = LSTM(256)(encoded_frame_sequence)
# the output will be a vector# This is a model-level representation of the question encoder, reusing the same weights as before:
question_encoder = Model(inputs=question_input, outputs=encoded_question)# Let's use it to encode the question:
video_question_input = Input(shape=(100,), dtype='int32')
encoded_video_question = question_encoder(video_question_input)# And this is our video question answering model:
merged = keras.layers.concatenate([encoded_video, encoded_video_question])
output = Dense(1000, activation='softmax')(merged)
video_qa_model = Model(inputs=[video_input, video_question_input], outputs=output)

Keras学习笔记:函数式模型相关推荐

  1. Keras学习笔记:序列式模型

    目录: 目录: 快速开始序列(Sequential)模型 指定输入数据的shape 编译 训练 例子 用于序列分类的栈式LSTM 采用stateful LSTM的相同模型 本系列参考官方文档官方文档 ...

  2. Keras学习笔记---保存model文件和载入model文件

    Keras学习笔记---保存model文件和载入model文件 保存keras的model文件和载入keras文件的方法有很多.现在分别列出,以便后面查询. keras中的模型主要包括model和we ...

  3. 深度学习(十)keras学习笔记

    keras学习笔记 原文地址:http://blog.csdn.net/hjimce/article/details/49095199 作者:hjimce keras与torch7的使用非常相似,是最 ...

  4. CSS 学习笔记 - 盒模型

    CSS学习笔记 - 盒模型 外边距margin 内边距padding 背景background 背景图background-image 边框border 样式 宽度 颜色 圆角 边框图片border- ...

  5. 学习笔记_OSI模型

    学习笔记_OSI模型 OSI模型简介 OSI模型各层说明 OSI模型简介 OSI/RM协议由ISO(国际标准化组织)指定,功能为 给开发者提供一个通用的.必须的概念以便开发及完善:可以用来解释连接不同 ...

  6. labview学习笔记--3D模型(3)

    labview学习笔记–3D模型(3) 这次的内容是设置模型的运动–平移和旋转 1.首先,我们先找到设置平移和设置旋转的控件:程序框图->编程->图形与声音->三维图片控件-> ...

  7. TensorFlow2.0学习笔记-3.模型训练

    3.模型训练 3.1.Keras版本模型训练 • 构建模型(顺序模型.函数式模型.子类模型) • 模型训练: model.fit() • 模型验证: model.evaluate() • 模型预测:  ...

  8. 《南溪的目标检测学习笔记》——模型预处理的学习笔记

    1 介绍 在目标检测任务中,模型预处理分为两个步骤: 图像预处理:基于图像处理算法 数值预处理:基于机器学习理论 关于图像预处理,请参考<南溪的目标检测学习笔记>--图像预处理的学习笔记 ...

  9. CV学习笔记-相机模型(欧式变换及仿射变换)

    相机模型 1.相机模型原理 1. 相机成像 相机成像是一个小孔成像模型,将现实生活中的三维空间物体映射到二维的成像平面上,进而生成二维的图像. 相机模型中的坐标系: 世界坐标系Pw(Xw, Yw, Z ...

最新文章

  1. 电视机当计算机屏幕,怎么实现电视机当电脑的显示器和音箱用?
  2. 【已解决】GO语言开发中调用另一个库报错 cannot refer to unexported name XXXX
  3. 汇编: and,or逻辑运算指令
  4. 统计1000个10以内随机数随机数出现的个数
  5. Android Scrollview嵌套RecyclerView导致滑动卡顿问题解决(屡试不爽)
  6. Android 封装一个通用的PopupWindow
  7. 具有NetBeans,WebLogic 12c,JPA和MySQL数据源的Arquillian
  8. 新华三社招流程_【面试经验|校招】新华三/产品经理
  9. error: failed to push some refs to ‘github.com:English.git‘ hint: Updates w
  10. 郑州大学计算机专业本科毕业去向,河南6所高校毕业生月薪公布 :河大最高 郑大垫底...
  11. 【LeetCode】64. Minimum Path Sum
  12. [30期] 第一个项目总结-—数码黑店在这一年开张
  13. php百度地图普通ip定位,使用百度地图定位IP位置
  14. java简体字转换繁体字_java代码实现简体繁体转换
  15. 人工智能和算法,有望帮助欧洲解决头大的难民问题
  16. Google I/O 2021:在重要时刻提供帮助
  17. 文献 | 柳叶刀发文:虚拟现实的新用途之治疗场所恐惧症
  18. stm32f4定时器时钟频率/选择
  19. 不是水文 ,没有人这样教过 Spring Security 和 OAuth 2.0
  20. Unity 3D模型展示之控制标注

热门文章

  1. artificial intelligence courses
  2. 如果不知道做什么,那应该做什么呢?
  3. 在线浏览器摄像头软件!妈妈再也不用担心我的windows摄像头驱动没更新啦!
  4. SpringBoot实战之SpringBoot自动配置原理
  5. spring + angular 实现导出excel
  6. hdfs web_ui深入讲解、服务启动日志分析、NN SNN关系
  7. redis学习及实践5---redis相关资料参考文献
  8. Console-算法[]-数组求最大值和最小值(只能遍历一次)
  9. chrome默认为浏览器并且设置外部调用默认的启动参数
  10. WCF(学习笔记)【参见WCF教程】