Word2Vec Skipgrams - Должны ли пары охватывать предложения? - PullRequest
0 голосов
/ 28 августа 2018

Фон

Я пытаюсь обучить модели Skip-грамматики word2vec, используя отрицательную выборку. из того, что я понимаю, мне нужно создать пары (цель, контекст) и метку, где 0 = не в контексте и 1 = в контексте.

В чем я не уверен:

Должны ли мы составлять пары скипграмм за предложением? или мы должны свести предложения в одно большое предложение и сгенерировать скипграммы из этого? Другими словами, должны ли сгенерированные пары охватывать предложения?

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

data = ['this is some stuff.', 'I have a cookie.']

Результаты

...SNIP...
[some, have]
[stuff, this]
[stuff, is]
[stuff, some]
[stuff, i]
[stuff, have]
[stuff, a]
[i, is]
[i, some]
[i, stuff]
[i, have]
[i, a]
[i, cookie]
[have, some]
[have, stuff]
...SNIP...

Мы можем видеть, что есть пары, которые простираются через предложения

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

...SNIP...
[some, stuff]
[stuff, this]
[stuff, is]
[stuff, some]
[i, have]
[i, a]
[i, cookie]
[have, i]
[have, a]
[have, cookie]
...SNIP...

То, что я сделал до сих пор.

Получить данные

from sklearn.datasets import fetch_20newsgroups
newsgroups_train = fetch_20newsgroups(subset='train',
                          remove=('headers', 'footers', 'quotes'))

Инициализация некоторых переменных

vocabulary_size = 8
window_size = 3 
neg_samples = 0.0

Свести предложения в одну большую последовательность

sents = newsgroups_train.data
tokenizer = Tokenizer(num_words= vocabulary_size, lower=True, filters=filters)
tokenizer.fit_on_texts(sents)
word_index_inv = {v: k for k, v in tokenizer.word_index.items()}
sequences = tokenizer.texts_to_sequences(sents)
couples, labels = skipgrams(list(itertools.chain.from_iterable(sequences)), vocabulary_size=vocabulary_size, window_size=window_size, shuffle=False, negative_samples=neg_samples)
word_target, word_context = zip(*couples)
word_target = np.array(word_target, dtype="int32")
word_context = np.array(word_context, dtype="int32")

OR

Разделить набор данных на предложения и создать пары на основе каждого предложения.

sents = [nltk.sent_tokenize(s) for s in newsgroups_train.data]
sents = list(itertools.chain.from_iterable(sents))

tokenizer = Tokenizer(num_words= vocabulary_size, lower=True, filters=filters)
tokenizer.fit_on_texts(sents)
word_index_inv = {v: k for k, v in tokenizer.word_index.items()}
sequences = tokenizer.texts_to_sequences(sents)    
couples = []
labels = []
for seq in sequences:
    c,l = skipgrams(seq, vocabulary_size=vocabulary_size, 
            window_size=window_size, shuffle=False, 
            negative_samples=neg_samples)
    couples.extend(c)
    labels.extend(l)
word_target, word_context = zip(*couples)
word_target = np.array(word_target, dtype="int32")
word_context = np.array(word_context, dtype="int32")

Распечатайте наши слова

for couple in couples:
    print('[{}, {}]'.format(word_index_inv[couple[0]], word_index_inv[couple[1]]))

1 Ответ

0 голосов
/ 29 августа 2018

Обычно это не так важно, так или иначе.

Даже когда библиотеки / API говорят о «предложениях», они действительно означают «тексты», которые могут быть несколькими предложениями.

Наихудший случай, если вы столкнетесь с некоторыми контекстами, охватывающими тексты, которые не имеют существенного отношения, это то, что это добавляет немного шума к обучению ... что может потребовать немного больше обучения, чтобы достичь оптимальности для другого нешумного контексты. Но часто бегущие тексты на самом деле связаны из одного и того же исходного источника, поэтому такие контексты могут по-прежнему отражать реальные полезные шаблоны и, таким образом, быть чистым позитивом по сравнению с небольшими фрагментами текста.

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

...