如何在Keras中定义一对一、一对多、多对一和多对多的LSTM神经网络?

9
我正在阅读this一篇关于循环神经网络的文章,想要了解如何在Keras中表达一对一、一对多、多对一和多对多的LSTM神经网络。我已经阅读了许多关于RNN的文章,并理解了LSTM NN的工作原理,特别是梯度消失、LSTM单元格、它们的输出和状态、序列输出等等。然而,我在用Keras表达所有这些概念时遇到了问题。
首先,我使用LSTM层创建了以下玩具神经网络。
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乘以3。据我所知,这意味着输入是一个包含2个向量的序列,每个向量有3个特征,因此我的输入必须是一个形状为(n_examples, 2, 3)的3D张量。就“序列”而言,输入是长度为2的序列,序列中的每个元素由3个特征表示(如果我理解错误,请纠正我)。当我调用predict时,它返回一个带有单个标量的二维张量。

问题1:这是一对一还是另一种类型的LSTM网络?

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

问题2:我们所说的“一个/多个输入/输出”是指“一个/多个”标量、向量、序列等,一个/多个什么?

问题3:有人可以给出Keras中每种类型网络的简单工作示例吗:1-1、1-M、M-1和M-M?

PS:我在一个线程中提出了多个问题,因为它们非常相近且相互关联。


1
https://dev59.com/C1gQ5IYBdhLWcg3wRB3K - ralf htp
1
@nuric 感谢您提供的参考,但是这篇文章并没有完全回答我的问题。特别是,我的例子是一对一还是多对一,为什么?如果LSTM的输出是一个向量,我们是否将输出视为多个(标量)或一个(向量)? - fade2black
2
你可以将其视为一个向量。许多“one”等术语是指时间步长而不是特征。 - nuric
1个回答

11
这里的一对一一对多多对一多对多仅存在于RNN / LSTM或处理顺序(时间)数据的网络中,CNN处理空间数据,因此不存在这种区别。所以总是涉及多个时间步长 / 序列
不同的类型描述了输入和输出的形状及其分类。对于输入,一个意味着单个输入量被分类为封闭数量,而多个意味着一系列数量(即图像序列,单词序列)被分类为封闭数量。对于输出,一个表示输出是标量(二元分类,即是鸟不是鸟),01多个表示输出是one-hot编码向量,每个类别都有一个维度(多类分类,即是麻雀是知更鸟,...),例如三个类别:001, 010, 100
在下面的示例中,使用图像和图像序列作为要分类的量,或者您可以使用单词或...和单词序列(句子)或...: 一对一:单个图像(或单词,...)被分类为单个类别(二元分类),即这是一只鸟还是不是。

一对多:单个图像(或单词等)属于多个类别

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

多对多:图像序列(或单词等)被分类为多个类别

参见 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


一对一激活函数=sigmoid(默认值)损失函数=均方误差

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/

该文章介绍了如何在Python中使用TimeDistributed层来提高长短时记忆网络的性能。它解释了什么是TimeDistributed层以及如何将其与LSTM网络结合使用。本文还提供了示例代码和说明,帮助读者更好地理解如何实现这些技术。

one-to-many 使用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))

来源: Keras中的一对多和多对多LSTM示例


多对一二元分类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,需要对目标、真实数据进行独热编码,完全连接输出层的维度为7(Dense71),输出一个7维向量,其中7个类别被独热编码。

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多类分类

使用TimeDistributed层的备选多对多,参见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/

时间分布层是一种在长短时记忆网络中广泛使用的技术。它允许模型对序列数据进行逐步处理,并将输出传递到下一层。本教程将介绍如何使用Keras库中的时间分布层来改进LSTM模型。


Dense层始终是全连接层,这就是为什么它作为输出层几乎在任何模型中都被使用的原因。"闭合数量"意味着"作为一个单位",无论您选择一个单一的数量作为单位还是多个数量作为单位。您根据问题选择架构,例如,如果您想将句子分类到多个类别中,则选择多对多,如果您想检测单个图像是否包含鸟类,则选择一对一。如果更改输入形状,网络仍然可以是一对一,但是不允许有时间步数,这必须固定为1。 - ralf htp
我通过实验发现,如果定义LSTM(4),它将输出一个由4个标量组成的向量,但是当我们将其连接到Dense层时,整个网络会因为Dense层的缘故输出单个值。另外,如果我们想要单一输入和单一输出而没有其他层,则可以定义输入形状(1,1)的LSTM(1)。对吗? - fade2black
关于一对多,我可以定义一个单层LSTM(3),其输入形状为(1,1)。在这种情况下,神经网络将接受单个标量作为输入,并输出3个标量作为单个向量的输出。这是一输入和多输出吗? - fade2black
只有在指定Dense(1)时才会出现。Dense是全连接的。全连接是一种特殊的层类型,请在网络中搜索此内容。如果有许多输出,则向量始终是one-hot编码的。 - ralf htp
我认为一个向量是单个的还是多个的,仅取决于向量中标量s的数量,而不是向量是one-hot还是dense。我比以前更困惑了。在我提到的那篇文章中,没有提到其他类型的层(如Dense、RepeatedVectors等),这些LSTM网络的种类纯粹是基于LSTM本身解释的。 - fade2black
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接