我有一串字母跟在"语法"后面。在我的训练集上我也有布尔标签来表示字符串是否符合"语法"与否。基本上,我的模型试图学习确定一串字母是否遵循规则。这是一个相当简单的问题(我从课本上抄的)。
我像这样生成我的数据集:
def generate_dataset(size):
good_strings = [string_to_ids(generate_string(embedded_reber_grammar))
for _ in range(size // 2)]
bad_strings = [string_to_ids(generate_corrupted_string(embedded_reber_grammar))
for _ in range(size - size // 2)]
all_strings = good_strings + bad_strings
X = tf.ragged.constant(all_strings, ragged_rank=1)
# X = X.to_tensor(default_value=0)
y = np.array([[1.] for _ in range(len(good_strings))] +
[[0.] for _ in range(len(bad_strings))])
return X, y
注意X = X.to_tensor(default_value=0)
这行。如果这一行被注释掉,我的模型就能很好地学习。但是,如果它没有被注释掉,它就无法学习,验证集的执行与概率(50-50)相同。
这是我的实际模型:
np.random.seed(42)
tf.random.set_seed(42)
embedding_size = 5
model = keras.models.Sequential([
keras.layers.InputLayer(input_shape=[None], dtype=tf.int32, ragged=True),
keras.layers.Embedding(input_dim=len(POSSIBLE_CHARS) + 1, output_dim=embedding_size),
keras.layers.GRU(30),
keras.layers.Dense(1, activation="sigmoid")
])
optimizer = keras.optimizers.SGD(lr=0.02, momentum = 0.95, nesterov=True)
model.compile(loss="binary_crossentropy", optimizer=optimizer, metrics=["accuracy"])
history = model.fit(X_train, y_train, epochs=5, validation_data=(X_valid, y_valid))
我使用0
作为密集张量的默认值。strings_to_ids
对任何值都不使用0,而是从1开始。此外,当我切换到使用密集张量时,我将ragged=True
更改为False.
,我不知道为什么使用密集张量会导致模型失败,因为我之前在类似的练习中使用过密集张量。
有关更多细节,请参阅书中的解决方案(练习8)或我自己的协作笔记本。
所以答案是密集张量的形状在训练集和验证集上是不同的。这是因为最长序列在两组之间的长度不同(与测试集相同)。