Уровень внедрения использует матрицу поиска с формой (input_dim, output_dim). где вводимые векторы вложения dim number для изучения. Когда я передаю индекс, слой берет вектор по его индексу из матрицы вложения.
Спасибо, что указали, что я путаюсь с input_length с input_dim.
Прежде всего, возникает ошибка, если вы используете тензор потока.керас.
тензор потока
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Embedding, Input
import numpy as np
ip = Input(shape = (3,))
emb = Embedding(1, 2, trainable=True, mask_zero=True)(ip)
model = Model(ip, emb)
input_array = np.array([[5, 3, 1], [1, 2, 3]])
model.compile("rmsprop", "mse")
output_array = model.predict(input_array)
print(output_array)
print(output_array.shape)
model.summary()
![enter image description here](https://i.stack.imgur.com/bCzub.png)
Но если Я использую keras 2.3.1, я не получаю никакой ошибки.
keras 2.3.1
from keras.models import Model
from keras.layers import Embedding, Input
import numpy as np
ip = Input(shape = (3,))
emb = Embedding(1, 2, trainable=True, mask_zero=True)(ip)
model = Model(ip, emb)
input_array = np.array([[5, 3, 1], [1, 2, 3]])
model.compile("rmsprop", "mse")
output_array = model.predict(input_array)
print(output_array)
print(output_array.shape)
model.summary()
![enter image description here](https://i.stack.imgur.com/kN8N6.png)
Итак, керас сломан? Первое, на что нужно обратить внимание - это keras и tenorflow.keras имеют разные реализации для встраивания слоя. Чтобы проверить это, давайте go добавим слой встраивания keras.
https://github.com/keras-team/keras/blob/master/keras/layers/embeddings.py#L16
А сейчас давайте просто рассмотрим функцию вызова.
def call(self, inputs):
if K.dtype(inputs) != 'int32':
inputs = K.cast(inputs, 'int32')
out = K.gather(self.embeddings, inputs)
return out
NB: Если вам нужен точный исходный код для keras 2.3.1 go здесь и скачайте исходный код: https://github.com/keras-team/keras/releases
Но если мы go до реализации тензорного потока, это другое.
https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/ops/embedding_ops.py
Просто чтобы проверить, функция вызова написана по-другому.
def call(self, inputs):
dtype = K.dtype(inputs)
if dtype != 'int32' and dtype != 'int64':
inputs = math_ops.cast(inputs, 'int32')
out = embedding_ops.embedding_lookup(self.embeddings, inputs)
return out
Теперь мы можем копать глубже чтобы найти другое поведение и точно определить источник, для которого keras не выдает ошибку, а tenorflow.keras делает, но давайте сделаем простое замечание. Делает ли слой встраивания keras что-то не так?
Давайте спроектируем простую сеть, как раньше, и посмотрим на весовую матрицу.
from keras.models import Model
from keras.layers import Embedding, Input
import numpy as np
ip = Input(shape = (3,))
emb = Embedding(1, 2, trainable=True, mask_zero=True)(ip)
model = Model(ip, emb)
input_array = np.array([[5, 3, 1], [1, 2, 3]])
model.compile("rmsprop", "mse")
output_array = model.predict(input_array)
print(output_array)
print(output_array.shape)
model.summary()
Модель дает следующий вывод.
[[[0. 0.]
[0. 0.]
[0. 0.]]
[[0. 0.]
[0. 0.]
[0. 0.]]]
(2, 3, 2)
Model: "model_18"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_21 (InputLayer) (None, 3) 0
_________________________________________________________________
embedding_33 (Embedding) (None, 3, 2) 2
=================================================================
Total params: 2
Trainable params: 2
Non-trainable params: 0
Хорошо, мы получаем кучу нулей, но по умолчанию weight_initializer не равен нулям!
Итак, давайте посмотрим на матрицу весов.
import keras.backend as K
w = model.layers[1].get_weights()
print(w)
[array([[ 0.03680499, -0.04904002]], dtype=float32)]
На самом деле, это не все нули.
Итак, почему мы получаем нули?
Давайте изменим наш вход в модель.
Как единственный в словарном словарном индексе для input_dim = 1, равно 0. Давайте передадим 0 в качестве одного из входных данных.
from keras.models import Model
from keras.layers import Embedding, Input
import numpy as np
ip = Input(shape = (3,))
emb = Embedding(1, 2, trainable=True, mask_zero=True)(ip)
model = Model(ip, emb)
input_array = np.array([[5, 0, 1], [1, 2, 0]])
model.compile("rmsprop", "mse")
output_array = model.predict(input_array)
print(output_array)
print(output_array.shape)
model.summary()
Теперь мы получаем ненулевые векторы для позиций, где мы прошли 0.
[[[ 0. 0. ]
[-0.04339869 -0.04900574]
[ 0. 0. ]]
[[ 0. 0. ]
[ 0. 0. ]
[-0.04339869 -0.04900574]]]
(2, 3, 2)
Model: "model_19"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_22 (InputLayer) (None, 3) 0
_________________________________________________________________
embedding_34 (Embedding) (None, 3, 2) 2
=================================================================
Total params: 2
Trainable params: 2
Non-trainable params: 0
Короче говоря, Керас сопоставляет любой индекс словарного запаса с нулевым вектором, и это разумно, так как для этих позиций прямой проход гарантирует, что все вклады равны NIL (хотя смещения могут играть роль). Это немного нелогично, так как передача лексемных токенов в модель кажется чрезмерной (а не просто удаляющей их на этапе предварительной обработки) и плохой практикой.
Урок заключается в том, чтобы вообще избегать Keras и переход на tenorflow.keras, как они ясно отмечают, будет меньше поддержки и исправлены незначительные ошибки после версий 2.2.