Что такое встраивание в Керас?

97

В документации Keras неясно, что это на самом деле. Я понимаю, что мы можем использовать это для сжатия входного пространства функций в меньшее. Но как это сделать с точки зрения нейронного дизайна? Это автоэнокдер, RBM?


источник
7
Это таблица поиска, которую можно обучить
gokul_uf
1
Он просто создает и индексирует весовую матрицу; см. мой подробный ответ ниже ( stackoverflow.com/a/53101566/9024698 ).
Outcast
3
Хотя в ответах, получивших наибольшее количество голосов, говорится, что это умножение матриц, исходный код и другие ответы показывают, что на самом деле это просто обучаемая матрица. Входные слова просто выбирают соответствующую строку в этой матрице.
Daniel Möller

Ответы:

67

Насколько мне известно, слой Embedding представляет собой простое матричное умножение, которое преобразует слова в соответствующие им вложения слов.

Веса слоя Embedding имеют форму (vocabulary_size, embedding_dimension). Для каждой обучающей выборки входными данными являются целые числа, которые представляют определенные слова. Целые числа находятся в диапазоне размера словаря. Слой внедрения преобразует каждое целое число i в i-ю строку матрицы весов внедрения.

Чтобы быстро сделать это как матричное умножение, входные целые числа сохраняются не как список целых чисел, а как горячая матрица. Следовательно, входная форма (nb_words, dictionary_size) с одним ненулевым значением в строке. Если вы умножите это на веса вложения, вы получите результат в форме

(nb_words, vocab_size) x (vocab_size, embedding_dim) = (nb_words, embedding_dim)

Таким образом, с помощью простого матричного умножения вы преобразуете все слова в образце в соответствующие вложения слов.

Лоррит
источник
3
Определенно допустимый подход (см. Полу-контролируемое последовательное обучение ). Вы также можете изучить вложения с помощью автоэнкодера, а затем использовать их в качестве инициализации уровня встраивания, чтобы уменьшить сложность вашей нейронной сети (я предполагаю, что вы делаете что-то еще после уровня встраивания).
Lorrit 07
3
Вот хороший пост о встраивании слов и их преимуществах.
sietschie
3
В случае, который я представил, каждый обучающий ввод представляет собой набор слов (может быть предложением). Каждое слово представлено как горячий вектор и вложено в плотный вектор. Недостатком этого подхода является то, что, поскольку ввод должен быть постоянной длины, все ваши предложения должны содержать одинаковое количество слов. Альтернативой могут быть векторы абзацев , которые могут встраивать предложения, абзацы или даже документы в векторы.
Лоррит 02
4
Слой встраивания просто оптимизирует свои веса, чтобы минимизировать потери. Может быть, это означает, что он будет учитывать семантическое сходство, а может, и нет. Мало ли с нейронными сетями. Если вы хотите быть уверенным, что встраивание следует определенной формуле (например, w2v), используйте эту формулу. Если у вас достаточно данных, вы можете использовать слой «Встраивание» и обучить вложения. Просто попробуйте и проверьте, нравятся ли вам результаты.
Lorrit 08
2
Я согласен с user36624 (ответ ниже). Это НЕ простое матричное умножение.
Даниэль Мёллер
21

Keras EmbeddingСлой не выполняет никакого умножения матриц , но это только:

1. создает весовую матрицу размеров (Dictionary_size) x (embedding_dimension)

2. индексирует эту весовую матрицу


Всегда полезно взглянуть на исходный код, чтобы понять, что делает класс. В этом случае мы рассмотрим class встраивание, которое наследуется от базового слоя, classназываемого Layer .

(1) - Создание весовой матрицы размеров (Dictionary_size) x (embedding_dimension) :

Это происходит при buildфункции встраивания :

def build(self, input_shape):
    self.embeddings = self.add_weight(
        shape=(self.input_dim, self.output_dim),
        initializer=self.embeddings_initializer,
        name='embeddings',
        regularizer=self.embeddings_regularizer,
        constraint=self.embeddings_constraint,
        dtype=self.dtype)
    self.built = True

Если вы посмотрите на базовый класс Layer, вы увидите, что приведенная add_weightвыше функция просто создает матрицу обучаемых весов (в данном случае размерности (vocabulary_size) x (embedding_dimension) ):

def add_weight(self,
               name,
               shape,
               dtype=None,
               initializer=None,
               regularizer=None,
               trainable=True,
               constraint=None):
    """Adds a weight variable to the layer.
    # Arguments
        name: String, the name for the weight variable.
        shape: The shape tuple of the weight.
        dtype: The dtype of the weight.
        initializer: An Initializer instance (callable).
        regularizer: An optional Regularizer instance.
        trainable: A boolean, whether the weight should
            be trained via backprop or not (assuming
            that the layer itself is also trainable).
        constraint: An optional Constraint instance.
    # Returns
        The created weight variable.
    """
    initializer = initializers.get(initializer)
    if dtype is None:
        dtype = K.floatx()
    weight = K.variable(initializer(shape),
                        dtype=dtype,
                        name=name,
                        constraint=constraint)
    if regularizer is not None:
        with K.name_scope('weight_regularizer'):
            self.add_loss(regularizer(weight))
    if trainable:
        self._trainable_weights.append(weight)
    else:
        self._non_trainable_weights.append(weight)
    return weight

(2) - Индексирование этой весовой матрицы

Это происходит при callфункции встраивания :

def call(self, inputs):
    if K.dtype(inputs) != 'int32':
        inputs = K.cast(inputs, 'int32')
    out = K.gather(self.embeddings, inputs)
    return out

Эта функция возвращает результат Embeddingслоя, который есть K.gather(self.embeddings, inputs). Что именно делает tf.keras.backend.gather, так это индексирует матрицу весов self.embeddings(см. buildФункцию выше) в соответствии со inputsсписками положительных целых чисел.

Эти списки можно получить, например, если вы передадите свои текстовые / словесные входные данные в функцию one_hot Keras, которая кодирует текст в список индексов слов размера n (это НЕ одна горячая кодировка - см. Также этот пример для получения дополнительной информации: https://machinelearningmastery.com/use-word-embedding-layers-deep-learning-keras/ ).


Поэтому все. Умножения матриц нет.

Напротив, этот Keras Embeddingслой полезен только потому, что именно он позволяет избежать умножения матриц и, следовательно, экономить некоторые вычислительные ресурсы.

В противном случае вы могли бы просто использовать Keras плотный слой (после того, как вы закодировали свои входные данные), чтобы получить матрицу обучаемых весов ( размеров (Dictionary_size) x (embedding_dimension) ), а затем просто выполнить умножение, чтобы получить результат, который будет точно то же самое с выводом Embeddingслоя.

Изгой
источник
5

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

Андрей Никишаев
источник
4

В Keras Embeddingслой НЕ является простым слоем умножения матриц, а является слоем справочной таблицы (см. Функцию вызова ниже или исходное определение ).

def call(self, inputs):
    if K.dtype(inputs) != 'int32':
        inputs = K.cast(inputs, 'int32')
    out = K.gather(self.embeddings, inputs)
    return out

Он отображает каждое известное целое число nв inputsобучаемый вектор признаков W[n], размерность которого является так называемой длиной встроенного признака.

ловушка
источник
Хорошо, когда вы умножаете горячо представленный набор векторов на матрицу, продукт становится поисковым. Таким образом, Embeddingслой является действительно умножение матриц.
yannis
За исключением того, что нигде keras не выполняет это умножение. Он просто определяет «вложения = обучаемую матрицу» и использует входные индексы для сбора слов из матрицы.
Даниэль Мёллер
Таким образом, это встраивание экономит много памяти, просто не создавая ни одной горячей версии входных данных.
Даниэль Мёллер
1

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

Али Мирзаи
источник