具有 fasttext 词嵌入的 Keras 模型

Keras model with fasttext word embedding

我正在尝试学习一种语言模型,以使用 keras 给定所有前面的单词来预测句子的最后一个单词。我想使用学习的快速文本嵌入模型嵌入我的输入。

我设法预处理了我的文本数据并嵌入了使用 fasttext。我的训练数据由每个 40 个标记的句子组成。我创建了 2 个 np 数组,X 和 y 作为输入,y 是我想要预测的。

X 的形状为 (44317, 39, 300),例句数量为 44317,每个句子中的标记数量为 39,词嵌入维度为 300。

y 的形状 (44317, 300) 是每个示例中句子最后一个标记的嵌入。

我的keras模型代码如下(灵感来自this

#importing all the needed tensorflow.keras components
model = Sequential()  
model.add(InputLayer((None, 300)))
model.add(LSTM(100, return_sequences=True))
model.add(LSTM(100))
model.add(Dense(100, activation='relu'))
model.add(Dense(300, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.fit(X, y, batch_size=128, epochs=20)
model.save('model.h5')

但是,我在这个模型上训练时得到的准确率非常低(大约 1.5%)。我认为我误解了 keras 模型的某些组件,就好像我没有嵌入我的输入并添加一个额外的嵌入层而不是 InputLayer 我得到大约 60% 的准确度。

我的主要疑问是我的第二个 Dense 层上的“300”值,因为我读到这应该对应于我的词嵌入模型的词汇量大小(即 48000),但是如果我输入的不是 300我收到尺寸错误。所以我知道我做错了什么,但我找不到解决方法。

PS : 我还尝试了 y = to_categorical(y, num_classes=vocab_size) 和 vocab_size 我的词嵌入的词汇量,并通过在第二个 Dense 中将 300 更改为相同的值,但是它会尝试创建一个形状数组 (13295100, 48120 ) 而不是我所期望的:(44317, 48120).

在下一句预测任务中训练 RNN 模型非常困难。 LSTM/GRU 没有足够的资源从文本中提取足够的特征。

有两种方法可以解决问题:

  1. 预测字符而不是单词 class
  2. 使用变压器模型。比如Bert,擅长特征提取和masked word预测

如果您真的想使用 Fasttext 中的词向量,则必须使用权重矩阵和 Embedding 层将它们合并到您的模型中。 embedding层的目标是将代表一个句子的每个整数序列映射到其对应的300维向量表示:

import gensim.downloader as api
import numpy as np
import tensorflow as tf

def load_doc(filename):
    file = open(filename, 'r')
    text = file.read()
    file.close()
    return text

fasttext = api.load("fasttext-wiki-news-subwords-300")
embedding_dim = 300

in_filename = 'data.txt'
doc = load_doc(in_filename)
lines = doc.split('\n')

tokenizer = tf.keras.preprocessing.text.Tokenizer()
tokenizer.fit_on_texts(lines)
text_sequences = tokenizer.texts_to_sequences(lines)
text_sequences = tf.keras.preprocessing.sequence.pad_sequences(text_sequences, padding='post')
vocab_size = len(tokenizer.word_index) + 1

text_sequences = np.array(text_sequences)
X, y = text_sequences[:, :-1], text_sequences[:, -1]
y = tf.keras.utils.to_categorical(y, num_classes=vocab_size)
max_length = X.shape[1]

weight_matrix = np.zeros((vocab_size, embedding_dim))
for word, i in tokenizer.word_index.items():
    try:
        embedding_vector = fasttext[word]
        weight_matrix[i] = embedding_vector
    except KeyError:
        weight_matrix[i] = np.random.uniform(-5, 5, embedding_dim)

sentence_input = tf.keras.layers.Input(shape=(max_length,))
x = tf.keras.layers.Embedding(vocab_size, embedding_dim, weights=[weight_matrix],
                              input_length=max_length)(sentence_input)

x = tf.keras.layers.LSTM(100, return_sequences=True)(x)
x = tf.keras.layers.LSTM(100)(x)
x = tf.keras.layers.Dense(100, activation='relu')(x)
output = tf.keras.layers.Dense(vocab_size, activation='softmax')(x)
model = tf.keras.Model(sentence_input, output)

model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.fit(X, y, batch_size=5, epochs=20)                                 

请注意,我正在使用您链接的 tutorial 中的数据集和预处理步骤。