Word2Vec Subsampling - реализация - PullRequest
       71

Word2Vec Subsampling - реализация

0 голосов
/ 08 ноября 2019

Я реализую модель Skipgram , как в Pytorch, так и в Tensorflow2. У меня есть сомнения по поводу реализации подвыборки частых слов. Дословно из статьи вероятность подсэмплирования слова wi вычисляется как

enter image description here

, где t - пользовательский порог (обычно небольшойзначение, такое как 0,0001 ) и f - это частота слова в документе. Хотя авторы реализовали его другим, но почти эквивалентным способом, давайте придерживаться этого определения.

При вычислении P(wi) мы можем получить отрицательные значения. Например, предположим, что у нас есть 100 слов, и одно из них появляется чрезвычайно часто, чем другие (как в случае с моим набором данных).

import numpy as np
import seaborn as sns

np.random.seed(12345)

# generate counts in [1, 20]
counts = np.random.randint(low=1, high=20, size=99)

# add an extremely bigger count
counts = np.insert(counts, 0, 100000)

# compute frequencies
f = counts/counts.sum()

# define threshold as in paper
t = 0.0001

# compute probabilities as in paper
probs = 1 - np.sqrt(t/f)
sns.distplot(probs);

В: Какой правильный путь креализовать подвыборку с использованием этой «вероятности»?

В качестве дополнительной информации я видел, что в keras функция keras.preprocessing.sequence.make_sampling_table использует другой подход:

def make_sampling_table(size, sampling_factor=1e-5):
    """Generates a word rank-based probabilistic sampling table.
    Used for generating the `sampling_table` argument for `skipgrams`.
    `sampling_table[i]` is the probability of sampling
    the i-th most common word in a dataset
    (more common words should be sampled less frequently, for balance).
    The sampling probabilities are generated according
    to the sampling distribution used in word2vec:
    ```
    p(word) = (min(1, sqrt(word_frequency / sampling_factor) /
        (word_frequency / sampling_factor)))
    ```
    We assume that the word frequencies follow Zipf's law (s=1) to derive
    a numerical approximation of frequency(rank):
    `frequency(rank) ~ 1/(rank * (log(rank) + gamma) + 1/2 - 1/(12*rank))`
    where `gamma` is the Euler-Mascheroni constant.
    # Arguments
        size: Int, number of possible words to sample.
        sampling_factor: The sampling factor in the word2vec formula.
    # Returns
        A 1D Numpy array of length `size` where the ith entry
        is the probability that a word of rank i should be sampled.
    """
    gamma = 0.577
    rank = np.arange(size)
    rank[0] = 1
    inv_fq = rank * (np.log(rank) + gamma) + 0.5 - 1. / (12. * rank)
    f = sampling_factor * inv_fq

    return np.minimum(1., f / np.sqrt(f))

1 Ответ

1 голос
/ 09 ноября 2019

Я склонен доверять развернутому коду больше, чем бумажным рецензиям, особенно в случае, подобном word2vec, где исходный текст авторов word2vec.c , выпущенный авторами статьи, широко использовался и служил в качествешаблон для других реализаций. Если мы посмотрим на его механизм субсэмплинга ...

        if (sample > 0) {
          real ran = (sqrt(vocab[word].cn / (sample * train_words)) + 1) * (sample * train_words) / vocab[word].cn;
          next_random = next_random * (unsigned long long)25214903917 + 11;
          if (ran < (next_random & 0xFFFF) / (real)65536) continue;
        }

... мы увидим, что те слова с крошечным счетчиком (.cn), которые могли бы дать отрицательные значения в исходной формуле вместо этого, дают значения большечем 1.0, и, следовательно, никогда не может быть меньше, чем long -случайно-замаскировано и масштабировано, чтобы никогда не быть больше 1.0 ((next_random & 0xFFFF) / (real)65536). Таким образом, кажется, что намерение авторов было, чтобы все отрицательные значения исходной формулы означали «никогда не отбрасывать».

Согласно комментариям и реализации keras make_sampling_table(), они не обращаются к фактическим частотам слов вообще. Вместо этого они предполагают Zipf-подобное распределение, основанное на порядке ранжирования слов, для синтеза моделируемой частоты слов.

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

Я не уверен, почему они выбрали это приближение. Возможно, другие аспекты их обычных процессов не поддерживали истинные частоты до этого шага, и они ожидают, что всегда будут работать с текстами на естественном языке, где предполагаемые частоты будут в целом истинными.

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

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

В частности, представьте раздачу с одним токеном миллион раз, затем сотня токенов появляется всего по 10 раз каждый. Порядок этих сотен токенов в списке рангов произвольный - действительно, они все связаны по частоте. Но подход, основанный на моделировании, путем подгонки распределения Zipfian к этому порядку, фактически будет выбирать каждую из них очень по-разному. Одно слово из 10 появлений, достаточно удачное для того, чтобы быть на позиции 2-го ранга, будет гораздо более урезанным, как если бы оно было гораздо более частым. И значение «высокой головы» 1-го ранга, при условии, что его истинная частота * занижена *, будет менее пониженным, чем в противном случае. Ни один из этих эффектов не кажется полезным, или в духе опции частого выборочного сокращения слов, которая должна только «прореживать» очень частые слова и во всех случаях оставлять слова примерно одинаковой частоты друг с другом в исходном корпусе. эквивалентно представлены друг другу в корпусе с пониженной выборкой.

Итак, для вашего случая я бы выбрал исходную формулу (вероятность отбрасывания, которая требует специальной обработки отрицательных значений), или практическую / инвертированную реализацию word2vec.c (вероятность сохранения того, что насыщает на уровне 1,0), а не приближение в стиле керас.

(AЭто совершенно отдельное примечание, которое, тем не менее, может иметь отношение к вашему набору данных / целям, если вы используете отрицательную выборку: есть другой параметр, управляющий относительной выборкой отрицательных примеров, часто фиксируемый в 0.75 в ранних реализациях, который один из предложенных документов может быть полезен для раздачи токенов не на естественном языке и для конечного использования, связанного с рекомендациями . Этот параметр называется ns_exponent в реализации Python gensim, но просто фиксированное значение power, внутреннее для предварительного расчета таблицы выборки в исходном word2vec.c коде .)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...