Gok*_*tug 5 python deep-learning keras tensorflow recurrent-neural-network
据我所知和研究,数据集中的序列可以有不同的长度;我们不需要填充或截断它们,前提是训练过程中的每个批次都包含相同长度的序列。
为了实现和应用它,我决定将批量大小设置为 1,并在 IMDB 电影分类数据集上训练我的 RNN 模型。我添加了我在下面编写的代码。
import matplotlib.pyplot as plt
import tensorflow as tf
from tensorflow.keras.datasets import imdb
from tensorflow.keras import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.layers import SimpleRNN
from tensorflow.keras.layers import Embedding
max_features = 10000
batch_size = 1
(x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=max_features)
model = Sequential()
model.add(Embedding(input_dim=10000, output_dim=32))
model.add(SimpleRNN(units=32, input_shape=(None, 32)))
model.add(Dense(1, activation="sigmoid"))
model.compile(optimizer="rmsprop",
loss="binary_crossentropy", metrics=["acc"])
history = model.fit(x_train, y_train,
batch_size=batch_size, epochs=10,
validation_split=0.2)
Run Code Online (Sandbox Code Playgroud)
acc = history.history["acc"]
loss = history.history["loss"]
val_acc = history.history["val_acc"]
val_loss = history.history["val_loss"]
epochs = range(len(acc) + 1)
plt.plot(epochs, acc, "bo", label="Training Acc")
plt.plot(epochs, val_acc, "b", label="Validation Acc")
plt.title("Training and Validation Accuracy")
plt.legend()
plt.figure()
plt.plot(epochs, loss, "bo", label="Training Loss")
plt.plot(epochs, val_loss, "b", label="Validation Loss")
plt.title("Training and Validation Loss")
plt.legend()
plt.show()
Run Code Online (Sandbox Code Playgroud)
我遇到的错误是由于输入numpy数组中的列表组件而无法将输入转换为张量格式。但是,当我更改它们时,我继续遇到类似的错误。
错误信息:
ValueError: Failed to convert a NumPy array to a Tensor (Unsupported object type list).
Run Code Online (Sandbox Code Playgroud)
我无法处理这个问题。在这一点上有人可以帮助我吗?
有两个问题。您需要pad_sequences
首先在文本序列上使用。input_shape
并且中也没有这样的参数SimpleRNN
。尝试使用以下代码:
max_features = 20000 # Only consider the top 20k words
maxlen = 200 # Only consider the first 200 words of each movie review
batch_size = 1
(x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=max_features)
print(len(x_train), "Training sequences")
print(len(x_test), "Validation sequences")
x_train = tf.keras.preprocessing.sequence.pad_sequences(x_train, maxlen=maxlen)
x_test = tf.keras.preprocessing.sequence.pad_sequences(x_test, maxlen=maxlen)
model = Sequential()
model.add(Embedding(input_dim=max_features, output_dim=32))
model.add(SimpleRNN(units=32))
model.add(Dense(1, activation="sigmoid"))
model.compile(optimizer="rmsprop", loss="binary_crossentropy", metrics=["acc"])
history = model.fit(x_train, y_train, batch_size=batch_size,
epochs=10, validation_split=0.2)
Run Code Online (Sandbox Code Playgroud)
这是官方的代码示例,也许对你有帮助。
根据您的评论和信息,似乎可以使用可变长度输入序列,也请检查此和此。但我仍然可以说,在大多数情况下,从业者更喜欢pad
统一长度的序列;因为它有说服力。选择非均匀或可变的输入序列长度是某种特殊情况;类似于我们想要视觉模型的可变输入图像大小。
但是,在这里我们将添加有关padding
如何mask
在训练时间中取出填充值的信息,这在技术上似乎是可变长度输入训练。希望这能说服你。我们先来了解一下pad_sequences
做什么。通常在序列数据中,很常见的情况是每个训练样本的长度不同。让我们考虑以下输入:
raw_inputs = [
[711, 632, 71],
[73, 8, 3215, 55, 927],
[83, 91, 1, 645, 1253, 927],
]
Run Code Online (Sandbox Code Playgroud)
这3个训练样本的长度不同,分别为3、5、6。接下来我们要做的是通过添加一些值(通常是0
或-1
)来使它们的长度相等 - 无论是在序列的开头还是结尾。
tf.keras.preprocessing.sequence.pad_sequences(
raw_inputs, maxlen=6, dtype="int32", padding="pre", value=0.0
)
array([[ 0, 0, 0, 711, 632, 71],
[ 0, 73, 8, 3215, 55, 927],
[ 83, 91, 1, 645, 1253, 927]], dtype=int32)
Run Code Online (Sandbox Code Playgroud)
我们可以设置padding = "post"
在序列末尾设置填充值。但它建议"post"
在使用RNN
图层时使用填充,以便能够使用CuDNN
图层的实现。但是,仅供参考,您可能会注意到我们设置了maxlen = 6
最高输入序列长度。但它不一定是最高的输入序列长度,因为如果数据集变大,计算成本可能会很高。我们可以将其设置为5
假设我们的模型可以在这个长度内学习特征表示,它是一种超参数。这带来了另一个参数truncating
。
tf.keras.preprocessing.sequence.pad_sequences(
raw_inputs, maxlen=5, dtype="int32", padding="pre", truncating="pre", value=0.0
)
array([[ 0, 0, 711, 632, 71],
[ 73, 8, 3215, 55, 927],
[ 91, 1, 645, 1253, 927]], dtype=int32
Run Code Online (Sandbox Code Playgroud)
好的,现在我们有了一个填充的输入序列,所有输入的长度都是统一的。现在,我们可以mask
在训练时间内删除这些额外的填充值。我们将告诉模型数据的某些部分正在填充,并且这些部分应该被忽略。这种机制就是掩蔽。因此,这是一种告诉序列处理层输入中缺少某些时间步长的方法,因此在处理数据时应跳过这些时间步长。在模型中引入输入掩码有三种方法Keras
:
keras. layers.Masking layer
.keras.layers.Embedding
图层mask_zero=True
。RNN
。这里我们只通过配置图层来展示Embedding
。它有一个名为默认mask_zero
设置的参数。False
如果我们设置它,True
那么0
将跳过序列中包含的索引。条目表示在处理过程中False
应忽略相应的时间步长。
padd_input = tf.keras.preprocessing.sequence.pad_sequences(
raw_inputs, maxlen=6, dtype="int32", padding="pre", value=0.0
)
print(padd_input)
embedding = tf.keras.layers.Embedding(input_dim=5000, output_dim=16, mask_zero=True)
masked_output = embedding(padd_input)
print(masked_output._keras_mask)
[[ 0 0 0 711 632 71]
[ 0 73 8 3215 55 927]
[ 83 91 1 645 1253 927]]
tf.Tensor(
[[False False False True True True]
[False True True True True True]
[ True True True True True True]], shape=(3, 6), dtype=bool)
Run Code Online (Sandbox Code Playgroud)
以下是它在类中的计算方式Embedding(Layer)
。
def compute_mask(self, inputs, mask=None):
if not self.mask_zero:
return None
return tf.not_equal(inputs, 0)
Run Code Online (Sandbox Code Playgroud)
这里有一个问题,如果我们设置mask_zero
为True
,结果索引0
不能在词汇表中使用。根据文档
mask_zero:布尔值,输入值 0 是否是应屏蔽掉的特殊“填充”值。当使用可能采用可变长度输入的循环层时,这非常有用。如果是
True
,则模型中的所有后续层都需要支持屏蔽,否则将引发异常。如果 mask_zero 设置为 True,则索引 0 不能在词汇表中使用(input_dim 应等于词汇表大小 + 1)。
max_features + 1
所以,我们至少要使用。这是对此的一个很好的解释。
这是使用这些代码的完整示例。
# get the data
(x_train, y_train), (_, _) = imdb.load_data(num_words=max_features)
print(x_train.shape)
# check highest sequence lenght
max_list_length = lambda list: max( [len(i) for i in list])
print(max_list_idx(x_train))
max_features = 20000 # Only consider the top 20k words
maxlen = 350 # Only consider the first 350 words out of `max_list_idx(x_train)`
batch_size = 512
print('Length ', len(x_train[0]), x_train[0])
print('Length ', len(x_train[1]), x_train[1])
print('Length ', len(x_train[2]), x_train[2])
# (1). padding with value 0 at the end of the sequence - padding="post", value=0.
# (2). truncate 'maxlen' words
# out of `max_list_idx(x_train)` at the end - maxlen=maxlen, truncating="post"
x_train = tf.keras.preprocessing.sequence.pad_sequences(x_train,
maxlen=maxlen, dtype="int32",
padding="post", truncating="post",
value=0.)
print('Length ', len(x_train[0]), x_train[0])
print('Length ', len(x_train[1]), x_train[1])
print('Length ', len(x_train[2]), x_train[2])
Run Code Online (Sandbox Code Playgroud)
您的模型定义现在应该是
model = Sequential()
model.add(Embedding(
input_dim=max_features + 1,
output_dim=32,
mask_zero=True))
model.add(SimpleRNN(units=32))
model.add(Dense(1, activation="sigmoid"))
Run Code Online (Sandbox Code Playgroud)
model.compile(optimizer="rmsprop", loss="binary_crossentropy", metrics=["acc"])
history = model.fit(x_train, y_train,
batch_size=256,
epochs=1, validation_split=0.2)
639ms/step - loss: 0.6774 - acc: 0.5640 - val_loss: 0.5034 - val_acc: 0.8036
Run Code Online (Sandbox Code Playgroud)
参考
归档时间: |
|
查看次数: |
153 次 |
最近记录: |