我们如何在 Keras 中定义一对一、一对多、多对一和多对多的 LSTM 神经网络? [复制]

Posted

技术标签:

【中文标题】我们如何在 Keras 中定义一对一、一对多、多对一和多对多的 LSTM 神经网络? [复制]【英文标题】:How can we define one-to-one, one-to-many, many-to-one, and many-to-many LSTM neural networks in Keras? [duplicate] 【发布时间】:2019-02-07 20:01:27 【问题描述】:

我正在阅读this的文章(循环神经网络的不合理有效性),想了解如何表达一对一、一对多、多对一和多对多Keras 中的 LSTM 神经网络。我已经阅读了很多关于 RNN 并了解 LSTM NN 的工作原理,特别是消失梯度、LSTM 单元、它们的输出和状态、序列输出等。但是,我无法在 Keras 中表达所有这些概念。

首先,我使用 LSTM 层创建了以下玩具 NN

from keras.models import Model
from keras.layers import Input, LSTM
import numpy as np

t1 = Input(shape=(2, 3))
t2 = LSTM(1)(t1)
model = Model(inputs=t1, outputs=t2)

inp = np.array([[[1,2,3],[4,5,6]]])
model.predict(inp)

输出:

array([[ 0.0264638]], dtype=float32)

在我的示例中,我的输入形状为 2 x 3。据我了解,这意味着输入是 2 个向量的序列,每个向量有 3 个特征,因此我的输入必须是形状为 @987654325 的 3D 张量@。在'sequences'方面,输入是一个长度为2的序列,序列中的每个元素由3个特征表示(如果我错了请纠正我)。当我调用predict 时,它返回一个带有单个标量的二维张量。所以,

Q1:是一对一还是另一种类型的 LSTM 网络?

当我们说“一/多输入和一/多输出”时

Q2:我们所说的“一个/多个输入/输出”是什么意思? “一/多”标量、向量、序列……,一/多什么?

Q3:有人可以为每种类型的网络在 Keras 中给出一个简单的工作示例:1-1、1-M、M-1 和 M-M?

PS:我在一个线程中问了多个问题,因为它们非常接近并且彼此相关。

【问题讨论】:

***.com/questions/43034960/… @nuric 感谢您的参考,但是这篇文章并没有完全回答我的问题。特别是,我的示例是一对一还是多对一,为什么?如果 LSTM 的输出是一个向量,我们认为输出是多(标量)还是一个(向量)? 你认为它是一次向量。许多等中使用的术语指的是时间步长而不是特征。 【参考方案1】:

一对一一对多多对一多对一的区别-many 仅在 RNN / LSTM 或处理顺序(时间)数据的网络的情况下存在,CNN 处理空间数据,这种区别不存在存在。所以很多总是涉及多个时间步/一个序列

不同的物种描述了输入和输出的形状及其分类。对于输入 one 表示单个输入量被归类为封闭量,many 意味着一系列量(即图像序列、单词序列)被归类为封闭数量。对于输出 one 表示输出是一个标量(二进制分类即 is a birdis not a bird0 或 @987654329 @, many 表示输出是一个 one-hot 编码向量,每个类都有一个维度(多类分类即 is a sparrow, 是一个知更鸟,...),即三个类001, 010, 100

在以下示例中,图像和图像序列用作应分类的数量,或者您可以使用单词或...和单词序列(句子)或...:

一对一:单个图像(或单词,...)被分类为单个类别(二元分类),即这是否是一只鸟

一对多:单个图像(或单词,...)被分为多个类别

多对一:图像序列(或单词,...)被分类为单一类别(序列的二元分类)

ma​​ny-to-many :图像序列(或单词,...)分为多个类

cf https://www.quora.com/How-can-I-choose-between-one-to-one-one-to-many-many-to-one-many-to-one-and-many-to-many-in-long-short-term-memory-LSTM


一对一activation=sigmoid(默认)loss=mean_squared_error

from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
# prepare sequence
length = 5
seq = array([i/float(length) for i in range(length)])
X = seq.reshape(len(seq), 1, 1)
y = seq.reshape(len(seq), 1)
# define LSTM configuration
n_neurons = length
n_batch = length
n_epoch = 1000
# create LSTM
model = Sequential()
model.add(LSTM(n_neurons, input_shape=(1, 1)))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adam')
print(model.summary())
# train LSTM
model.fit(X, y, epochs=n_epoch, batch_size=n_batch, verbose=2)
# evaluate
result = model.predict(X, batch_size=n_batch, verbose=0)
for value in result:
    print('%.1f' % value)

来源:https://machinelearningmastery.com/timedistributed-layer-for-long-short-term-memory-networks-in-python/


一对多使用RepeatVector()将单个量转换为多类分类所需的序列

def test_one_to_many(self):
        params = dict(
            input_dims=[1, 10], activation='tanh',
            return_sequences=False, output_dim=3
        ),
        number_of_times = 4
        model = Sequential()
        model.add(RepeatVector(number_of_times, input_shape=(10,)))

        model.add(LSTM(output_dim=params[0]['output_dim'],
                       activation=params[0]['activation'],
                       inner_activation='sigmoid',
                       return_sequences=True,
                       ))
        relative_error, keras_preds, coreml_preds = simple_model_eval(params, model)
        # print relative_error, '\n', keras_preds, '\n', coreml_preds, '\n'
        for i in range(len(relative_error)):
            self.assertLessEqual(relative_error[i], 0.01) 

来源:https://www.programcreek.com/python/example/89689/keras.layers.RepeatVector

替代一对多

model.add(RepeatVector(number_of_times, input_shape=input_shape))
model.add(LSTM(output_size, return_sequences=True))

来源:Many to one and many to many LSTM examples in Keras


多对一二分类loss=binary_crossentropyactivation=sigmoid,全连接输出层的维数为1(Dense(1)),输出一个标量,01)

model = Sequential()
model.add(Embedding(5000, 32, input_length=500))
model.add(LSTM(100, dropout=0.2, recurrent_dropout=0.2))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])        
print(model.summary())
model.fit(X_train, y_train, epochs=3, batch_size=64)
# Final evaluation of the model
scores = model.evaluate(X_test, y_test, verbose=0)

多对多多类分类loss=sparse_categorial_crossentropyactivation=softmax,需要目标的one-hot编码,ground truth数据,full-连接的输出层为 7 (Dense71)) 输出一个 7 维向量,其中 7 个类是 one-hot 编码的)

from keras.models import Sequential
from keras.layers import *

model = Sequential()
model.add(Embedding(5000, 32, input_length=500))
model.add(LSTM(100, dropout=0.2, recurrent_dropout=0.2))
model.add(Dense(7, activation='softmax'))
model.compile(loss='sparse_categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

model.summary()

cf Keras LSTM multiclass classification

替代多对多使用TimeDistributed层cf https://machinelearningmastery.com/timedistributed-layer-for-long-short-term-memory-networks-in-python/进行描述

from keras.models import Sequential
from keras.layers import Dense
from keras.layers import TimeDistributed
from keras.layers import LSTM
# prepare sequence
length = 5
seq = array([i/float(length) for i in range(length)])
X = seq.reshape(1, length, 1)
y = seq.reshape(1, length, 1)
# define LSTM configuration
n_neurons = length
n_batch = 1
n_epoch = 1000
# create LSTM
model = Sequential()
model.add(LSTM(n_neurons, input_shape=(length, 1), return_sequences=True))
model.add(TimeDistributed(Dense(1)))
model.compile(loss='mean_squared_error', optimizer='adam')
print(model.summary())
# train LSTM
model.fit(X, y, epochs=n_epoch, batch_size=n_batch, verbose=2)
# evaluate
result = model.predict(X, batch_size=n_batch, verbose=0)
for value in result[0,:,0]:
    print('%.1f' % value)

来源:https://machinelearningmastery.com/timedistributed-layer-for-long-short-term-memory-networks-in-python/

【讨论】:

感谢您的回复!你能澄清一下你所说的“封闭数量”是什么意思吗? 另外,我不认为是 Dense 层使第一个示例成为“一对一”的。是因为输入形状是(1,1)吗?即使没有 Dense 层,NN 也会成功输出单个标量。我的问题不在于如何以及在何处使用这些网络(图像、文字等,虽然是有用的知识),而是什么使 LSTM NN 成为一对一、多对一的。输入形状?输出形状?特别是在一对一的例子中,如果我将输入形状从(1,1)更改为(1,2)或(2,1),它仍然是一对一的吗? Dense 始终是全连接层,这就是为什么它在几乎所有模型中都用作输出层的原因。 封闭数量的意思是作为一个单位,要么选择一个数量作为一个单位,要么选择多个数量作为一个单位。您根据问题选择架构,即如果您想在多个类别中分类句子,您选择多对多,如果您想检测单个图像是否包含鸟,您选择一对一。如果您更改输入形状,网络仍然可以是一对一的,但是您不允许设置时间步数,这必须固定为 1。 我通过实验注意到,如果定义 LSTM(4),那么它会输出 4 个标量的向量,但是当我们将它连接到 Dense 时,由于 Dense 层,整个网络会输出单个值.或者,如果我们想要一个输入和一个输出,而不需要任何其他层,我们可以定义具有输入形状 (1,1) 的 LSTM(1)。对吗? 对于一对多,我可以定义一个具有输入形状 (1,1) 的单层 LSTM(3)。在这种情况下,NN 将接受单个标量作为输入并输出 3 个标量作为单个向量的输出。这是一个输入多输出吗?

以上是关于我们如何在 Keras 中定义一对一、一对多、多对一和多对多的 LSTM 神经网络? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

如何在 DynamoDB 中建模一对一、一对多和多对多关系

SQLAlchemy_定义(一对一/一对多/多对多)关系

Mybatis 高级映射,一对一,一对多,多对多映射

mybatis的一对多,多对一,以及多对对的配置和使用

数据库中根据数据一对一,一对多,多对多关系设计

EF Core 一对一 一对多 多对多 关系定义