Используйте Tensorflow и предварительно обученный FastText для встраивания невидимых слов

Я использую предварительно обученную модель fasttext https://github.com/facebookresearch/fastText/blob/master/pretrained-vectors.md).

Я использую Gensim для загрузки модели fasttext. Он может выводить вектор для любых слов, независимо от того, видим ли он или невидим (вне словарного запаса).

from gensim.models.wrappers import FastText
en_model = FastText.load_fasttext_format('../wiki.en/wiki.en')
print(en_model['car'])
print(en_model['carcaryou'])

В тензорном потоке я знаю, что могу использовать приведенный ниже код, чтобы получить обучаемые вложения увиденных слов:

# Embedding layer
embeddings = tf.get_variable('embedding_matrix', [vocab_size, state_size], Trainable=True)
rnn_inputs = tf.nn.embedding_lookup(embeddings, x)

Индексы известных слов получить легко. Однако для этих невидимых слов FastText «предсказывает» их скрытые векторы на основе шаблонов подслов. Невидимые слова не имеют индексов.

В этом случае, как мне использовать тензорный поток для обработки как известных, так и невидимых слов с помощью fasttext?


person Munichong    schedule 30.10.2017    source источник
comment
Можете ли вы использовать tf.cond, чтобы определить, известно ли слово (инструменты для этого см. Tf.lookup) в сочетании с tf.py_func для вызова FastText, если слово неизвестно?   -  person Alexandre Passos    schedule 30.10.2017
comment
@AlexandrePassos Да. Я думаю, это выполнимо. Но что, если я хочу, чтобы встраивание как известных, так и невидимых слов можно было обучить? Для этих невидимых слов мне нужно где-то сохранить их вложения. Я прав?   -  person Munichong    schedule 30.10.2017
comment
Я тоже изо всех сил пытаюсь найти ответ на этот вопрос. Вы поняли это @Munichong?   -  person user1669710    schedule 06.07.2018
comment
@ user1669710 Нет ... Извините   -  person Munichong    schedule 09.07.2018


Ответы (1)


Я нашел обходной путь, используя tf.py_func:

def lookup(arr):
    global model
    global decode

    decoded_arr = decode(arr)
    new_arr = np.zeros((*arr.shape, 300))
    for s, sent in enumerate(decoded_arr):
        for w, word in enumerate(sent):
            try:
                new_arr[s, w] = model.wv[word]
            except Exception as e:
                print(e)
                new_arr[s, w] = np.zeros(300)
    return new_arr.astype(np.float32)

z = tf.py_func(lookup, [x], tf.float32, stateful=True, name=None)

Этот фрагмент кода работает (на французском языке, извините, но это не имеет значения)

import tensorflow as tf
import numpy as np
from gensim.models.wrappers import FastText

model = FastText.load_fasttext_format("../../Tracfin/dev/han/data/embeddings/cc.fr.300.bin")
decode = np.vectorize(lambda x: x.decode("utf-8"))

def lookup(arr):
    global model
    global decode

    decoded_arr = decode(arr)
    new_arr = np.zeros((*arr.shape, 300))
    for s, sent in enumerate(decoded_arr):
        for w, word in enumerate(sent):
            try:
                new_arr[s, w] = model.wv[word]
            except Exception as e:
                print(e)
                new_arr[s, w] = np.zeros(300)
    return new_arr.astype(np.float32)

def extract_words(token):
    # Split characters
    out = tf.string_split([token], delimiter=" ")
    # Convert to Dense tensor, filling with default value
    out = tf.reshape(tf.sparse_tensor_to_dense(out, default_value="<pad>"), [-1])
    return out


textfile = "text.txt"
words = [
    "ceci est un texte hexabromocyclododécanes intéressant qui mentionne des",
    "mots connus et des mots inconnus commeceluici ou celui-là polybromobiphényle",
]

with open(textfile, "w") as f:
    f.write("\n".join(words))

tf.reset_default_graph()
padded_shapes = tf.TensorShape([None])
padding_values = "<pad>"

dataset = tf.data.TextLineDataset(textfile)
dataset = dataset.map(extract_words, 2)
dataset = dataset.shuffle(10000, reshuffle_each_iteration=True)
dataset = dataset.repeat()
dataset = dataset.padded_batch(3, padded_shapes, padding_values)
iterator = tf.data.Iterator.from_structure(
    dataset.output_types, dataset.output_shapes
)
dataset_init_op = iterator.make_initializer(dataset, name="dataset_init_op")
x = iterator.get_next()
z = tf.py_func(lookup, [x], tf.float32, stateful=True, name=None)
sess = tf.InteractiveSession()
sess.run(dataset_init_op)
y, w = sess.run([x, z])
y = decode(y)

print(
    "\nWords out of vocabulary: ",
    np.sum(1 for word in y.reshape(-1) if word not in model.wv.vocab),
)
print("Lookup worked: ", all(model.wv[y[0][0][0]] == w[0][0][0]))

Печать:

Words out of vocabulary:  6
Lookup worked:  True

Оптимизировать не пробовал, особенно цикл поиска, комментарии приветствуются

person ted    schedule 26.07.2018
comment
Это решение для обхода tf.nn.embedding_lookup. Это означает, что вы получаете вектор для каждого слова, если известна хотя бы некоторая символьная n-грамма. Но вложения не поддаются обучению (что-то, что ОП просил в комментарии), даже те, которые используются для увиденных слов. - person lenz; 12.04.2019
comment
Привет, я пытаюсь использовать решение Теда в своем коде. Он работает сам по себе с небольшой доработкой, но когда я использую его для замены части моего кода tf.nn.embedding_lookup, это вызывает ошибку. - person user4343712; 26.09.2019