Использование kken tokenizer для новых слов не в обучающем наборе

В настоящее время я использую Kosen Tokenizer для создания индекса слова, а затем сопоставляя этот индекс слова с импортированным словарем GloVe для создания матрицы внедрения. Тем не менее, проблема заключается в том, что это, по-видимому, лишает одно из преимуществ использования вложения слова-вектора, поскольку при использовании обучаемой модели для предсказаний, если она сталкивается с новым словом, которое не в индексе слова токенизатора, оно удаляет его из последовательности,

#fit the tokenizer
tokenizer = Tokenizer()
tokenizer.fit_on_texts(texts)
word_index = tokenizer.word_index

#load glove embedding into a dict
embeddings_index = {}
dims = 100
glove_data = 'glove.6B.'+str(dims)+'d.txt'
f = open(glove_data)
for line in f:
    values = line.split()
    word = values[0]
    value = np.asarray(values[1:], dtype='float32')
    embeddings_index[word] = value
f.close()

#create embedding matrix
embedding_matrix = np.zeros((len(word_index) + 1, dims))
for word, i in word_index.items():
    embedding_vector = embeddings_index.get(word)
    if embedding_vector is not None:
        # words not found in embedding index will be all-zeros.
        embedding_matrix[i] = embedding_vector[:dims]

#Embedding layer:
embedding_layer = Embedding(embedding_matrix.shape[0],
                        embedding_matrix.shape[1],
                        weights=[embedding_matrix],
                        input_length=12)

#then to make a prediction
sequence = tokenizer.texts_to_sequences(["Test sentence"])
model.predict(sequence)

Итак, есть ли способ, по которому я могу использовать токенизатор для преобразования предложений в массив и по-прежнему использовать как можно больше слова GloVe, а не только те, которые отображаются в моем учебном тексте?

Редактирование: при дальнейшем созерцании, я предполагаю, что одним из вариантов было бы добавить текст или тексты в тексты, в которые помещается токенизатор, который включает в себя список ключей в словаре перчаток. Хотя это может испортить некоторые статистические данные, если я хочу использовать tf-idf. Есть ли предпочтительный способ сделать это или другой лучший подход?

Ответ 1

Я бы попробовал другой подход. Основная проблема в том, что ваш word_index основан на ваших тренировочных данных. Попробуйте это:

#load glove embedding into a dict
embeddings_index = {}
dims = 100
glove_data = 'glove.6B.'+str(dims)+'d.txt'
f = open(glove_data)
for line in f:
    values = line.split()
    word = values[0]
    value = np.asarray(values[1:], dtype='float32')
    embeddings_index[word] = value
f.close()

word_index = {w: i for i, w in enumerate(embeddings_index.keys(), 1)}

#create embedding matrix
embedding_matrix = np.zeros((len(word_index) + 1, dims))
for word, i in word_index.items():
    embedding_vector = embeddings_index.get(word)
    if embedding_vector is not None:
        # words not found in embedding index will be all-zeros.
        embedding_matrix[i] = embedding_vector[:dims]

Теперь ваш embedding_matrix содержит все работы GloVe.

Для токенизации ваших текстов вы можете использовать что-то вроде этого:

from keras.preprocessing.text import text_to_word_sequence

def texts_to_sequences(texts, word_index):
    for text in texts:
        tokens = text_to_word_sequence(text)
        yield [word_index.get(w) for w in tokens if w in word_index]

sequence = texts_to_sequences(['Test sentence'], word_index)

Ответ 2

В Keras Tokenizer у вас есть параметр oov_token. Просто выберите свой токен, и неизвестные слова будут иметь его.

tokenizer_a = Tokenizer(oov_token=1)
tokenizer_b = Tokenizer()
tokenizer_a.fit_on_texts(["Hello world"])
tokenizer_b.fit_on_texts(["Hello world"])

Выходы

In [26]: tokenizer_a.texts_to_sequences(["Hello cruel world"])
Out[26]: [[2, 1, 3]]

In [27]: tokenizer_b.texts_to_sequences(["Hello cruel world"])
Out[27]: [[1, 2]]