Keras Python 库使创建深度学习模型快速而简单。
顺序式 API 允许您为大多数问题逐层创建模型。它的局限性在于不允许您创建共享层或具有多个输入或输出的模型。
Keras 中的函数式 API 是创建模型的另一种方式,它提供了更大的灵活性,包括创建更复杂的模型。
在本教程中,您将学习如何使用 Keras 中更灵活的函数式 API 来定义深度学习模型。
完成本教程后,您将了解:
- 顺序式 API 和函数式 API 之间的区别。
- 如何使用函数式 API 定义简单的多层感知器、卷积神经网络和循环神经网络模型。
- 如何定义具有共享层和多个输入和输出的更复杂模型。
通过我的新书《使用 Python 进行深度学习》启动您的项目,其中包括逐步教程和所有示例的 Python 源代码文件。
让我们开始吧。
- 2017 年 11 月更新:添加了关于输入层悬空维度的说明。
- 2018 年 11 月更新:添加了 CNN 缺少展平层,感谢 Konstantin。
- 2018 年 11 月更新:添加了函数式 API Python 语法的描述。
教程概述
本教程分为7个部分;它们是:
- Keras 顺序模型
- Keras 函数式模型
- 标准网络模型
- 共享层模型
- 多输入多输出模型
- 最佳实践
- 新功能:关于函数式 API Python 语法的说明
1. Keras 顺序模型
回顾一下,Keras 提供了一个顺序模型 API。
如果您是Keras或深度学习的新手,请参阅此分步Keras教程。
顺序模型 API 是一种创建深度学习模型的方式,其中创建了 Sequential 类的实例,并向其添加模型层。
例如,可以定义层并将其作为数组传递给 Sequential
1 2 3 |
from keras.models import Sequential from keras.layers import Dense model = Sequential([Dense(2, input_dim=1), Dense(1)]) |
层也可以分段添加
1 2 3 4 5 |
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 提供了一种更灵活的模型定义方式。
它特别允许您定义多输入或多输出模型以及共享层的模型。更重要的是,它允许您定义特设的非循环网络图。
模型通过创建层实例并将其成对直接连接,然后定义一个 Model 来指定作为模型输入和输出的层来定义。
我们依次看看 Keras 函数式 API 的三个独特方面
1. 定义输入
与顺序模型不同,您必须创建并定义一个独立的输入层,该层指定输入数据的形状。
输入层接受一个形状参数,它是一个元组,指示输入数据的维度。
当输入数据是一维时(例如多层感知器),形状必须明确为训练网络时用于拆分数据的 mini-batch 大小留出空间。因此,当输入是一维时(例如 (2,)),形状元组总是定义为悬空的最后一个维度。
1 2 |
from keras.layers import Input visible = Input(shape=(2,)) |
2. 连接层
模型中的层成对连接。
这是通过在定义每个新层时指定输入来源来完成的。使用括号表示法,即在创建层之后,指定当前层的输入来自哪个层。
让我们通过一个简短的例子来阐明这一点。我们可以像上面那样创建输入层,然后创建一个隐藏层作为 Dense 层,它只接收来自输入层的输入。
1 2 3 4 |
from keras.layers import Input from keras.layers import Dense visible = Input(shape=(2,)) hidden = Dense(2)(visible) |
请注意在创建 Dense 层之后 (visible) 将输入层输出作为 Dense 隐藏层的输入进行连接。
正是这种逐层连接的方式赋予了函数式 API 灵活性。例如,您可以看到开始定义即时层图是多么容易。
3. 创建模型
创建所有模型层并将它们连接在一起后,您必须定义模型。
与顺序式 API 一样,模型是您可以总结、拟合、评估和用于进行预测的东西。
Keras 提供了一个 Model 类,您可以使用它从您创建的层创建模型。它要求您只指定输入和输出层。例如:
1 2 3 4 5 6 |
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 时,最好看看一些标准神经网络模型是如何定义的。
在本节中,我们将介绍如何定义简单的多层感知器、卷积神经网络和循环神经网络。
这些示例将为理解后面更复杂的示例奠定基础。
多层感知器
在本节中,我们为二元分类定义一个多层感知器模型。
该模型有 10 个输入,3 个隐藏层,分别有 10、20 和 10 个神经元,以及一个有 1 个输出的输出层。每个隐藏层使用修正线性激活函数,输出层使用 sigmoid 激活函数进行二元分类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
# 多层感知器 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) # 总结层 print(model.summary()) # 绘制图 plot_model(model, to_file='multilayer_perceptron_graph.png') |
运行示例会打印网络的结构。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
_________________________________________________________________ 层(类型) 输出形状 参数数量 ================================================================= 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 ================================================================= 总参数:551 可训练参数:551 不可训练参数: 0 _________________________________________________________________ |
模型图的绘图也已创建并保存到文件中。

多层感知器网络图
卷积神经网络
在本节中,我们将定义一个用于图像分类的卷积神经网络。
该模型接收黑白 64×64 图像作为输入,然后包含两个卷积和 池化层 的序列作为特征提取器,随后是一个全连接层来解释特征,以及一个带有 sigmoid 激活的输出层用于两类预测。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# 卷积神经网络 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 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) flat = Flatten()(pool2) hidden1 = Dense(10, activation='relu')(flat) output = Dense(1, activation='sigmoid')(hidden1) model = Model(inputs=visible, outputs=output) # 总结层 print(model.summary()) # 绘制图 plot_model(model, to_file='convolutional_neural_network.png') |
运行示例会总结模型层。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
_________________________________________________________________ 层 (类型) 输出形状 参数数量 ================================================================= input_1 (InputLayer) (None, 64, 64, 1) 0 _________________________________________________________________ conv2d_1 (Conv2D) (None, 61, 61, 32) 544 _________________________________________________________________ max_pooling2d_1 (MaxPooling2 (None, 30, 30, 32) 0 _________________________________________________________________ conv2d_2 (Conv2D) (None, 27, 27, 16) 8208 _________________________________________________________________ max_pooling2d_2 (MaxPooling2 (None, 13, 13, 16) 0 _________________________________________________________________ flatten_1 (Flatten) (None, 2704) 0 _________________________________________________________________ dense_1 (Dense) (None, 10) 27050 _________________________________________________________________ dense_2 (Dense) (None, 1) 11 ================================================================= 总参数:35,813 可训练参数:35,813 不可训练参数: 0 _________________________________________________________________ |
模型图的绘图也已创建并保存到文件中。

卷积神经网络图
循环神经网络
在本节中,我们将定义一个长短期记忆循环神经网络用于序列分类。
该模型期望 100 个时间步长,每个时间步长具有一个特征作为输入。该模型有一个单个 LSTM 隐藏层来从序列中提取特征,然后是一个全连接层来解释 LSTM 输出,再然后是一个输出层用于进行二元预测。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
# 循环神经网络 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) # 总结层 print(model.summary()) # 绘制图 plot_model(model, to_file='recurrent_neural_network.png') |
运行示例会总结模型层。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
_________________________________________________________________ 层(类型) 输出形状 参数数量 ================================================================= input_1 (InputLayer) (None, 100, 1) 0 _________________________________________________________________ lstm_1 (LSTM) (None, 10) 480 _________________________________________________________________ dense_1 (Dense) (None, 10) 110 _________________________________________________________________ dense_2 (Dense) (None, 1) 11 ================================================================= 总参数:601 可训练参数:601 不可训练参数: 0 _________________________________________________________________ |
模型图的绘图也已创建并保存到文件中。

循环神经网络图
4. 共享层模型
多个层可以共享一个层的输出。
例如,一个输入可能存在多个不同的特征提取层,或者多个层用于解释特征提取层的输出。
我们来看这两个例子。
共享输入层
在本节中,我们定义了多个具有不同大小内核的卷积层来解释图像输入。
该模型接收大小为 64x64 像素的黑白图像。有两个 CNN 特征提取子模型共享此输入;第一个的内核大小为 4,第二个的内核大小为 8。这些特征提取子模型的输出被展平为向量并连接成一个长向量,然后传递给一个全连接层进行解释,最后由一个输出层进行二元分类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
# 共享输入层 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 # 输入层 visible = Input(shape=(64,64,1)) # 第一个特征提取器 conv1 = Conv2D(32, kernel_size=4, activation='relu')(visible) pool1 = MaxPooling2D(pool_size=(2, 2))(conv1) flat1 = Flatten()(pool1) # 第二个特征提取器 conv2 = Conv2D(16, kernel_size=8, activation='relu')(visible) pool2 = MaxPooling2D(pool_size=(2, 2))(conv2) flat2 = Flatten()(pool2) # 合并特征提取器 merge = concatenate([flat1, flat2]) # 解释层 hidden1 = Dense(10, activation='relu')(merge) # 预测输出 output = Dense(1, activation='sigmoid')(hidden1) model = Model(inputs=visible, outputs=output) # 总结层 print(model.summary()) # 绘制图 plot_model(model, to_file='shared_input_layer.png') |
运行示例会总结模型层。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
____________________________________________________________________________________________________ 层 (类型) 输出形状 参数数量 连接到 ==================================================================================================== input_1 (InputLayer) (None, 64, 64, 1) 0 ____________________________________________________________________________________________________ conv2d_1 (Conv2D) (None, 61, 61, 32) 544 input_1[0][0] ____________________________________________________________________________________________________ conv2d_2 (Conv2D) (None, 57, 57, 16) 1040 input_1[0][0] ____________________________________________________________________________________________________ max_pooling2d_1 (MaxPooling2D) (None, 30, 30, 32) 0 conv2d_1[0][0] ____________________________________________________________________________________________________ max_pooling2d_2 (MaxPooling2D) (None, 28, 28, 16) 0 conv2d_2[0][0] ____________________________________________________________________________________________________ flatten_1 (Flatten) (None, 28800) 0 max_pooling2d_1[0][0] ____________________________________________________________________________________________________ flatten_2 (Flatten) (None, 12544) 0 max_pooling2d_2[0][0] ____________________________________________________________________________________________________ concatenate_1 (Concatenate) (None, 41344) 0 flatten_1[0][0] flatten_2[0][0] ____________________________________________________________________________________________________ dense_1 (Dense) (None, 10) 413450 concatenate_1[0][0] ____________________________________________________________________________________________________ dense_2 (Dense) (None, 1) 11 dense_1[0][0] ==================================================================================================== 总参数:415,045 可训练参数:415,045 不可训练参数: 0 ____________________________________________________________________________________________________ |
模型图的绘图也已创建并保存到文件中。

具有共享输入的神经网络图
共享特征提取层
在本节中,我们将使用两个并行子模型来解释 LSTM 特征提取器的输出,用于序列分类。
模型的输入是 100 个时间步长,每个时间步长具有 1 个特征。一个具有 10 个记忆单元的 LSTM 层解释此序列。第一个解释模型是一个浅层单全连接层,第二个是一个深度 3 层模型。两个解释模型的输出被连接成一个长向量,该向量传递给用于进行二元预测的输出层。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
# 共享特征提取层 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 # 定义输入 visible = Input(shape=(100,1)) # 特征提取 extract1 = LSTM(10)(visible) # 第一个解释模型 interp1 = Dense(10, activation='relu')(extract1) # 第二个解释模型 interp11 = Dense(10, activation='relu')(extract1) interp12 = Dense(20, activation='relu')(interp11) interp13 = Dense(10, activation='relu')(interp12) # 合并解释 merge = concatenate([interp1, interp13]) # output output = Dense(1, activation='sigmoid')(merge) model = Model(inputs=visible, outputs=output) # 总结层 print(model.summary()) # 绘制图 plot_model(model, to_file='shared_feature_extractor.png') |
运行示例会总结模型层。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
____________________________________________________________________________________________________ 层 (类型) 输出形状 参数数量 连接到 ==================================================================================================== input_1 (InputLayer) (None, 100, 1) 0 ____________________________________________________________________________________________________ lstm_1 (LSTM) (None, 10) 480 input_1[0][0] ____________________________________________________________________________________________________ dense_2 (Dense) (None, 10) 110 lstm_1[0][0] ____________________________________________________________________________________________________ dense_3 (Dense) (None, 20) 220 dense_2[0][0] ____________________________________________________________________________________________________ dense_1 (Dense) (None, 10) 110 lstm_1[0][0] ____________________________________________________________________________________________________ dense_4 (Dense) (None, 10) 210 dense_3[0][0] ____________________________________________________________________________________________________ concatenate_1 (Concatenate) (None, 20) 0 dense_1[0][0] dense_4[0][0] ____________________________________________________________________________________________________ dense_5 (Dense) (None, 1) 21 concatenate_1[0][0] ==================================================================================================== 总参数:1,151 可训练参数:1,151 不可训练参数: 0 ____________________________________________________________________________________________________ |
模型图的绘图也已创建并保存到文件中。

带共享特征提取层的神经网络图
5. 多输入多输出模型
函数式 API 也可用于开发具有多输入(可能具有不同模态)的更复杂模型。它还可用于开发生成多输出的模型。
我们将在本节中分别介绍这些示例。
多输入模型
我们将开发一个图像分类模型,它以两个不同尺寸的图像版本作为输入。具体来说,一个是黑白 64×64 版本,另一个是彩色 32×32 版本。独立的特征提取 CNN 模型分别对每个版本进行操作,然后将两个模型的结果连接起来进行解释和最终预测。
请注意,在创建 Model() 实例时,我们将两个输入层定义为一个数组。具体如下:
1 |
model = Model(inputs=[visible1, visible2], outputs=output) |
完整的示例如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# 多个输入 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 # 第一个输入模型 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) # 第二个输入模型 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 = concatenate([flat1, flat2]) # 解释模型 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) # 总结层 print(model.summary()) # 绘制图 plot_model(model, to_file='multiple_inputs.png') |
运行示例会总结模型层。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
____________________________________________________________________________________________________ 层 (类型) 输出形状 参数数量 连接到 ==================================================================================================== input_1 (InputLayer) (None, 64, 64, 1) 0 ____________________________________________________________________________________________________ input_2 (InputLayer) (None, 32, 32, 3) 0 ____________________________________________________________________________________________________ conv2d_1 (Conv2D) (None, 61, 61, 32) 544 input_1[0][0] ____________________________________________________________________________________________________ conv2d_3 (Conv2D) (None, 29, 29, 32) 1568 input_2[0][0] ____________________________________________________________________________________________________ max_pooling2d_1 (MaxPooling2D) (None, 30, 30, 32) 0 conv2d_1[0][0] ____________________________________________________________________________________________________ max_pooling2d_3 (MaxPooling2D) (None, 14, 14, 32) 0 conv2d_3[0][0] ____________________________________________________________________________________________________ conv2d_2 (Conv2D) (None, 27, 27, 16) 8208 max_pooling2d_1[0][0] ____________________________________________________________________________________________________ conv2d_4 (Conv2D) (None, 11, 11, 16) 8208 max_pooling2d_3[0][0] ____________________________________________________________________________________________________ max_pooling2d_2 (MaxPooling2D) (None, 13, 13, 16) 0 conv2d_2[0][0] ____________________________________________________________________________________________________ max_pooling2d_4 (MaxPooling2D) (None, 5, 5, 16) 0 conv2d_4[0][0] ____________________________________________________________________________________________________ flatten_1 (Flatten) (None, 2704) 0 max_pooling2d_2[0][0] ____________________________________________________________________________________________________ flatten_2 (Flatten) (None, 400) 0 max_pooling2d_4[0][0] ____________________________________________________________________________________________________ concatenate_1 (Concatenate) (None, 3104) 0 flatten_1[0][0] flatten_2[0][0] ____________________________________________________________________________________________________ dense_1 (Dense) (None, 10) 31050 concatenate_1[0][0] ____________________________________________________________________________________________________ dense_2 (Dense) (None, 10) 110 dense_1[0][0] ____________________________________________________________________________________________________ dense_3 (Dense) (None, 1) 11 dense_2[0][0] ==================================================================================================== 总参数:49,699 可训练参数:49,699 不可训练参数: 0 ____________________________________________________________________________________________________ |
模型图的绘图也已创建并保存到文件中。

带多个输入的神经网络图
多输出模型
在本节中,我们将开发一个模型,该模型能够进行两种不同类型的预测。给定一个包含 100 个时间步长的一个特征的输入序列,该模型将同时对序列进行分类,并输出一个长度相同的新序列。
一个 LSTM 层解释输入序列并返回每个时间步长的隐藏状态。第一个输出模型创建一个堆叠的 LSTM,解释特征,并进行二元预测。第二个输出模型使用相同的输出层对每个输入时间步长进行实值预测。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# 多个输出 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 # 输入层 visible = Input(shape=(100,1)) # 特征提取 extract = LSTM(10, return_sequences=True)(visible) # 分类输出 class11 = LSTM(10)(extract) class12 = Dense(10, activation='relu')(class11) output1 = Dense(1, activation='sigmoid')(class12) # 序列输出 output2 = TimeDistributed(Dense(1, activation='linear'))(extract) # output model = Model(inputs=visible, outputs=[output1, output2]) # 总结层 print(model.summary()) # 绘制图 plot_model(model, to_file='multiple_outputs.png') |
运行示例会总结模型层。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
____________________________________________________________________________________________________ 层 (类型) 输出形状 参数数量 连接到 ==================================================================================================== input_1 (InputLayer) (None, 100, 1) 0 ____________________________________________________________________________________________________ lstm_1 (LSTM) (None, 100, 10) 480 input_1[0][0] ____________________________________________________________________________________________________ lstm_2 (LSTM) (None, 10) 840 lstm_1[0][0] ____________________________________________________________________________________________________ dense_1 (Dense) (None, 10) 110 lstm_2[0][0] ____________________________________________________________________________________________________ dense_2 (Dense) (None, 1) 11 dense_1[0][0] ____________________________________________________________________________________________________ time_distributed_1 (TimeDistribu (None, 100, 1) 11 lstm_1[0][0] ==================================================================================================== 总参数:1,452 可训练参数:1,452 不可训练参数: 0 ____________________________________________________________________________________________________ |
模型图的绘图也已创建并保存到文件中。

带多个输出的神经网络图
6. 最佳实践
在本节中,我将为您提供一些技巧,帮助您在定义自己的模型时最大限度地利用函数式 API。
- 一致的变量名。对输入层(visible)和输出层(output)使用相同的变量名,甚至可以对隐藏层(hidden1、hidden2)也使用相同的变量名。这将有助于正确地连接各个部分。
- 审查层摘要。始终打印模型摘要并审查层输出,以确保模型按照您的预期连接在一起。
- 审查图表。始终创建模型图表并审查它,以确保所有部分都按照您的意图组合在一起。
- 命名层。您可以为层分配名称,这些名称将在审查模型图的摘要和图表时使用。例如:Dense(1, name='hidden1')。
- 分离子模型。考虑分离子模型的开发,并在最后将子模型组合在一起。
在使用函数式 API 时,您有什么自己的最佳实践技巧吗?
请在评论中告诉我。
7. 函数式 API Python 语法说明
如果您是 Python 新手或刚接触 Python,函数式 API 中使用的语法可能会让您感到困惑。
例如,给定
1 2 3 |
... dense1 = Dense(32)(input) ... |
双括号语法有什么作用?
这意味着什么?
它看起来令人困惑,但它不是一个特殊的 Python 特性,只是一行代码做了两件事。
第一个括号“(32)”通过类构造函数创建层,第二个括号“(input)”是一个通过 __call__() 函数实现的无名函数,当调用时将连接层。
__call__() 函数是所有 Python 对象上的默认函数,可以被重写,用于“调用”一个实例化对象。就像 __init__() 函数是所有对象上的默认函数,在实例化对象后立即调用以初始化它一样。
我们可以在两行代码中完成同样的事情
1 2 3 4 |
# 创建层 dense1 = Dense(32) # 将层连接到前一层 dense1(input) |
我想我们也可以显式地调用对象的 __call__() 函数,尽管我从未尝试过
1 2 3 4 |
# 创建层 dense1 = Dense(32) # 将层连接到前一层 dense1.__call_(input) |
进一步阅读
如果您想深入了解此主题,本节提供了更多资源。
总结
在本教程中,您学习了如何使用 Keras 中的函数式 API 来定义简单和复杂的深度学习模型。
具体来说,你学到了:
- 顺序式 API 和函数式 API 之间的区别。
- 如何使用函数式 API 定义简单的多层感知器、卷积神经网络和循环神经网络模型。
- 如何定义具有共享层和多个输入和输出的更复杂模型。
你有什么问题吗?
在下面的评论中提出你的问题,我会尽力回答。
谢谢你
我一直在等待这个教程
谢谢,希望它有所帮助!
我正在使用 keras API,我正在使用带有 2 个输入和 1 个输出的共享层,并且在 fit 模型方面遇到了问题
model.fit([train_images1, train_images2],
batch_size=batch_size,
epochs=epochs,
validation_data=([test_images1, test_images2]))
我收到此错误
ValueError: 检查模型输入时出错:您传递给模型的 Numpy 数组列表的大小不是模型预期的大小。预期看到 2 个数组,但却得到了以下包含 1 个数组的列表:[array([[[[0.2 , 0.5019608 , 0.8862745 , …, 0.5686275 ,
0.5137255 , 0.59607846],
[0.24705882, 0.3529412 , 0.31764707, …, 0.5803922 ,
0.57254905, 0.6 ],
也许可以仔细检查数据是否具有每个模型头部预期的形状。
你修好了吗?
您没有在 fit 方法中提供输出,这就是它要求 2 个 numpy 数组的原因。
Fathi,你修好了吗??
Jason 你太棒了!
我迫不及待地想看到你在这个精彩的博客上发表更多内容,你把所有这些都藏在哪里了 😉
你能写一本书,在书中实现更多函数式 API 吗?
我确信这本书会大获成功
此致
Thabet
我同意 Thabet Ali 的观点,需要一本关于高级函数式 API 部分的书。
Tom,函数式 API 的哪些方面你需要更多帮助?
谢谢!
函数式 API 给你带来了什么问题?
我想了解更多关于如何使用函数式 API 在多输入时间序列信号上实现自动编码器,并进行单输出分类。
谢谢。
例如,LSTMs 可以直接处理多个时间序列,不需要并行的输入模型。
你为什么要将自动编码器用于时间序列?
是的,我想这是因为输出序列比输入序列短
就像在这个数据集中看到的
https://archive.ics.uci.edu/ml/datasets/human+activity+recognition+using+smartphones
其中有三个时间序列输入和 5 个不同的输出类别
嗨,Jason,你是在征求心愿单吗? 🙂
– 使用 Keras API 进行自动编码器 / 异常检测
谢谢!
感谢您的建议!
是的,完全同意。
Jason,感谢您非常有趣的博客。一篇美丽的帖子,可以打开新的大门。
谢谢亚历山大。
Brownlee 博士,
你是如何学习这么多算法背后的数学知识的?
致敬
Leon
我读了很多书 🙂
我能否将 LSTM 层的 initial_state 视为架构的输入分支?假设对于每个数据,我有一个序列 s1、s2、s3 和一个上下文特征 X。我定义了一个具有 128 个神经元的 LSTM,对于每个批次,我想通过 Dense(128) 层将 X 映射到 128 维特征,并为该批次训练设置 initial_state,同时将序列 s1、s2、s3 作为输入序列馈送到 LSTM。
抱歉 Alex,我不太明白。如果你有什么想法,也许可以设计一个实验来测试它们?
感谢您精彩的教程。
对于任何想要直接在 Jupyter Notebook 中可视化的人,请使用以下行。
from IPython.display import SVG
from keras.utils.vis_utils import model_to_dot
SVG(model_to_dot(model).create(prog=’dot’, format=’svg’))
太棒了,谢谢你的提示!
感谢这个博客。它真的很有帮助,而且解释得很清楚。
谢谢 Luis,很高兴听到这个消息。感谢您的支持!
嗨,Jason – 我想知道代码是否应该是
visible = Input(image_file, shape=( height, width, color channels))
如果不是,我想知道代码如何引用问题中的图像……
很惊讶没有人问这个……
JASON 你真棒!
在第 1 节中,您写道“形状元组总是定义一个悬空的最后一个维度”,但是当您定义卷积网络时,您将其定义为
visible = Input(shape=(64,64,1))
没有任何悬空的最后一个维度。我是不是漏掉了什么?
是的,我错了。这只适用于一维输入。我已经更新了帖子,谢谢。
你还是错了。即使是一维输入,也没有“悬空的最后一个维度”。这是一个 Python 用来区分 0 元组或 1 元组与括号的“尾随逗号”。
谢谢您的留言。
Jason,我读 Keras 和 AI 已经有一段时间了,我总是觉得你的文章比网上的其他内容更清晰、更直接 🙂
谢谢!
谢谢 Franek。
Jason,出于某种原因,我需要知道模型中层的输出张量。我尝试按照 Keras 文档尝试使用 layer.get_output、get_output_et 等,但我总是无法得到任何合理的结果。
我试图在您的博客上寻找这个主题,但没有找到任何内容。您打算写一篇关于这个的帖子吗? 🙂 那真的很有帮助!
抱歉,我没有关于获取输出张量的好建议。也许可以发布到 Keras Google 群组或 Slack 频道?
请看这里
https://machinelearning.org.cn/get-help-with-keras/
嗨,Jason,又一篇很棒的帖子。
我使用您过去的一篇文章创建了一个 LSTM,它使用多个时间序列,预测特定时间序列的多个步骤。目前我有这个结构
其中
– x_tr 的维度为 (440, 7, 6)(440 个样本,7 个过去时间步,6 个变量/时间序列)
– y_tr 的维度为 (440, 21),即 440 个样本和 21 个提前预测值。
现在,我想扩展我的网络,使其预测两个时间序列的(多步提前)值。我尝试了以下代码:
其中 y1 和 y2 的维度均为 (440, 21),但我遇到了这个错误:
“检查目标时出错:预期 dense_4 具有 3 个维度,但得到的数组形状为 (440, 21)”。
我应该如何重塑 y1 和 y2 以使其适应网络?
抱歉,我无法为您调试代码,或许您可以发布到 Stack Overflow 上?
查看关于 LSTM 的文章,这将有很大帮助。输出序列的维度必须为 n,2,21;即 n 个数据,2 个时间步和 21 个变量。
Y.reshape( (440/2),2,21)
x 维度已经就位,将 y 维度更改为 3 个维度。样本数、时间步、变量
很棒的教程,它真的帮助我更好地理解了 Model API!谢谢!
很高兴听到这个消息。
嗨 Jason,这是一篇很棒的帖子,特别适合初学者学习函数式 API。您介意写一篇帖子,一步一步地为初学者解释图像分割问题的代码吗?
感谢您的建议。
嗨 Jason,感谢您如此精彩的帖子。它极大地帮助我理解了 Keras 中的函数式 API。
您能否解释一下在多输出情况下,每个子模型都有不同的目标函数时,我们如何定义 model.compile 语句。例如,一个输出可能是回归,另一个是分类,就像您在这篇帖子中提到的那样。
我相信您必须为整个模型设置一个目标函数。
一如既往的精彩教程!
您认为将来可以制作关于 Siamese 神经网络的教程吗?特别有趣的是,如何在 Keras 中创建三元组损失模型,例如识别面部。函数式 API 肯定是可行的方法,但我无法想象层应该如何连接。
感谢您的建议,Harry。
不错的教程
非常感谢
谢谢。
非常感谢您的教程!它帮助了我很多!
我有一个关于成本函数的问题。我有一个请求和几个文档:1 个相关的和 4 个不相关的。我想要一个既最大化 SCORE(Q, D+) 又最小化 SCORE(Q, D-) 的成本函数。所以,我可以有 Delta = SUM{ Score(Q,D+) – Score(Q,Di-) },其中 i 属于 (1..4)
使用铰链损失成本函数,我有 L = max(0, 4 – Delta)
我想知道,取出这 4 个文档,用 NN 计算它们的得分,然后将所有内容发送到成本函数中,这是一种好的做法吗?
我好奇是否有可能将两个独立的层作为输入层,而不是将它们连接成一个新层,然后让连接层投射到输出层。如果 Keras 无法做到这一点,您能推荐一个允许这样做的库吗?我刚接触神经网络,所以更喜欢适合初学者的库。
除了连接层,还有许多合并层可供选择。
这有帮助吗?
我有两张图片,第一张图片及其标签是好的,第二张图片及其标签是坏的。我想一次将两张图片传递给深度学习模型进行训练。在测试时,我将有两张(未标记的)图片,我想检测哪张是好的,哪张是坏的。您能告诉我怎么做吗?
您将需要一个带有两个输入的模型,每个图像一个。
您有没有给模型提供两个输入的例子?
是的,请参阅此图像标题示例,了解如何输入照片和文本
https://machinelearning.org.cn/develop-a-deep-learning-caption-generation-model-in-python/
非常感谢您的教程!非常感谢。
我困惑的是多输入多输出的模型。简单来说,假设我们有两个输入层,一些共享层和两个输出层。我能够在 Keras 中构建这个模型并获得预期的模型输出,但是当我尝试拟合模型时,Keras 抱怨道:ValueError:所有输入数组 (x) 应该具有相同的样本数。
是否无法输入不同大小的输入?
正确。输入必须填充到相同的长度。
你好,
在帖子的开头,您谈到了悬挂维度以容纳小批量大小。您能稍微解释一下吗?
我的特征矩阵是一个 numpy N 维数组,采用 one-hot 编码形式:(6000,200),我的批次大小 = 150。
这是否意味着我应该提供 shape=(200,)?
* 批次大小 = 50。
谢谢!
抱歉,这意味着一个 numpy 数组,其中实际上只有 1D 数据,第二个维度未指定。
例如
结果是
它是 1D 的,但对于初学者来说看起来很混乱。
这意味着我应该使用 shape(200,)。
非常感谢您的及时回复!!!
如何处理多输入多输出的情况
只需将此帖子中的一些示例组合起来即可。
嗨,Jason,
非常感谢您的博客,通过一些示例很容易理解,我认识到从一些示例中学习是学习新事物的快速方法之一。
在您的文章中,我有点困惑,在多输入的情况下。如果您有一个图像,但您想为每个 Conv 分支获取 RGB 32x32x3 版本和 64x64x1 灰度版本。网络如何知道这一点。因为当我们定义网络时,我们只说了 input_shape,我们没有说我们想要将哪种图像导入到分支 1 或分支 2 中的 Conv?在 fit 方法中,我们还必须说输入和输出,而不是给出详细信息。如果我想要灰度版本是:32x32x3(3 因为我想要通道方向,三重灰度版本)。网络如何识别第一个分支是用于灰度。如果我不知道有什么简单的事情,请原谅我的问题。再次感谢您的文章。我一直在关注您的文章。
您可以将所有图像通过一个输入运行,并将较小的图像填充到较大图像的维度。或者您可以使用多输入模型并定义两个独立的输入形状。
你好,
当我在模型中运行此函数式 API 进行 K 折交叉验证时,在每次折叠的返回拟合模型中,命名密集层中的数字都在增加。
例如,在第一折中是“dense_2_acc”,然后在第二折中是“dense_5_acc”。
我的模型摘要显示我的模型是正确的。您能否告诉我为什么拟合模型“历史”对象中每次折叠的名称会发生变化?
此致,
抱歉,我没有见过这种行为。也许是错误?你可以尝试发布到 keras 邮件列表。
https://machinelearning.org.cn/get-help-with-keras/
这是一个非常棒且简洁的初学者教程,用于使用 Keras 构建神经网络。做得好!
谢谢,听到这个我很高兴。
谢谢您的教程。
“当输入数据是一维的,例如多层感知器时,形状必须明确为训练网络时用于分割数据的迷你批次大小的形状留出空间。
因此,当输入是一维时,形状元组总是定义为悬挂的最后一个维度 (2,)。”
…
visible = Input(shape=(2,))
”
我一开始读这两句话有点困惑。
关于末尾逗号:当元组只有一个元素时,总是需要一个末尾逗号。否则 (2) 只返回值 2,而不是包含值 2 的元组。 https://docs.pythonlang.cn/3/reference/expressions.html#expression-lists
由于 Input 的 shape 参数应该是一个元组(https://keras.org.cn/layers/core/#input),当我们有一个要传递的单个元素时,除了添加逗号之外,我们别无选择。
所以,我无法理解“形状必须明确为迷你批次大小的形状留出空间……因此,形状元组总是定义为悬挂的最后一个维度”所隐含的含义
嗨,Jason,
非常感谢这篇精彩的帖子。
所以,在您共享输入层的情况下,您有相同的 CNN 模型用于特征提取,并且输出可以连接,因为两个特征都产生了二元分类结果。
但是,如果我们有单独的分类模型(用于序列分类)和回归模型(用于时间序列),它们依赖于相同的输入数据。那么,是否可以将分类模型(产生两个以上的类别)与回归模型连接起来,并且模型连接后的最终结果是二元分类?
在这种情况下,非常感谢您的意见。
谢谢你。
我不确定我是否理解。也许可以尝试一下,并尽可能多地尝试各种变体,然后看看效果如何。
嗨 Jason,谢谢您这篇简洁的帖子。
不客气,我很高兴它有所帮助。
谢谢 Jason,非常棒且有帮助的帖子
您能详细介绍一下如何使用函数式 API 组合宽深模型吗?
感谢您的建议。
您对这种方法有什么具体问题或疑虑吗?
谢谢 Jason,
您的文章是最好的,文章之间的一致性令人钦佩。
您能否也用函数式 API 解释一下残差网络。
谢谢
谢谢,也谢谢您的建议。
非常感谢您的精彩文章。
尽管我有一个问题,我使用多输入多输出模型和相同的网络作为我的输入。我希望在它们之间共享权重,您能指出我应该如何处理这个问题吗?
在层之间复制它们,或使用一个允许您重用层的包装器,例如 timeDistributed。
您的所有帖子都很棒。上帝保佑您 🙂
谢谢,我很高兴它们有帮助。
真的,很棒的教程。
你为什么不用测试步骤“预测”来完成它呢?
再次感谢 🙂
感谢您的建议。
我在这里解释如何进行预测
https://machinelearning.org.cn/how-to-make-classification-and-regression-predictions-for-deep-learning-models-in-keras/
“共享输入层”非常有趣。我想知道这两个卷积结构是否可以替换为两个预训练模型(比如 VGG16 和 Inception)。您怎么看?
好的,试试看吧。
这个问题是关于您之前关于“使用窗口方法的多层感知器”的帖子:https://machinelearning.org.cn/time-series-prediction-with-deep-learning-in-python-with-keras/
在您的代码中,您成功地使用多维数组输入创建了一个模型,而无需将其展平。
使用 Keras 函数式 API 也能做到这一点吗?我找到的每个解决方案似乎都需要展平数据,但我正在尝试进行时间序列分析,展平会导致信息丢失。
输入的形状与使用函数式 API 无关。
无论数据的形状如何,您都可以使用任一 API。
时间序列数据必须转换为监督学习问题
https://machinelearning.org.cn/convert-time-series-supervised-learning-problem-python/
嗨,
感谢这篇博客。我想知道如何从 Alexnet 模型的中间层提取特征。我正在使用函数式 API。
您可以创建一个在新模型,其终点在您感兴趣的层,然后使用正向传播(例如调用 predict())来获取特征。
我在图像标题教程中给出了 VGG 的一个例子。
https://machinelearning.org.cn/develop-a-deep-learning-caption-generation-model-in-python/
嗨,Jason!
再次感谢您的精彩博客。我有一个关于当前多输入模型研究的问题。
我正在构建一个结合文本序列和患者特征的模型。为此,我正在使用一个 LSTM“分支”,我将其与神经网络中的一个普通“分支”连接起来。我很好奇您是否遇到过一些深入探讨此类架构的精彩论文/文章,可能会给我一些关于如何优化此模型并彻底理解它的见解。
此致,
Joost Zeeuw
手头没有。我建议你对架构进行大量实验,看看什么最适合你的数据集。
我很想听听你的进展。
嗨 Jason!博客写得真好!
我的问题是:如何使用生成器为这种模型提供数据?实际上是两个生成器,一个用于测试,一个用于训练。顺便说一下,我正在尝试进行音素分类
我尝试了类似这样的代码:
#模型
input_data = Input(name='the_input', shape=(None, self.n_feats))
x = Bidirectional(LSTM(20, return_sequences=False, dropout=0.3), merge_mode='sum')(input_data)
y_pred = Dense(39, activation="softmax"), name="out")(x)
labels = Input(name='the_labels', shape=[39], dtype='int32') # 不确定这个,但否则如何比较标签呢??
self.model = Model(inputs=[input_data, labels], outputs=y_pred)
...
# 为了简化,我将省略优化和编译步骤
我的生成器会产生类似这样的东西
return ({'the_input':data_x, 'the_labels':labels},{'out':np.zeros([batch_size, np.max(seq_lens), num_classes])})
另外,只是为了确定,对于序列分类(多对一),我应该在循环层中使用 return_sequences=False,而不是 TimeDistributed rigth?
谢谢!
艾萨克
我这里有一个使用生成器的例子(在渐进式加载下)
https://machinelearning.org.cn/develop-a-deep-learning-caption-generation-model-in-python/
嗨,Jason,
感谢这篇博客。它非常有趣。读完你的博客后,我有一个疑问,如果你能帮助我解决这个问题——如果一个人想从一个经过微调的 Siamese 网络中的中间层提取特征,该网络已经用前馈多层感知器进行了预训练,该怎么办?
您能提供任何线索吗?这将对我非常有帮助。
您可以通过 layer.get_weights() 获取网络的权重。
你好,感谢你的文章。
我有一个问题。
结合离散和连续特征层更有效的方法是什么?
通常,整数编码、独热编码或嵌入层对分类变量是有效的。
嗨,Jason,您的博客非常好。我想在 Keras 中添加自定义层。您能解释一下我该怎么做吗?
谢谢。
我希望将来能涵盖这个话题。
嗨,Jason,
感谢这篇精彩的文章。我尝试实现一个1个隐藏层(2个神经元)后接一个输出层,都使用带有Sigmoid激活的密集层,用于训练XOR输入——这是一个经典问题,当然有解决方案。然而,在没有指定特定初始化的情况下,我无法训练这个最小神经元网络以找到解决方案(使用足够多的神经元时,我认为它独立于初始化而工作)。您能否提供这样一个简单的示例,作为Keras机制的测试用例,并就损失函数存在多个临界点时可能遇到的陷阱进行评论?
祝好,
Matt
感谢您的建议。
XOR无论如何都只是一个学术练习,也许可以关注一些真实数据集?
感谢您出色的教程。我正在尝试将Keras函数式API用于我的问题。我有两组不同的输入,我正在尝试使用一个双输入-单输出模型。
我的模型看起来像您的“多输入模型”示例,正如您所提到的,我正在做同样的事情,比如
model = Model(inputs=[visible1, visible2], outputs=output)
我正在使用这段代码拟合模型
model.fit([XTrain1, XTrain2], [YTrain1, YTrain2], validation_split=0.33, epochs=100, batch_size=150, verbose=2),但我收到了关于大小不匹配的错误。
输出TensorShape的维度为3,而YTrain1和YTrain2的形状也为(–, 3)。您对如何解决此错误有什么建议吗?我将不胜感激。
如果模型只有一个输出,您只需要指定一个yTrain。
嗨
谢谢你的回复。
我还有另一个问题,如果您能帮助我,我将不胜感激。
在您的多层感知器示例中,输入数据是一维的,如果我在Dense4的末尾添加一个reshape模块,将输出重塑为二维对象,那么是否可以将这个二维特征空间视为图像?
有没有绘制这个二维张量对象的语法?
谢谢
如果您在图像上拟合MLP,图像像素必须在作为输入提供之前被展平为1D。
谢谢,Jason
您能给我一个Conv1D => BiLSTM => Dense组合的例子吗?
我尝试过,但不知道如何将它们组合起来
这将有所帮助,作为一个开始
https://machinelearning.org.cn/cnn-long-short-term-memory-networks/
非常感谢您的快速回复,Jason,我读了这篇文章,非常有用!
但当我应用时,我发现它有一个非常奇怪的事情,我不知道为什么
看我的程序,它运行正常,但val_acc,我不知道为什么它总是 .] – ETA: 0s – loss: 0.2195 – acc: 0.8978
Epoch 00046: loss improved from 0.22164 to 0.21951,
40420/40420 [==============================] – 386s – loss: 0.2195 – acc: 0.8978 – val_loss: 5.2004 – val_acc: 0.2399
Epoch 48/100
40416/40420 [============================>.] – ETA: 0s – loss: 0.2161 – acc: 0.9010
Epoch 00047: loss improved from 0.21951 to 0.21610,
40420/40420 [==============================] – 390s – loss: 0.2161 – acc: 0.9010 – val_loss: 5.0661 – val_acc: 0.2369
Epoch 49/100
40416/40420 [============================>.] – ETA: 0s – loss: 0.2274 – acc: 0.8965
Epoch 00048: loss did not improve
40420/40420 [==============================] – 393s – loss: 0.2276 – acc: 0.8964 – val_loss: 5.1333 – val_acc: 0.2412
Epoch 50/100
40416/40420 [============================>.] – ETA: 0s – loss: 0.2145 – acc: 0.9028
Epoch 00049: loss improved from 0.21610 to 0.21455,
40420/40420 [==============================] – 395s – loss: 0.2146 – acc: 0.9027 – val_loss: 5.3898 – val_acc: 0.2344
Epoch 51/100
40416/40420 [============================>.] – ETA: 0s – loss: 0.2100 – acc: 0.9051
Epoch 00050: loss improved from 0.21455 to 0.20999,
您可能需要根据您的问题调整网络。
我尝试了很多次,但即使它过拟合了所有数据库,val_acc仍然很低。
我知道它过拟合了所有数据,因为我使用预测程序预测了所有数据库,准确率与训练准确率一样高。
谢谢你
也许可以尝试添加一些正则化,例如Dropout?
也许可以获取更多数据?
也许可以尝试减少训练的epochs数量?
也许可以尝试减小模型的大小?
谢谢你,Jason,
——我正在尝试通过添加一些 dropout 层进行测试,
——训练时的 epoch 数量不需要减少,因为我自己经常观察到这一点,
——关于模型的大小,我正在并行训练 4 个程序来检查它。
——最后一点,获取更多数据,如果以上所有方法都获得更好的结果,我才会这样做
听起来很棒。
嗨 Jason 感谢这篇很棒的文章
真的很有帮助
当我运行这段代码时
l_input = Input(shape=(336, 25))
adense = GRU(256)(l_input)
bdense = Dense(64, activation=’relu’)(adense)
.
.
.
我会收到这个错误
ValueError: Invalid reduction dimension 2 for input with 2 dimensions. for ‘model_1/gru_1/Sum’ (op: ‘Sum’) with input shapes: [?,336], [2] and with computed input tensors: input[1] = .
我真的筋疲力尽了,我在任何地方都找不到答案。
我该怎么办?
我感谢您的帮助
听起来数据和模型预期不符。也许可以改变数据或模型?
这是一个特别有用的教程,但我没有数据源就无法开始使用。
谢谢。
我之前留过一个关于需要数据源的回复,我看到其他读者没有这个问题,但我似乎仍然处于不知道输入什么数据或如何为这些示例进行预处理的阶段。我也很困惑,因为看起来PNG是一种常见的源。
我对一个能接收文本和问题并返回答案的示例特别感兴趣——我在哪里可以找到这样的输入以及如何将其适配到您的代码中?
Jason,您的github数据集中哪个数据集适合这个LSTM教程?或者您能推荐一个在线数据集吗?我对用于文本处理(非IMDB)的LSTM和Keras函数式API都感兴趣。
不太确定您想达到什么目的?
有没有可能用一些真实/虚拟数据作为载体来制作一个关于这个的教程?
我有很多关于真实数据集的深度学习教程,您可以从这里开始
https://machinelearning.org.cn/start-here/#deeplearning
还有这里
https://machinelearning.org.cn/start-here/#nlp
还有这里
https://machinelearning.org.cn/start-here/#deep_learning_time_series
谢谢您,Jason先生,
您能帮我使用卡尔曼滤波器预测太阳辐射吗?
您有关于卡尔曼滤波器预测太阳辐射的matlab代码吗?
此致
抱歉,我没有matlab示例,也没有卡尔曼滤波器的示例。
你好吗?抱歉打扰了。我正在关注您关于Keras使用神经网络和卷积神经网络的解释。我正在尝试使用一组具有三个通道的图像和另一组具有一个通道的图像进行卷积。当我使用Keras为每种类型的图像运行CNN时,我得到了一个结果。所以我有两个输入和一个输出。输入是X_train1,大小为(24484,227,227,1),X_train2,大小为(24484,227,227,3)。所以我分别为每个输入进行卷积,然后使用KERAS的“merge”命令,然后将“merge”应用于CNN。但是,我收到了以下错误
ValueError: could not broadcast input array from shape (24484,227,227,1) into shape (24484,227,227)。
我已经尝试删除数字1,所以形状变为(24484,227,227)。这样看起来是对的。但是错误又发生在X_train2上,并带有以下警告
ValueError: could not broadcast input array from shape (24484,227,227,3) into shape (24484,227,227)。
但是,我无法删除数字“3”。
您能帮我消除这个错误吗?
我的代码是
X_train1:形状为(24484,227,227,1)
X_train2:形状为(24484,227,227,3)
X_val1:形状为(2000,227,227,1)
X_val2:形状为(2000,227,227,3)
batch_size=64
num_epochs=30
DROPOUT = 0.5
model_input1 = Input(shape = (img_width, img_height, 1))
DM = Convolution2D(filters = 64, kernel_size = (1,1), strides = (1,1), activation = “relu”)(model_input1)
DM = Convolution2D(filters = 64, kernel_size = (1,1), strides = (1,1), activation = “relu”)(DM)
model_input2 = Input(shape = (img_width, img_height, 3))
RGB = Convolution2D(filters = 64, kernel_size = (1,1), strides = (1,1), activation = “relu”)(model_input2)
RGB = Convolution2D(filters = 64, kernel_size = (1,1), strides = (1,1), activation = “relu”)(RGB)
merge = concatenate([DM, RGB])
# 第一个卷积层
z = Convolution2D(filters = 96, kernel_size = (11,11), strides = (4,4), activation = “relu”)(merge)
z = BatchNormalization()(z)
z = MaxPooling2D(pool_size = (3,3), strides=(2,2))(z)
# 第二个卷积层
z = ZeroPadding2D(padding = (2,2))(z)
z = Convolution2D(filters = 256, kernel_size = (5,5), strides = (1,1), activation = “relu”)(z)
z = BatchNormalization()(z)
z = MaxPooling2D(pool_size = (3,3), strides=(2,2))(z)
# 剩余的3个卷积层
z = ZeroPadding2D(padding = (1,1))(z)
z = Convolution2D(filters = 384, kernel_size = (3,3), strides = (1,1), activation = “relu”)(z)
z = ZeroPadding2D(padding = (1,1))(z)
z = Convolution2D(filters = 384, kernel_size = (3,3), strides = (1,1), activation = “relu”)(z)
z = ZeroPadding2D(padding = (1,1))(z)
z = Convolution2D(filters = 256, kernel_size = (3,3), strides = (1,1), activation = “relu”)(z)
z = MaxPooling2D(pool_size = (3,3), strides=(2,2))(z)
z = Flatten()(z)
z = Dense(4096, activation=”relu”)(z)
z = Dropout(DROPOUT)(z)
z = Dense(4096, activation=”relu”)(z)
z = Dropout(DROPOUT)(z)
model_output = Dense(num_classes, activation=’softmax’)(z)
model = Model([model_input1,model_input2], model_output)
model.summary()
sgd = SGD(lr=0.001, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='categorical_crossentropy',
optimizer=sgd,
metrics=['accuracy'])
print(‘RGB_D’)
datagen_train = ImageDataGenerator(rescale=1./255)
datagen_val = ImageDataGenerator(rescale=1./255)
print(“fit_generator”)
# 使用训练集训练模型…
Results_Train = model.fit_generator(datagen_train.flow([X_train1,X_train2], [Y_train1,Y_train2], batch_size = batch_size),
steps_per_epoch = nb_train_samples//batch_size,
epochs = num_epochs,
validation_data = datagen_val.flow([X_val1,X_val1], [Y_val1,Y_val2],batch_size = batch_size),
shuffle=True,
verbose=1)
print(Results_Train.history)
看起来您的数据和模型不匹配。您可以重塑数据或更改模型的预期。
感谢您提供的所有信息。
您是否有使用Keras API共享层(2个输入和1个输出)的示例?
我想知道如何使用每个输入来获取其:Xtrain, Ytrain 和 Xtest, Ytest,
我想,用一个例子会更简单。
谢谢你。
也许这会有帮助。
https://machinelearning.org.cn/lstm-autoencoders/
你好,Jason。
您知道如何将每个模型与不同的损失函数结合起来吗?
Leeor。
是的,在它们训练之后,可以作为集成模型。
嗨,Jason,
感谢您精彩的教程!
我只是想知道“卷积神经网络”的例子。max_pooling2d_2 和 dense_1 之间是不是少了一个 Flatten 层?
像这样
pool2 = MaxPooling2D(pool_size=(2, 2))(conv2)
flatt = Flatten()(pool2)
hidden1 = Dense(10, activation=’relu’)(flatt)
此致
我想你说得对!已修复。
嗨 Jason
在多输入模型中,您是如何命名图层的?
____________________________________________________________________________________________________
层(类型)输出形状参数 # 连接到
====================================================================================================
input_1 (InputLayer) (None, 64, 64, 1) 0
____________________________________________________________________________________________________
conv2d_1 (Conv2D) (None, 61, 61, 32) 544 input_1[0][0]
____________________________________________________________________________________________________
conv2d_2 (Conv2D) (None, 57, 57, 16) 1040 input_1[0][0]
____________________________________________________________________________________________________
max_pooling2d_1 (MaxPooling2D) (None, 30, 30, 32) 0 conv2d_1[0][0]
____________________________________________________________________________________________________
max_pooling2d_2 (MaxPooling2D) (None, 28, 28, 16) 0 conv2d_2[0][0]
____________________________________________________________________________________________________
flatten_1 (Flatten) (None, 28800) 0 max_pooling2d_1[0][0]
____________________________________________________________________________________________________
flatten_2 (Flatten) (None, 12544) 0 max_pooling2d_2[0][0]
____________________________________________________________________________________________________
concatenate_1 (Concatenate) (None, 41344) 0 flatten_1[0][0]
flatten_2[0][0]
____________________________________________________________________________________________________
dense_1 (Dense) (None, 10) 413450 concatenate_1[0][0]
____________________________________________________________________________________________________
dense_2 (Dense) (None, 1) 11 dense_1[0][0]
====================================================================================================
总参数:415,045
可训练参数:415,045
不可训练参数: 0
____________________________________________________________________________________________________
如果模型一次性构建完成,默认名称即可。
如果模型是在不同时间构建的,我会给每个头部一个任意名称,例如:name = ‘head_1_’ + name
对Keras的见解非常深刻。
我还阅读了您的 Deep_Learning_Time_Series_Forcasting,非常有帮助。
谢谢。
正是您的邮件促使我更新这篇文章,增加了Python语法解释!
哇,非常感谢您所有的帖子,您为我的学习和原型设计经验节省了大量时间!
我使用了一个LSTM层,并想使用其输出来馈送一个Dense层以获得第一个预测值,然后将这个新值插入到第一个LSTM输出中,并馈送一个新的LSTM层。我卡在了维度问题上…
main_inputs = Input(shape=(train_X.shape[1], train_X.shape[2]), name=’main_inputs’)
ly1 = LSTM(100, return_sequences=False)(main_inputs)
auxiliary_output = Dense(1, activation=’softmax’, name=’aux_output’)(ly1)
merged_input = concatenate([main_inputs, auxiliary_output])
ly2 = LSTM(100, return_sequences=True)(merged_input)
main_output = Dense(1, activation= ‘softmax’, name=’main_output’)(ly2)
任何建议都欢迎
具体是什么问题?
我没有能力调试您的代码,也许可以发到stackoverflow上?
谢谢Jason的帖子🙂
在多输入CNN模型示例中,两张图片是否以相同的索引同时输入到模型中?
两张图片是否以相同的类别同时输入到模型中?
在训练中,每张黑白图片是多次(与所有彩色图片一起)输入到模型中,还是每张黑白图片只输入一次(与仅一张彩色图片一起)?
谢谢..
两张图片同时提供给模型。
两张图片是否以相同的类别同时输入到模型中?
这真的取决于您正在解决的问题。
嗨,Jason,我一直在寻找评论,希望有人会问类似的问题。
我有一些图像及其对应的数值。如果我构建一个用于图像的微调VGG模型和一个用于数值的MLP(或任何其他模型),并像您在这篇文章中那样将它们连接起来,我需要如何保持它们之间的对应关系?
通过某种标准(例如图像名称)将图像(和数值)输入到模型中是否实际可行?因为我的图像名称和数值数据集中的一列保存着样本的名称。
非常感谢。
您可以使用多输入模型,一个用于图像的输入,一个用于数字的输入。
训练数据集将是两个数组,一个图像数组,一个数字数组。行将对应。
这有帮助吗?
非常感谢。为了我自己澄清一下,请让我知道您对这些的反馈
1. 您的意思是我需要将图像转换为数组,并根据它们的名称,将其作为新列附加到数值数据文件(csv)中吗?
2. 我还没有见过这样的数值数据,其中一列包含图像的RGB值作为数组。您能发布一些相关的链接/来源吗?
感谢您的反馈。再次感谢!
不是。会有一个图像数组和一个数字数组,它们之间的行将对应。例如,第一个数组中的第0行将是与第二个数组中第0行的数字相关的图像。
如果这是新内容,这将帮助您处理数组
https://machinelearning.org.cn/gentle-introduction-n-dimensional-arrays-python-numpy/
这将帮助您将图像加载为数组
https://machinelearning.org.cn/how-to-load-and-manipulate-images-for-deep-learning-in-python-with-pil-pillow/
你好,现在我想使用一维数据(例如 wave.shape=(360,))作为输入,以及三维数据(例如 velocity.shape=(560,7986,3))作为输出。我想问一下,这个问题是否可以通过多层感知器来训练这些数据解决?我尝试过,但形状问题没有解决,它显示“ValueError: Error when checking target: expected dense_3 to have 2 dimensions, but got array with shape (560, 7986, 3)”
也许吧,这真的取决于数据代表什么。
您好,感谢分享内容🙂
“多输出”情况与“多任务深度学习”是否相同?
我正在尝试构建多任务深度学习模型,并在这里找到了。
再次感谢您。
是的,可以这样说。
Jason,目前我有一个非常微小的贡献。只是一个错别字。在,
……共享特征提取层
在本节中,我们将两个并行子模型来解释输出…
这句话看起来像缺少一个动词或什么,听起来很奇怪。
如果对你来说没问题,就忽略吧,肯定是我太累了。
我希望将来能更实质性地支持这个非凡的网站。
(你不需要发布这条评论)
此致
安东尼奥
谢谢,已修复!
(我喜欢保留这些评论,以表明一切都在进步中,并且在逐步改进)
Jason,非常感谢您的教程,它非常有帮助!我有一个问题,ModelCheckpoint回调如何与多个输出一起工作?如果我设置 save_best_only = True 会保存什么?是保存对两个输出都产生最佳总体结果的模型,还是会保存两个模型?
很好的问题,我在这篇文章中详细讨论了这个问题。
https://machinelearning.org.cn/how-to-stop-training-deep-neural-networks-at-the-right-time-using-early-stopping/
您能发一篇关于如何在Keras中制作部分连接层的帖子吗?带有预定义的神经元连接(上一层到下一层)。
感谢您的建议。
嗨,Jason,
如果我们想将预测结果写入单独的txt文件,需要在代码末尾添加什么?
谢谢。
您可以使用savetext()函数直接将numpy数组保存到csv文件中。
嗨,Jason,我非常喜欢这篇文章。我有一个应用程序,数据以CSV文件形式存在,其中包含四列文本数据,我将前三列作为输入数据来预测第四列数据作为我的输出。我需要将前三列作为输入,因为数据是相关的。您能指导我如何使用glove训练模型吗?
谢谢
也许这个教程会有帮助
https://machinelearning.org.cn/tutorial-first-neural-network-python-keras/
嗨 Jason
再次感谢您的精彩教程,我想知道将两层作为特征提取进行连接时的区别。您使用了 merge = concatenate([interp1, interp13])
其他人使用 merge = concatenate([interp1, interp13], axis = -1)。我想知道这两者之间是否有区别,以及区别有多大
它们是一回事。axis=-1 是默认值,无需指定。在此处了解更多信息
https://keras.org.cn/layers/merge/
嗨 Jason
感谢您的精彩教程,我想使用带 fit generator 的多输入模型
model.fit_generator(generator=fit_generator,
steps_per_epoch=steps_per_epoch_fit,
epochs=epochs,
verbose=1,
validation_data=val_generator,
validation_steps=steps_per_epoch_val)
但我收到 ValueError: Error when checking model input: the list of Numpy arrays that you are passing to your model is not the size the model expected. Expected to see 2 array(s), but instead got the following list of 1 arrays
keras 代码
input1 = Input(shape=(145,53,63,40))
input2 = Input(shape=(145,133560))
#特征 1
conv1 = Conv3D(16, (3,3,3),data_format =’channels_last’)(input1)
pool1 = MaxPooling3D(pool_size=(2, 2,2))(conv1)
batch1 = BatchNormalization()(pool1)
ac1=Activation(‘relu’)(batch1)
…….
ac3=Activation(‘relu’)(batch3)
flat1 = Flatten()(ac3)
#特征 2
gr1=GRU(8,return_sequences=True)(input2)
batch4 = BatchNormalization()(gr1)
ac4=Activation (‘relu’)(batch4)
flat2= Flatten()(ac4)
# 合并特征提取器
merge = concatenate([flat1, flat2])
output = Dense(2)(merge)
out=BatchNormalization()(output)
out1=Activation(‘softmax’)(out)
# 预测输出
model = Model(inputs=[input1,input2], outputs=out1)
opt2 = optimizers.Adam(lr=learn_rate, decay=decay)
model.compile(loss=’categorical_crossentropy’, optimizer=opt2,
metrics=['accuracy'])
我很乐意帮忙,但我没有能力调试你的代码,我在这里有一些建议
https://machinelearning.org.cn/faq/single-faq/can-you-read-review-or-debug-my-code
我尝试了给定部分(5. 多输入和输出模型)
请帮我拟合数据。我收到了错误
AttributeError: ‘NoneType’ object has no attribute ‘shape’
我的输入
干得不错。
或许可以尝试这里的一些建议
https://machinelearning.org.cn/faq/single-faq/can-you-read-review-or-debug-my-code
我是机器学习新手。使用函数式 API 拟合模型后,我得到了训练准确率和损失。但我不知道如何使用 Keras 函数式 API 找到测试准确率。
您可以通过调用 model.evaluate() 在测试数据集上评估模型。
我想构建 CNN + convLSTM 模型,
但是,在最后一行出现了维度错误…我该如何调整形状
:输入 0 与层 conv_lst_m2d_27 不兼容:期望 ndim=5,找到 ndim=4
input = Input(shape=(30,30,3), dtype=’float32”)
conv1 = Convolution2D(kernel_size=1, filters=32, strides=(1,1), activation=”selu”)(input)
conv2 = Convolution2D(kernel_size=2, filters=64, strides=(2,2), activation=”selu”)(conv1)
conv3 = Convolution2D(kernel_size=2, filters=128, strides=(2,2), activation=”selu”)(conv2)
conv4 = Convolution2D(kernel_size=2, filters=256, strides=(2,2), activation=’selu’)(conv3)
ConvLSTM_1 = ConvLSTM2D(32, 2, strides=(1,1) )(conv1)
也许改变输入形状以匹配模型的预期,或者改变模型以匹配数据形状的预期?
非常感谢您的精彩文章。
如果我的问题是这样的,我应该如何使用 API 设置我的模型
首先,分类化学品是否有毒,如果它们有毒,它们的毒性分数是多少。我可以分别创建两个模型。但是将它们结合在一起是一种很好的正则化,一些论文说。我认为这是一个多输入和多输出问题。我有一个数据集,其输入形状相同,组合输出将是 y1 = 0 或 1,如果 y1=1,则 y2 = 数值分数。
我不知道在哪里以及如何将 if 语句放入组合模型中。
任何建议都将不胜感激。
也许从这里开始
https://machinelearning.org.cn/start-here/#deeplearning
也许我没有清楚地解释我的问题。
我可以使用 Keras 分别构建分类和回归模型,没有任何问题。我的问题是如何将这两个模型与“IF 语句”组合成一个多输入、多输出模型。从您提供的链接中,我找不到解决方案。您能详细说明一下吗?非常感谢。
输入和输出具体是什么?
就像这样
例如 x1 x2 x3 x4 y1 y2
1 0.1 0.5 0.7 0.4 1 0.3
2 0.5 0.2 0.4 0.1 0
3 0.7 0.6 0.3 0.2 0
4 0.12 0.33 0.05 0.77 1 0.55
.. .. .. .. .. .. ..
只有当 y1 = 1 时,y2 才有一个值
以上不是真实数据集。
解决这个问题可能有很多方法。
也许您可以设置模型始终预测一些东西,并且只在 y1 具有特定值时才关注 y2?
首先,非常感谢您的快速回复。
我还是不明白。您说有很多方法可以解决,但我不知道其中任何一种。有两个数据集(X1,y1),(X2,y2)。所以我认为这是一个多输入和多输出问题。两个数据集之间的样本数量应该相等吗?
是的。
谢谢你,Jason,又一个很棒的教程!你是一位非常有才华的老师!
谢谢,很高兴对您有帮助。
嗨 Jason,我一直关注您的博客和书籍(线性代数用于机器学习),它们非常有帮助。您是否有关于 LSTM 层后接 2D CNN/Maxpool 的帖子?如果您已有帖子,请提供链接。
实际上,按照这篇帖子中给出的方向操作后,我遇到了一些维度问题。
https://stackoverflow.com/questions/53904688/using-keras-to-build-a-lstmconv2d-model/56253458#56253458
但这并没有解决我的问题。如果您能在这方面提供帮助,那就太好了。
谢谢你
我不认为我有 LSTM 连接到 CNN,我认为这没有意义。
你为什么要这样做?
你好,
首先非常感谢您的出色网页。从我开始进行深度学习的第一天起,它就提供了很大的帮助。不过我有一个问题。您在“多输入模型”小节中提到的具有多个输入和一个输出的模型的相应损失函数是什么?我想知道,如果您的输入是 X1 和 X2,输出是 Y,那么损失函数的数学表达式会是什么。我想做同样的事情。但是,我不确定我将最小化什么。
另一个问题是关于损失权重。例如,如果我有两个输出和它们各自的两个损失函数,如果我将第一个损失权重设置为零,它会停用与第一个输出相关的训练过程吗?
提前非常感谢您的帮助。
此致,
该模型将为每个输出设置一个损失函数。
Y 只有一个输出,一个具有两个输入 X1 和 X2 的单输出模型。
如果输出是向量,则只有一个损失函数,对向量输出中的每个项取平均值。
在非平凡问题中,除非您过度拟合训练数据,否则您永远不会达到零损失。
非常感谢您的回复。但是,您误解了我关于多输出的问题。不过,我已经解决了那个问题。但是我关于包含两个输入(X1 和 X2)和一个输出的网络的问题仍然没有得到解答。我知道它只有一个损失,但我不确定损失是什么。它可以是以下任何一种
1. [ F1(x1)+F2(x2) – Y ]
2. [ F(x1,x2) – Y ]
我不确定这里会是哪一个损失。如果您能帮助我,我将不胜感激。非常感谢。
多输入中的输入是聚合的,因此损失是两个输入的函数。
很棒的博客!
您能帮我们提供一个不使用密集层的示例代码架构吗?
发现很难理解最后一部分如何摆脱密集层。
谢谢
您可以使用任何您想要的输出层。
你为什么要去掉密集层?
太棒了。非常感谢分享。真的很有帮助!你是个巫师……
我很高兴它能帮到你。
精彩的帖子!它既易于理解,又足够复杂,可以推广多种类型的网络。它对我帮助很大!谢谢!!
谢谢,我很高兴它有所帮助!
嗨,Jason,
你帮了我很多,但我又碰壁了。
我想构建一个多输出多输入线性回归模型,但在网上找不到任何相关信息。我尝试使用不同的关键词,如使用 keras 的多目标线性回归、多依赖变量、多元。我找不到任何东西。
您有这方面的资料吗?
您可以将目标数量指定为输出层中的节点数量。
是的,我有很多时间序列的例子,你可以从这里开始
https://machinelearning.org.cn/start-here/#deep_learning_time_series
还有这个。
https://machinelearning.org.cn/faq/single-faq/how-do-you-use-lstms-for-multi-step-time-series-forecasting
这有帮助吗?
嗨,Jason,
非常感谢您提供的两个链接,我不知道您的资料组织得如此有条理。
我是机器学习新手,我想我有点困惑。
假设我有一堆数据,它们都是时间序列数据的平均值。
我真的需要使用时间序列吗?我有 10 列输入和 5 列输出。但是,我将处理此数据集的时间序列版本。
另外,时间序列的定义是:“在描述性建模或时间序列分析中,时间序列被建模以确定其在季节模式、趋势、与外部因素关系等方面的组成部分。……相比之下,时间序列预测使用时间序列中的信息(可能带有附加信息)来预测该序列的未来值。”——摘自您的博客
如果我的数据没有趋势或模式怎么办?比如我的数据是工业数据,例如发动机的数据?我想预测它在特定时间如何运行或类似的事情。
我还记得您曾发帖说 LSTM 不太适合时间序列预测。我可以使用哪些不同的方法?我没有图像,所以不能使用 CNN。
RNN 好吗?
抱歉写了这么长。
更新一下,我刚读了您关于用于时间序列建模的 CNN 的博客,我相信您不需要图像,我很抱歉说了“我没有图像,所以不能使用 CNN。”
https://machinelearning.org.cn/how-to-develop-convolutional-neural-network-models-for-time-series-forecasting/
对于上面的链接,您似乎只使用了序列,我的数据必须是序列吗?
是的。要使用一维 CNN,模型假定输入是序列。
时间序列可能具有或不具有模型可以利用的有用时间结构。您可以选择尝试捕获它或不捕获它——您是对的。
但是,您必须遵守观测值的时间顺序,例如,在过去训练,在未来测试,永远不要将两者混淆。否则,您的模型评估将无效(过于乐观)。
请参阅此框架,了解要尝试的方法和尝试它们的顺序。
https://machinelearning.org.cn/how-to-develop-a-skilful-time-series-forecasting-model/
一如既往的精彩帖子!!谢谢 Jason。
我有两个关于展平的问题
我们可以用 Bi-LSTM 替换展平吗?
如果我想在 Embedding 之后使用 Bi-LSTM,我应该在进入 Bi-Lstm 之前展平 Embedding 的输出吗?
谢谢。
无需展平。
太棒了
谢谢,很高兴对您有帮助。
一如既往的棒!但您介意告诉我如何在MIMO情况下处理损失函数吗?我猜它应该为每个输入/输出单独计算。谢谢!
没有不同,如果多个输出是数字,均方误差是一个很好的开始。
函数模型可以应用于预测股市吗?
这是我在这里回答的一个常见问题
https://machinelearning.org.cn/faq/single-faq/can-you-help-me-with-machine-learning-for-finance-or-the-stock-market
非常感谢这篇富有洞察力的文章。我正在寻找一种结合RNN(LSTM)和HMM的方法,根据两种范式的综合优势来预测股票价格,以期获得比普通RNN(LSTM)更好的结果。谢谢。
听起来是个有趣的项目,告诉我进展如何。
谢谢您的回复。但我需要您在这方面的见解。谢谢。
抱歉,我没有任何使用HMM或将其与LSTM集成的例子。
我建议开发一些原型以发现什么有效。
我创建了一个双输出LSTM模型来预测角速度和线速度,角速度的损失较低,但线速度的损失较高。请告诉我如何减少损失。
第 9/10 纪元
– 18秒 – 损失:0.4790 – A_输出_损失:0.0826 – L_输出_损失:0.3964 – A_输出_准确率:0.6077 – L_输出_准确率:0.4952 – 验证_损失:0.6638 – 验证_A_输出_损失:0.0958 – 验证_L_输出_损失:0.5680 – 验证_A_输出_准确率:0.6059 – 验证_L_输出_准确率:0.3166
第 10/10 纪元
– 18秒 – 损失:0.4752 – A_输出_损失:0.0821 – L_输出_损失:0.3931 – A_输出_准确率:0.6084 – L_输出_准确率:0.4996 – 验证_损失:0.6503 – 验证_A_输出_损失:0.0970 – 验证_L_输出_损失:0.5533 – 验证_A_输出_准确率:0.6052 – 验证_L_输出_准确率:0.3176
这里有一些建议。
https://machinelearning.org.cn/start-here/#better
在共享层CNN示例中,为什么形状从64变为61,我理解核大小是4,但64/4没有余数。另外,您知道mxnet是否有类似的方法或教程吗?
是的,我相信这归结为相同(same)填充与有效(valid)填充
https://machinelearning.org.cn/padding-and-stride-for-convolutional-neural-networks/
抱歉,我不了解mxnet。
嗨,Jason,
感谢您的精彩网站和您的精彩书籍(我们拥有大部分)。
我有一个问题,希望您能帮助我。
在上面的文章中,您描述了许多可以实现的不同网络结构。有没有什么经验法则可以描述哪种网络结构最适合哪种问题?我在时间序列预测方面做了一些工作,我读过的所有内容都告诉我只尝试不同的结构,但考虑到不同结构的数量,这很不切实际。
例如,如果您有多个数据输入源,您是将它们连接成MLP的单个输入,还是使用多输入模型?
我很想听听您的想法。
不客气。
不完全是,您必须使用受控实验来发现最适合您数据集的方法。
这可能对您有所帮助,作为一般指南
https://machinelearning.org.cn/when-to-use-mlp-cnn-and-rnn-neural-networks/
嗨 Jason,自从我开始大学项目以来,我一直在关注您的博客,我在这页上卡住了,我的问题是我有一个生物反应器(发酵过程)的数据集,它有100批数据,每批有1000个时间步和200个参数(变量)。
所以是 100 * 1000 = 100,000 个时间步,每个时间步有 200 个变量。我想开发一个“Y”形架构(就像您帖子中的 MIMO),因此“Y”的一侧输入是“观测变量”,另一侧是“受控变量”。我想通过 LSTM 层传递观测变量,但在输入维度上我很困惑,另一个是如何使用这个模型?
1. 我会根据当前批次预测下一个批次吗?
2. 我会根据 t 预测下一个时间步 (t+1) 吗?
3. 当我们想要进行预测时,是否需要传递整个批次大小,因为我们构建模型时使用了 dim(1000 * timesteps * 200)?
我的目标是:给定当前过程状态(3 或 4 或“n”个时间步),我希望我的模型能够预测 n+1 或 n+10 个时间步,同时提供“Y”另一侧的受控变量。
这将帮助您更好地理解 LSTM 的输入形状
https://machinelearning.org.cn/faq/single-faq/what-is-the-difference-between-samples-timesteps-and-features-for-lstm-input
非常感谢,我还有1个问题,如果您有时间回答,很抱歉用太多问题打扰您。
如果 Xa 和 Xb 是 2 个不同网络的输入(Xa-> LSTM)和(Xb-> Dense),并且它们将来想要共享一个公共的 Dense 层以给出输出“y”。
Xa 和 Xb 共享相同的时间索引,所以如果我将 Xa 重塑为 3D(samples, 10, 5),那么我应该如何重塑 Xb?
您将连接每个子模型的输出。您可能需要在连接之前展平 LSTM 输出。
请 Jason 博士
我不明白 None 的意思以及它是如何从 Flatten 层处理到 Dense 层的
正如我所读到的,它是(并行处理的批次数量,特征数量)
我还想知道如何编写 Python 代码来可视化这个展平输出(包括批次和特征)
非常感谢
None 意味着未指定,因此它将处理提供的任何数字。
非常感谢!整篇文章都很有帮助!!特别是最后关于函数式 API Python 语法的说明。没有人会费心将这个添加到他们的深度学习教程中!
谢谢,很高兴听到它有帮助!
先生,您的教程很棒。非常感谢。
不客气!
感谢您的信息丰富的教程。
我有两个目录包含RGB图像。我将使用两个数据生成器来读取它们,然后将这两个生成器馈送到CNN中。
问题1
我应该如何组合这两个数据生成器,更重要的是,如何将“fit_generator”函数用于多个生成器,以便网络可以在所有样本(两个目录)上进行训练?
问题2
如果我手动合并这两个数据集(将所有文件从一个目录复制到另一个目录)以形成一个单独的数据集,然后使用一个单独的数据生成器读取它们并将其馈送到CNN中。
与方法1(问题1中提及)相比,它对输出有影响吗?这意味着它会增加或减少准确性、损失或其他指标吗?
谢谢。
每个目录都使用一个单独的生成器。
可能。试试看。
Jason 先生,您好!
我也有同样的疑问。如果您能 kindly 分享任何参考代码,读者将不胜感激。
谢谢并致以问候
感谢您的建议。
这是我目前找到的关于函数式 API 的最佳解释。
谢谢,詹姆斯!
嗨,Jason,
感谢您写出如此精彩的博客,您提供的进一步阅读链接无法使用。请问您能更新它们吗?再次感谢!
谢谢,哪些链接?
你好,Jason。我有一个疑问。为什么 Keras 被称为 Keras API?它是一个库,它是如何变成 API 的?
代码库是可重用代码的集合
https://zh.wikipedia.org/wiki/Library_(computing)
API 是使用库(或任何软件)的标准接口
https://zh.wikipedia.org/wiki/Application_programming_interface
谢谢你,Jason,那么 Python 中的所有库都称为 API 吗?
它们是库,每个库都提供一个 API。
谢谢你,杰森
不客气。
太棒了。非常感谢您发表这篇文章。
不客气!
谢谢你,杰森,
这是一篇非常有用的文章。对于多输入多输出的情况,似乎每个输入中的示例/样本数量应该与训练数据相同。我有一个单一模式,具有两组不同的输入,它们产生两组不同的输出。对每个输出应用不同的损失(每个输出一个损失,总共2个)。
然而,我收到此错误:“所有输入数组 (x) 的样本数量应相同。”
这似乎是一个常见问题,但没有人有解决方案。您有什么想法吗?
==========================================================
#输入/输出1和2的示例数量不同
model = Model(inputs= [input1, input2], outputs=[outputs1, outputs2])
model.compile(loss=[loss1,loss2], optimizer=opt, metrics=[‘accuracy’])
model.fit({‘inputs1’:input_data_array1, ‘inputs2′:input_data_array2},
{outputs1′:y_arrray1,outputs2’:y_arrray2,
, epochs=100)
是的,输入样本的数量必须与输出样本的数量匹配,例如,对于两个目标。
我将提名杰森·布朗利为年度澳大利亚人!
谢谢,你真好!
你好 Jaison,
感谢您的博客。我是机器学习的新手,我有以下问题。
我创建了多个输入(CNN、LSTM)和一个单一输出模型。由于模型同时接受图像输入和文本输入,我该如何添加图像增强?
model.fit([image_train,text_train], label_train, batch_size=BATCH_SIZE,
epochs=40, verbose=1, callbacks=callbacks, validation_data=([image_test,text_test], label_test))
您可以创建带有文本副本(未增强)的增强图像。为此,您可能需要一个自定义数据生成器。
嗨,Jason,
感谢博客。
由于我是Python初学者,这可能是一个与Python语法而非Keras相关的问题。
对于 Keras 函数式 API 示例
from keras.layers import Input
from keras.layers import Dense
visible = Input(shape=(2,))
hidden = Dense(2)(visible)
最后的语法类似于 Java 中的类型转换,它在 Python 中叫什么,有什么作用?
不,不是类型转换。
它是在从构造函数返回的对象上调用一个函数,而这个函数恰好是将对象的输入连接到作为参数传递的另一个层的输出的函数。
很难阅读——我知道,但很容易编写。
所以根据你的解释,我可以这样写吗?
hidden = visible(Dense(2))
不。它会有不同的效果,例如,visible 将 Dense(2) 的输出作为输入,而 Dense(2) 的引用现在不可用。
非常感谢您的精彩文章。
如果我有两个输入但样本数量不同,是否可以使用多输入、多输出 API 来构建和训练模型?
我的问题是,如果我给你一张图片,首先,我想知道图片中是否有人。如果是,我想知道他/她多大。所以我必须准备两个数据集。例如,一个数据集包含10,000张图片,其中5,000张有人,5,000张没有人。另一个数据集包含1,000张有人且标注了年龄的图片。这两个数据集的样本数量不同,有些图片可能出现在两个数据集中。
对于这个问题,它是一个多输入、多输出问题,但两个输入的样本数量不同,我可以使用 Keras 的 API 来构建模型吗?如果不能,您有什么其他方法可以建议吗?非常感谢
不客气。
不,我认为每个输入的样本数量必须相同。
谢谢您的回复。如果每个输入的样本数量相同,那么当我准备这两个输入时,我需要将它们配对吗?我的意思是数据集1和数据集2的特征必须代表相同的样本。就像我举的例子,数据集1中的第1张图片必须是数据集2中的第1张图片,依此类推。
是的,输入需要配对。
非常感谢!
不客气。
嗨,好帖子!对函数式 API 进行了快速而清晰的介绍。
谢谢!
嗨,Jason,
感谢博客。
我正在将图像分成块。您对提取特征以区分隐写图像和原始图像有什么建议?
不客气。
“隐写图像和原始图像”是什么意思?
嗨,Jason,
非常感谢这篇精彩的教程!
我正在尝试使用您的示例“多输入模型”来实现一个具有多个输入层的模型。在调用 fit 函数时,我在输入数据的形状方面遇到了一些问题。您能提供一个如何在您的示例上调用 fit 函数的示例吗?
像往常一样调用 fit(),并提供一个输入列表,其中列表中的每个元素对应模型中的每个输入。
我在博客上提供了许多多输入模型的示例。也许可以尝试搜索一下。
谢谢!
不客气。
非常感谢您清晰的解释。我想知道如何在其中添加 BatchNormalization 和 Relu。实际上,我正在尝试使用函数式 API 编写 dncnn 代码。
顺序 API 代码
model=Sequential()
model.add(Conv2D(64,(3,3),padding=”same”,input_shape=(None,None,1)))
model.add(Activation('relu'))
for layers in range(2,16+1)
model.add(Conv2D(64,(3,3),padding=”same”))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(Conv2D(1,(3,3),padding=”same”))
我想知道如何使用函数式 API 实现
您可以通过函数式 API 添加批归一化层,就像添加任何其他层(例如密集层)一样。不需要特殊的语法。
先生,这个解释非常好。我想知道如何实现以下目标:
1. 创建并训练一个模型。(我已经明白了)
2. 将这个模型及其训练好的权重作为另一层用于其他模型中。
如果您能提供这方面的信息,将非常有帮助。
谢谢。
是的,这叫做迁移学习,请看这个
https://machinelearning.org.cn/?s=transfer+learning&post_type=post&submit=Search
你好,Jason。
您能给我解释一下理论吗?输入数据是如何转换为第一个 LSTM 层的张量的。例如,如果输入是 (None, 1, 10),并且 LSTM 的第一层有 64 个神经元,即 (None, 64)。这里是不是发生了一些矩阵乘法?
不涉及理论。这将帮助您为 LSTM 准备数据
https://machinelearning.org.cn/faq/single-faq/what-is-the-difference-between-samples-timesteps-and-features-for-lstm-input
感谢这个很棒的教程。它真的很有帮助。
不客气。
你好,Jason。
万分感谢。您简直是天才。
我有一个关于多输入层(CNN)的问题。我什么都明白了,但我不知道如果我有两张图像作为输入,该如何训练这个模型?您能指导一下吗?
通常我们这样调用拟合模型,使用单个 x 和 y,但我对两个输入感到困惑。
例如
model.fit(trainImages, trainPrices, validation_data=(testImages, testPrices),epochs=300, batch_size=batchSize)
如果您能帮助我,我将不胜感激。谢谢
您需要为模型的每个输入提供一个输入数据集,在调用fit时以列表形式提供,例如 model.fit([trainX1, trainX2], …)
我的博客上有很多例子。
谢谢你,Jason Brownlee,
我明白了,并且成功了。愿上帝保佑你,祝你在生活中取得更大的成功。
干得好!
你好,杰森
非常感谢你的辛勤工作
这几个月我一直在看你的教程,它们真的很有帮助
我能问一下你有没有关于深度学习模型有两个输入(比如文本和二进制特征)的例子,或者读过这样的例子吗?谢谢。
是的,你可以使用多输入模型,为每种数据类型/流设置一个输入。我有一些例子,例如照片字幕教程可能会给你一些想法。
你好,我能问一下如何进行自动编码器特征选择并将其放入深度神经网络模型中吗?
谢谢您
也许这会有帮助。
https://machinelearning.org.cn/autoencoder-for-classification/
很棒的帖子 @Jason Brownlee
有没有关于如何使用深度学习进行聚类的例子?
还没有,也许将来会有。
谢谢,这是我读过最好的解释🙂
不客气。
有趣而复杂的内容被简洁地表达出来。我真希望我能更早看到这篇帖子。非常感谢Jason。
不客气!
谢谢,Jason博士,这个很棒的博客。
另外,我想问如何连接CNN(使用图像)和LSTM(使用时间序列)模型,其中CNN是使用Keras的flow_from_directory和生成器进行训练的。
任何示例或指导都将有助于实际实现。
谢谢和问候
有一篇Keras CNN的帖子可能会给你一些示例代码作为开始:https://machinelearning.org.cn/how-to-develop-a-convolutional-neural-network-from-scratch-for-mnist-handwritten-digit-classification/
但我不知道你想将CNN和LSTM连接到什么?你是假设CNN的输出作为LSTM的输入吗?如果是这样,你只需在CNN中去掉最后一层,然后将其作为LSTM模型的输入。
感谢您宝贵的建议。
我希望使用LSTM从时间序列数据中提取特征,并使用CNN(使用Keras生成器)从图像中提取特征。此外,我需要在将它们馈送到全连接(Dense)层和随后的softmax层之前,将这两种特征连接起来。我不会将CNN输出作为LSTM输入。
此致
这可以。Keras有一个 concatenate 函数,可以让你组合它们。一个例子可以在这篇帖子的代码中找到:https://machinelearning.org.cn/how-to-implement-pix2pix-gan-models-from-scratch-with-keras/
谢谢。这篇帖子很容易理解。我很喜欢!
谢谢你。希望你喜欢。
有趣而复杂的内容被简洁地表达出来。我真希望我能更早看到这篇帖子。非常感谢Jason。
谢谢。很高兴你喜欢。
感谢这篇博客。
我想问一下,如果我想在最后一个隐藏层神经元上使用包含三角函数的函数。那么,我如何将张量中的输入分开并对它们应用函数,然后将输出提供给输出层呢?
我定义了一个自定义层,其输入类型是张量。然后我使用了 tf.split() 函数,我以为它会将前一个隐藏层的输入分成5个输入。然后,我对这5个输入使用了6个函数并将它们保存在一个列表中。最后,我使用 tf.convert_to_tensor() 函数将列表转换为张量。最终,自定义层将返回这个张量。我遇到了一个错误。
真的可以将一个张量分成5个变量吗?另外,批处理大小会影响分割吗?
我的数据集有以下列:
year, w_1_1, w_1_2,…., w_1_52, w_2_1, w_2_2,…,w_2_52, w_3_1,…, w_3_52, w_4_1,.., w_4_52, w_5_1,…, w_5_52, w_6_1,…, w_6_52, yield
其中 yield 是我希望模型预测的单个值。
我想创建6个1D CNN模型来训练数据的不同部分,第一个模型在 w_1_1 到 w_1_52 上训练,第二个模型在 w_2_1 到 w_2_52 上训练,第三个模型在 w_3_1 到 w_3_52 上训练,以此类推,直到第六个模型在 w_6_1 到 w_6_52 上训练,最后将它们的输出连接起来。
但我不知道如何为1D卷积调整数据的不同部分的大小。
嗨,Jaydeep……以下资源中介绍的概念同样适用于CNN。
https://machinelearning.org.cn/reshape-input-data-long-short-term-memory-networks-keras/
你好,James,谢谢你的教程,非常有帮助。
你有没有使用Keras函数式API的任何教程或完整实现?例如,使用Keras函数式API编译和拟合一个多输入多输出模型,并使用ImageDataGenerator函数。
谢谢。
嗨,Jack……非常欢迎!关于你的问题,我推荐以下资源作为起点
https://tensorflowcn.cn/api_docs/python/tf/keras/preprocessing/image/ImageDataGenerator
https://machinelearning.org.cn/develop-a-deep-learning-caption-generation-model-in-python/
我正在尝试使用 Python 连接多类别两特征(HOG 和 CNN)的 CNN,你能帮我吗?
嗨 efuye……请详细说明您已经做了什么以及可能遇到的问题,以便我们更好地帮助您。
嘿,Jason,感谢你的精彩博客文章!
在这种情况下,你将如何指定 layer_input 形状:我有一个三维的平衡月度面板数据集,每个月有2500个独立的横截面观测值,每个横截面有134个特征,时间段从2006-01到2019-12(168个月),所以是 2500 x 134 x 168。
因此,数据集有 2500*168 = 420000 行和 134 列。
正如你所说,批次大小(时间维度)被省略了,所以我在输入层中指定了 'shape = c(2500, 134)'。然而,我收到了错误 'ValueError: Input 0 of layer “model_6” is incompatible with the layer: expected shape=(None, 2537, 132), found shape=(None, 132)'
在这种三维面板数据的情况下,你能告诉我如何正确指定输入层的形状吗?
嗨,Henriko……你太客气了!以下资源可能会对你有所帮助
https://machinelearning.org.cn/reshape-input-data-long-short-term-memory-networks-keras/
https://stackoverflow.com/questions/52562133/keras-how-to-shape-inputs-for-cnn-and-lstm-layers
我正在尝试为我的数据集使用“多输入,多输出模型”。
# 合并输入模型
merge = concatenate([flat1, flat2])
我想知道这两个输入数据集是应该对整个数据集进行拼接,还是应该分别对训练和测试数据进行拼接。
期待任何建议。谢谢。
我正在尝试为我的数据集使用 “5. 多输入和输出模型”。
在这行代码中,
# 合并输入模型
merge = concatenate([flat1, flat2])
我应该分别拼接训练和测试数据集,还是应该一次性对整个数据集进行拼接?
嗨,Rahul……以下资源提供了训练集和测试集划分的最佳实践。
https://machinelearning.org.cn/train-test-split-for-evaluating-machine-learning-algorithms/
期待任何建议。
文献中通常有什么术语来指代“多输入模型”架构吗?在我看来它不像是一个多头网络。