Хорошо, вот что я понял, поправьте меня, если я ошибаюсь:
x
содержит 94556 целых чисел, каждое из которых является индексом одного из 2557 слов. y
содержит 94556 векторов из 2557 целых чисел, каждый из которых также содержит индекс одного слова, но на этот раз это горячая кодировка вместо категориальной. - Наконец, соответствующая пара слова из
x
и y
представляют собой два слова, которые находятся рядом в исходном тексте.
Если я прав до сих пор, то следующее выполняется правильно:
import numpy as np
import tensorflow as tf
from tensorflow.keras.layers import *
from tensorflow.keras.models import *
x = np.random.randint(0,2557,94556)
y = np.eye((2557))[np.random.randint(0,2557,94556)]
xr = x.reshape((-1,1))
print("x.shape: {}\nxr.shape:{}\ny.shape: {}".format(x.shape, xr.shape, y.shape))
model = Sequential()
model.add(Embedding(2557, 64, input_length=1, embeddings_initializer='glorot_uniform'))
model.add(Reshape((64,)))
model.add(Dense(512, activation='sigmoid'))
model.add(Dense(2557, activation='softmax'))
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
model.summary()
history=model.fit(xr, y, epochs=20, batch_size=32, validation_split=3/9)
Наиболее импортные модификации:
- При изменении формы
y
терялась связь между элементами из x
и y
. input_length
в слое Embedding
должно соответствовать второму измерению xr
. - Выход последнего слоя из сети должен быть того же измерения, что и второй измерение
y
.
Я действительно удивлен, что код работал без сбоев.
Наконец, из моих исследований, похоже, что люди не тренируют такие скипграммы на практике, скорее они пытаются предсказать, является ли обучающий пример правильным (два слова рядом) или нет. Возможно, именно по этой причине вы придумали результат измерения один.
Вот модель, вдохновленная https://github.com/PacktPublishing/Deep-Learning-with-Keras/blob/master/Chapter05/keras_skipgram.py:
word_model = Sequential()
word_model.add(Embedding(2557, 64, embeddings_initializer="glorot_uniform", input_length=1))
word_model.add(Reshape((embed_size,)))
context_model = Sequential()
context_model.add(Embedding(2557, 64, embeddings_initializer="glorot_uniform", input_length=1))
context_model.add(Reshape((64,)))
model = Sequential()
model.add(Merge([word_model, context_model], mode="dot", dot_axes=0))
model.add(Dense(1, kernel_initializer="glorot_uniform", activation="sigmoid"))
В этом случае, у вас будет 3 вектора, все одного размера (94556, 1)
(или, возможно, даже больше, чем 94556, поскольку вам может потребоваться сгенерировать дополнительные отрицательные образцы):
x
, содержащие целые числа от 0 до 2556 y
, содержащий целые числа от 0 до 2556 output
, содержащий нули и единицы, независимо от того, является ли каждая пара из x
и y
отрицательным или положительным примером
и тренировка будет выглядеть так:
history = model.fit([x, y], output, epochs=20, batch_size=32, validation_split=3/9)