如何在具有共享嵌入层和负采样的keras中实现word2vec CBOW?
How to implement word2vec CBOW in keras with shared Embedding layer and negative sampling?
我想创建一个词嵌入预训练网络,它在 word2vec CBOW 之上添加了一些东西。因此,我首先尝试实施 word2vec CBOW。由于我是 keras 的新手,我不知道如何在其中实施 CBOW。
初始化:
我已经计算了词汇量,并有了单词到整数的映射。
输入(尚未实现)网络:
2*k + 1
个整数的列表(代表上下文中的中心词和 2*k
个词)
网络规格
一个共享的Embedding
层应该采用这个整数列表并给出它们相应的向量输出。进一步取 2*k
上下文向量的平均值(我相信这可以使用 add_node(layer, name, inputs=[2*k vectors], merge_mode='ave')
完成)。
如果有人能分享其中的一小段代码,那将非常有帮助。
P.S.:我在看word2veckeras,但无法理解它的代码,因为它也使用了gensim。
更新 1:
我想在网络中共享嵌入层。嵌入层应该能够使用上下文词 (2*k) 和当前词。我可以通过在输入中获取所有 2*k + 1 个单词索引并编写一个自定义 lambda 函数来完成此操作。但是,在那之后我还想添加负采样网络,为此我必须使用上下文向量嵌入更多的单词和点积。有人可以提供一个示例,其中嵌入层是 Graph()
网络
中的共享节点
你可以尝试这样的事情。在这里,我将嵌入矩阵初始化为一个固定值。对于形状为 (1, 6)
的输入数组,您将获得形状为 (1, 100)
的输出,其中 100
是 6 个输入嵌入的平均值。
model = Sequential()
k = 3 # context windows size
context_size = 2*k
# generate weight matrix for embeddings
embedding = []
for i in range(10):
embedding.append(np.full(100, i))
embedding = np.array(embedding)
print embedding
model.add(Embedding(input_dim=10, output_dim=100, input_length=context_size, weights=[embedding]))
model.add(Lambda(lambda x: K.mean(x, axis=1), output_shape=(100,)))
model.compile('rmsprop', 'mse')
input_array = np.random.randint(10, size=(1, context_size))
print input_array.shape
output_array = model.predict(input_array)
print output_array.shape
print output_array[0]
Graph()
已从 keras
弃用
可以使用 keras functional API 创建任意网络。
以下是创建 word2vec cbow 模型的演示代码,该模型在随机输入
上进行了负采样测试
from keras import backend as K
import numpy as np
from keras.utils.np_utils import accuracy
from keras.models import Sequential, Model
from keras.layers import Input, Lambda, Dense, merge
from keras.layers.embeddings import Embedding
k = 3 # context windows size
context_size = 2*k
neg = 5 # number of negative samples
# generate weight matrix for embeddings
embedding = []
for i in range(10):
embedding.append(np.full(100, i))
embedding = np.array(embedding)
print embedding
# Creating CBOW model
word_index = Input(shape=(1,))
context = Input(shape=(context_size,))
negative_samples = Input(shape=(neg,))
shared_embedding_layer = Embedding(input_dim=10, output_dim=100, weights=[embedding])
word_embedding = shared_embedding_layer(word_index)
context_embeddings = shared_embedding_layer(context)
negative_words_embedding = shared_embedding_layer(negative_samples)
cbow = Lambda(lambda x: K.mean(x, axis=1), output_shape=(100,))(context_embeddings)
word_context_product = merge([word_embedding, cbow], mode='dot')
negative_context_product = merge([negative_words_embedding, cbow], mode='dot', concat_axis=-1)
model = Model(input=[word_index, context, negative_samples], output=[word_context_product, negative_context_product])
model.compile(optimizer='rmsprop', loss='mse', metrics=['accuracy'])
input_context = np.random.randint(10, size=(1, context_size))
input_word = np.random.randint(10, size=(1,))
input_negative = np.random.randint(10, size=(1, neg))
print "word, context, negative samples"
print input_word.shape, input_word
print input_context.shape, input_context
print input_negative.shape, input_negative
output_dot_product, output_negative_product = model.predict([input_word, input_context, input_negative])
print "word cbow dot product"
print output_dot_product.shape, output_dot_product
print "cbow negative dot product"
print output_negative_product.shape, output_negative_product
希望对您有所帮助!
更新 1:
我已经完成代码并上传了here
我想创建一个词嵌入预训练网络,它在 word2vec CBOW 之上添加了一些东西。因此,我首先尝试实施 word2vec CBOW。由于我是 keras 的新手,我不知道如何在其中实施 CBOW。
初始化:
我已经计算了词汇量,并有了单词到整数的映射。
输入(尚未实现)网络:
2*k + 1
个整数的列表(代表上下文中的中心词和 2*k
个词)
网络规格
一个共享的Embedding
层应该采用这个整数列表并给出它们相应的向量输出。进一步取 2*k
上下文向量的平均值(我相信这可以使用 add_node(layer, name, inputs=[2*k vectors], merge_mode='ave')
完成)。
如果有人能分享其中的一小段代码,那将非常有帮助。
P.S.:我在看word2veckeras,但无法理解它的代码,因为它也使用了gensim。
更新 1:
我想在网络中共享嵌入层。嵌入层应该能够使用上下文词 (2*k) 和当前词。我可以通过在输入中获取所有 2*k + 1 个单词索引并编写一个自定义 lambda 函数来完成此操作。但是,在那之后我还想添加负采样网络,为此我必须使用上下文向量嵌入更多的单词和点积。有人可以提供一个示例,其中嵌入层是 Graph()
网络
你可以尝试这样的事情。在这里,我将嵌入矩阵初始化为一个固定值。对于形状为 (1, 6)
的输入数组,您将获得形状为 (1, 100)
的输出,其中 100
是 6 个输入嵌入的平均值。
model = Sequential()
k = 3 # context windows size
context_size = 2*k
# generate weight matrix for embeddings
embedding = []
for i in range(10):
embedding.append(np.full(100, i))
embedding = np.array(embedding)
print embedding
model.add(Embedding(input_dim=10, output_dim=100, input_length=context_size, weights=[embedding]))
model.add(Lambda(lambda x: K.mean(x, axis=1), output_shape=(100,)))
model.compile('rmsprop', 'mse')
input_array = np.random.randint(10, size=(1, context_size))
print input_array.shape
output_array = model.predict(input_array)
print output_array.shape
print output_array[0]
Graph()
已从 keras
可以使用 keras functional API 创建任意网络。 以下是创建 word2vec cbow 模型的演示代码,该模型在随机输入
上进行了负采样测试from keras import backend as K
import numpy as np
from keras.utils.np_utils import accuracy
from keras.models import Sequential, Model
from keras.layers import Input, Lambda, Dense, merge
from keras.layers.embeddings import Embedding
k = 3 # context windows size
context_size = 2*k
neg = 5 # number of negative samples
# generate weight matrix for embeddings
embedding = []
for i in range(10):
embedding.append(np.full(100, i))
embedding = np.array(embedding)
print embedding
# Creating CBOW model
word_index = Input(shape=(1,))
context = Input(shape=(context_size,))
negative_samples = Input(shape=(neg,))
shared_embedding_layer = Embedding(input_dim=10, output_dim=100, weights=[embedding])
word_embedding = shared_embedding_layer(word_index)
context_embeddings = shared_embedding_layer(context)
negative_words_embedding = shared_embedding_layer(negative_samples)
cbow = Lambda(lambda x: K.mean(x, axis=1), output_shape=(100,))(context_embeddings)
word_context_product = merge([word_embedding, cbow], mode='dot')
negative_context_product = merge([negative_words_embedding, cbow], mode='dot', concat_axis=-1)
model = Model(input=[word_index, context, negative_samples], output=[word_context_product, negative_context_product])
model.compile(optimizer='rmsprop', loss='mse', metrics=['accuracy'])
input_context = np.random.randint(10, size=(1, context_size))
input_word = np.random.randint(10, size=(1,))
input_negative = np.random.randint(10, size=(1, neg))
print "word, context, negative samples"
print input_word.shape, input_word
print input_context.shape, input_context
print input_negative.shape, input_negative
output_dot_product, output_negative_product = model.predict([input_word, input_context, input_negative])
print "word cbow dot product"
print output_dot_product.shape, output_dot_product
print "cbow negative dot product"
print output_negative_product.shape, output_negative_product
希望对您有所帮助!
更新 1:
我已经完成代码并上传了here