众所周知,利用Keras-Python库可以快速、轻松地创建属于自己的深度学习的模型,今天我们就来介绍一些我们常用的API函数。
序贯模型(Sequential)API允许你为大多数问题逐层的创建模型。它的局限性在于它不允许你创建共享层或者是具有多个输入或输出的模型。
Keras中的API函数是创建更多灵活性模型的替代方法,其中也包括创建更复杂的模型。
在本篇博客中,你将发现如何在Keras中使用灵活的API函数来定义深度学习模型。
阅读完成后,你将知道:
- 连续的API和API函数之间的区别。
- 如何使用API函数定义简单的多层感知器,卷积神经网络和循环神经网络模型。
- 如何使用共享层和多个输入和输出定义更复杂的模型。
OK,让我们开始吧。
教程概述
本教程分为6部分:
- Keras序贯模型。
- Keras功能函数模型。
- 标准网络模型。
- 共享层模型。
- 多个输入和输出模型。
- ***练习。
1.Keras序贯模型
Keras提供了一个Sequential模型的API。
这是创建深度学习模型的一种方法,其中创建了Sequential类的实例,并创建了模型图层并将其添加其中。
例如,可以将层定义并传递给Sequential作为数组:
- from keras.models import Sequential
- from keras.layers import Dense
- model = Sequential([Dense(2, input_dim=1), Dense(1)])
层也可以分段添加:
- from keras.models import Sequential
- from keras.layers import Dense
- model = Sequential()
- model.add(Dense(2, input_dim=1))
- model.add(Dense(1))
序贯模型的API在大多数情况下非常适合开发深度学习模型,但也有一些限制。例如,它不能定义具有多个不同输入源的模型,因为那样会产生多个输出目标。
2.Keras功能函数模型
Keras功能API为定义模型提供了更灵活的方式。
它允许你定义多个输入或输出的模型以及可以共享图层的模型。除此之外,它还允许你定义临时的非循环网络图。
模型通过创建层的实例并将它们直接彼此成对连接来定义,然后定义一个模型,该模型的指定层作为模型的输入和输出。
我们来看看Keras功能API的三个独特方面:
2.1定义输入
与Sequential模型不同,你必须创建并定义一个独立的输入层,该层指定输入数据的形状。
输入层采用一个模型参数,它是一个代表输入数据维度的元组。
当输入数据为一维时,例如对于多层感知器,该模型必须明确留出在训练网络分割数据时所使用的小批量大小的形状。因此,模型元组始终以挂起的***一维(2)定义,例如:
- from keras.layers import Input
- visible = Input(shape=(2,))
2.2连接层
模型中的层可以成对连接,这是通过在定义每个新图层时指定输入来自哪里。使用括号符号,使得在创建图层之后,指定从当前图层的输入到即将到达的图层。
让我们用一个简单的例子来说明这一点。我们可以创建如上所述的输入层,然后创建一个隐藏层,作为仅从输入层接收输入的密集层。
- from keras.layers import Input
- from keras.layers import Dense
- visible = Input(shape=(2,))
- hidden = Dense(2)(visible)
正是通过这种连接层的方法,使功能API更具有灵活性。你可以看到开始定义ad-hoc图层的特殊图形变得多么的容易。
2.3创建模型
创建模型所需的所有图层并将其连接在一起后,接下来必须定义模型。与Sequential API一样,该模型是你可以概述、拟合、评估和使用做出预测。
Keras提供了一个Model类,你可以使用它从创建的图层时创建模型。它要求你需要指定输入和输出层。例如:
- from keras.models import Model
- from keras.layers import Input
- from keras.layers import Dense
- visible = Input(shape=(2,))
- hidden = Dense(2)(visible)
- model = Model(inputs=visible, outputs=hidden)
既然现在我们知道了Keras功能API的所有关键部分,我们通过定义一套不同的模型实践一下我们的学习成果。
以下每个示例都是可执行的,并打印结构并创建图表。我建议为你自己的模型做这个,这样可以让你清楚你的定义。
我希望这些示例可以为你在以后使用功能API定义自己的模型时提供了模板。
3.标准网络模型
当开始使用功能API时,***先了解一些关于标准神经网络模型的定义。在本节中,我们将介绍定义一个简单的多层感知器,卷积神经网络和循环神经网络。
这些例子将为以后理解更详细的例子奠定基础。
3.1多层感知器
在本节中,我们为二进制分类定义了一个多层Perceptron模型。该模型有10个输入,3个隐藏层,10个神经元,输出层有1个输出。在每个隐藏层中使用整流线性激活函数,在输出层使用S形激活函数进行二进制分类。
- # Multilayer Perceptron
- from keras.utils import plot_model
- from keras.models import Model
- from keras.layers import Input
- from keras.layers import Dense
- visible = Input(shape=(10,))
- hidden1 = Dense(10, activation='relu')(visible)
- hidden2 = Dense(20, activation='relu')(hidden1)
- hidden3 = Dense(10, activation='relu')(hidden2)
- output = Dense(1, activation='sigmoid')(hidden3)
- model = Model(inputs=visible, outputs=output)
- # summarize layers
- print(model.summary())
- # plot graph
- plot_model(model, to_file='multilayer_perceptron_graph.png')
运行示例打印网络的结构:
- _________________________________________________________________
- Layer (type) Output Shape Param #
- =================================================================
- input_1 (InputLayer) (None, 10) 0
- _________________________________________________________________
- dense_1 (Dense) (None, 10) 110
- _________________________________________________________________
- dense_2 (Dense) (None, 20) 220
- _________________________________________________________________
- dense_3 (Dense) (None, 10) 210
- _________________________________________________________________
- dense_4 (Dense) (None, 1) 11
- =================================================================
- Total params: 551
- Trainable params: 551
- Non-trainable params: 0
- _________________________________________________________________
模型图的创建并保存到文件:
3.2卷积神经网络
在本节中,我们将定义一个用于图像分类的卷积神经网络。
该模型接收黑白64×64图像作为输入,然后两个卷积层和汇集层的序列作为特征提取器,随后是完全连接的层来解释特征,并且输出层是具有S形激活函数。
- # Convolutional Neural Network
- from keras.utils import plot_model
- from keras.models import Model
- from keras.layers import Input
- from keras.layers import Dense
- from keras.layers.convolutional import Conv2D
- from keras.layers.pooling import MaxPooling2D
- visible = Input(shape=(64,64,1))
- conv1 = Conv2D(32, kernel_size=4, activation='relu')(visible)
- pool1 = MaxPooling2D(pool_size=(2, 2))(conv1)
- conv2 = Conv2D(16, kernel_size=4, activation='relu')(pool1)
- pool2 = MaxPooling2D(pool_size=(2, 2))(conv2)
- hidden1 = Dense(10, activation='relu')(pool2)
- output = Dense(1, activation='sigmoid')(hidden1)
- model = Model(inputs=visible, outputs=output)
- # summarize layers
- print(model.summary())
- # plot graph
- plot_model(model, to_file='convolutional_neural_network.png')
运行示例:
- _________________________________________________________________
- Layer (type) Output Shape Param #
- =================================================================
- input_1 (InputLayer) (None, 64, 64, 1) 0
- ••••••
- Total params: 8,933
- Trainable params: 8,933
- Non-trainable params: 0
- ________________________________________________________________
模型图的图创建并保存到文件:
3.3循环神经网络
在本节中,我们将定义一个LSTM循环神经网络用于序列分类。
该模型是100个时间步长作为输入,该模型具有单个LSTM隐藏层,用于从序列中提取特征,然后是完全连接的层以解释LSTM输出,随后是用于进行二进制预测的输出层。
- # Recurrent Neural Network
- from keras.utils import plot_model
- from keras.models import Model
- from keras.layers import Input
- from keras.layers import Dense
- from keras.layers.recurrent import LSTM
- visible = Input(shape=(100,1))
- hidden1 = LSTM(10)(visible)
- hidden2 = Dense(10, activation='relu')(hidden1)
- output = Dense(1, activation='sigmoid')(hidden2)
- model = Model(inputs=visible, outputs=output)
- # summarize layers
- print(model.summary())
- # plot graph
- plot_model(model, to_file='recurrent_neural_network.png')
运行示例总结模型层。
- _________________________________________________________________
- Layer (type) Output Shape Param #
- =================================================================
- •••••••
- =================================================================
- Total params: 601
- Trainable params: 601
- Non-trainable params: 0
- _________________________________________________________________
模型图的创建并保存到文件:
4.共享层模型
多层可以共享一层的输出。
例如,可能存在来自输入的多个不同的特征提取层,或者用于解释特征提取层输出的多个层。
我们来看看这两个例子。
4.1共享输入层
在本节中,我们使用不同大小的内核定义多个卷积层来解释图像输入。
该模型输入采用大小为64×64像素的黑白图像。有两个CNN特征提取子模型共享该输入:***个内核大小为4,第二个内核大小为8。这些特征提取子模型的输出被平坦化为向量,并连接成一个长向量,并传递到完全连接的层,以便在最终输出层之前进行二进制分类。
- # Shared Input Layer
- from keras.utils import plot_model
- from keras.models import Model
- from keras.layers import Input
- from keras.layers import Dense
- from keras.layers import Flatten
- from keras.layers.convolutional import Conv2D
- from keras.layers.pooling import MaxPooling2D
- from keras.layers.merge import concatenate
- # input layer
- visible = Input(shape=(64,64,1))
- # first feature extractor
- conv1 = Conv2D(32, kernel_size=4, activation='relu')(visible)
- pool1 = MaxPooling2D(pool_size=(2, 2))(conv1)
- flat1 = Flatten()(pool1)
- # second feature extractor
- conv2 = Conv2D(16, kernel_size=8, activation='relu')(visible)
- pool2 = MaxPooling2D(pool_size=(2, 2))(conv2)
- flat2 = Flatten()(pool2)
- # merge feature extractors
- merge = concatenate([flat1, flat2])
- # interpretation layer
- hidden1 = Dense(10, activation='relu')(merge)
- # prediction output
- output = Dense(1, activation='sigmoid')(hidden1)
- model = Model(inputs=visible, outputs=output)
- # summarize layers
- print(model.summary())
- # plot graph
- plot_model(model, to_file='shared_input_layer.png')
运行示例总结模型层。
- ___________________________________________________________________
- Layer (type) Output Shape Param # Connected to
- ===================================================================
- •••••••••••••••••••••••
- Total params: 415,045
- Trainable params: 415,045
- Non-trainable params: 0
- ___________________________________________________________________
模型图的被创建并保存到文件:
4.2共享特征提取层
在本节中,我们使用两个并行子模型解释LSTM特征提取器的输出以进行序列分类。
模型的输入是一个特征为100的时间步长,具有10个存储单元的LSTM层解释该序列。***种解释模式是浅层的单层完全连接层,第二种是深层的3层模型。两个解释模型的输出都被连接成一个长向量,传递给用于进行二进制预测的输出层。
- # Shared Feature Extraction Layer
- from keras.utils import plot_model
- from keras.models import Model
- from keras.layers import Input
- from keras.layers import Dense
- from keras.layers.recurrent import LSTM
- from keras.layers.merge import concatenate
- # define input
- visible = Input(shape=(100,1))
- # feature extraction
- extract1 = LSTM(10)(visible)
- # first interpretation model
- interp1 = Dense(10, activation='relu')(extract1)
- # second interpretation model
- interp11 = Dense(10, activation='relu')(extract1)
- interp12 = Dense(20, activation='relu')(interp11)
- interp13 = Dense(10, activation='relu')(interp12)
- # merge interpretation
- merge = concatenate([interp1, interp13])
- # output
- output = Dense(1, activation='sigmoid')(merge)
- model = Model(inputs=visible, outputs=output)
- # summarize layers
- print(model.summary())
- # plot graph
- plot_model(model, to_file='shared_feature_extractor.png')
运行示例总结模型层。
- ___________________________________________________________________
- Layer (type) Output Shape Param # Connected to
- •••••••
- Total params: 1,151
- Trainable params: 1,151
- Non-trainable params: 0
- ___________________________________________________________________
模型图被创建并保存到文件。
5.多个输入和输出模型
功能API也可用于开发具有多个输入的更复杂的模型,可能具有不同的模态。它也可以用于开发产生多个输出的模型。
我们将在本节中查看每个示例。
5.1多输入模型
我们将开发一个图像分类模型,它将两个版本的图像作为输入,每个版本的大小不同。具体是黑白64×64版,彩色32×32版。单独的特征提取CNN模型在每个模型上运行,然后将两个模型的结果连接起来进行解释和最终预测。
请注意,在创建Model()实例时,我们将两个输入图层定义为数组。
- model = Model(inputs=[visible1, visible2], outputs=output)
完整的示例如下所示。
- # Multiple Inputs
- from keras.utils import plot_model
- from keras.models import Model
- from keras.layers import Input
- from keras.layers import Dense
- from keras.layers import Flatten
- from keras.layers.convolutional import Conv2D
- from keras.layers.pooling import MaxPooling2D
- from keras.layers.merge import concatenate
- # first input model
- visible1 = Input(shape=(64,64,1))
- conv11 = Conv2D(32, kernel_size=4, activation='relu')(visible1)
- pool11 = MaxPooling2D(pool_size=(2, 2))(conv11)
- conv12 = Conv2D(16, kernel_size=4, activation='relu')(pool11)
- pool12 = MaxPooling2D(pool_size=(2, 2))(conv12)
- flat1 = Flatten()(pool12)
- # second input model
- visible2 = Input(shape=(32,32,3))
- conv21 = Conv2D(32, kernel_size=4, activation='relu')(visible2)
- pool21 = MaxPooling2D(pool_size=(2, 2))(conv21)
- conv22 = Conv2D(16, kernel_size=4, activation='relu')(pool21)
- pool22 = MaxPooling2D(pool_size=(2, 2))(conv22)
- flat2 = Flatten()(pool22)
- # merge input models
- merge = concatenate([flat1, flat2])
- # interpretation model
- hidden1 = Dense(10, activation='relu')(merge)
- hidden2 = Dense(10, activation='relu')(hidden1)
- output = Dense(1, activation='sigmoid')(hidden2)
- model = Model(inputs=[visible1, visible2], outputs=output)
- # summarize layers
- print(model.summary())
- # plot graph
- plot_model(model, to_file='multiple_inputs.png')
运行示例:
- ___________________________________________________________________
- Layer (type) Output Shape Param # Connected to
- •••••••••
- input_1 (InputLayer) (None, 64, 64, 1) 0
- Total params: 49,699
- Trainable params: 49,699
- Non-trainable params: 0
- ___________________________________________________________________
模型图被创建并保存到文件。
5.2多输出模型
在本节中,我们将开发出一种可以进行两种不同类型预测的模型。给定一个特征的100个时间步长的输入序列,该模型将对序列进行分类并输出具有相同长度的新序列。
LSTM层解释输入序列,并返回每个时间步长的隐藏状态。***个输出模型创建一个堆栈的LSTM,解释特征,并进行二进制预测。第二个输出模型使用相同的输出层对每个输入时间步长进行实值预测。
- # Multiple Outputs
- from keras.utils import plot_model
- from keras.models import Model
- from keras.layers import Input
- from keras.layers import Dense
- from keras.layers.recurrent import LSTM
- from keras.layers.wrappers import TimeDistributed
- # input layer
- visible = Input(shape=(100,1))
- # feature extraction
- extract = LSTM(10, return_sequences=True)(visible)
- # classification output
- class11 = LSTM(10)(extract)
- class12 = Dense(10, activation='relu')(class11)
- output1 = Dense(1, activation='sigmoid')(class12)
- # sequence output
- output2 = TimeDistributed(Dense(1, activation='linear'))(extract)
- # output
- model = Model(inputs=visible, outputs=[output1, output2])
- # summarize layers
- print(model.summary())
- # plot graph
- plot_model(model, to_file='multiple_outputs.png')
运行示例。
- ___________________________________________________________________
- Layer (type) Output Shape Param # Connected to
- ===================================================================
- input_1 (InputLayer) (None, 100, 1) 0
- ___________________________________________________________________
- ········
- Total params: 1,452
- Trainable params: 1,452
- Non-trainable params: 0
- ___________________________________________________________________
模型图的创建并保存到文件:
6.***做法
在本节中,我给你一些提示,以便在定义自己的模型时充分利用功能性API。
- 一致的变量名。对输入(可见)和输出层(输出)使用相同的变量名称,甚至可以使用隐藏层(hidden1,hidden2)。它将有助于正确地将事物联系起来。
- 查看图层图。始终打印模型摘要并查看图层输出,以确保模型按预期连接在一起。
- 查看图表。创建一个模型图的情节,并检查它,以确保所有的东西都按照你的意图放在一起。
- 命名图层。你可以为查看模型图的名称和绘图时使用的图层分配名称。例如:Dense(1,name =’hidden1’)。
- 单独的子模型。考虑分开子模型的发展,并将子模型结合在一起。