2017-02-28 3 views
2

ich mit Keras einen Word2Vec CBOW mit negativer Probenahme umzusetzen versuchen, nach dem Code gefunden here:Produkte verschmelzen Schichten mit Keras functionnal API für Word2Vec Modell

EMBEDDING_DIM = 100 

sentences = SentencesIterator('test_file.txt') 
v_gen = VocabGenerator(sentences=sentences, min_count=5, window_size=3, 
         sample_threshold=-1, negative=5) 

v_gen.scan_vocab() 
v_gen.filter_vocabulary() 
reverse_vocab = v_gen.generate_inverse_vocabulary_lookup('test_lookup') 

# Generate embedding matrix with all values between -1/2d, 1/2d 
embedding = np.random.uniform(-1.0/(2 * EMBEDDING_DIM), 
           1.0/(2 * EMBEDDING_DIM), 
           (v_gen.vocab_size + 3, EMBEDDING_DIM)) 

# Creating CBOW model 
# Model has 3 inputs 
# Current word index, context words indexes and negative sampled word indexes 
word_index = Input(shape=(1,)) 
context = Input(shape=(2*v_gen.window_size,)) 
negative_samples = Input(shape=(v_gen.negative,)) 

# All inputs are processed through a common embedding layer 
shared_embedding_layer = (Embedding(input_dim=(v_gen.vocab_size + 3), 
            output_dim=EMBEDDING_DIM, 
            weights=[embedding])) 

word_embedding = shared_embedding_layer(word_index) 
context_embeddings = shared_embedding_layer(context) 
negative_words_embedding = shared_embedding_layer(negative_samples) 

# Now the context words are averaged to get the CBOW vector 
cbow = Lambda(lambda x: K.mean(x, axis=1), 
       output_shape=(EMBEDDING_DIM,))(context_embeddings) 

# Context is multiplied (dot product) with current word and negative 
# sampled words 
word_context_product = merge([word_embedding, cbow], mode='dot') 
negative_context_product = merge([negative_words_embedding, cbow], 
           mode='dot', 
           concat_axis=-1) 

# The dot products are outputted 
model = Model(input=[word_index, context, negative_samples], 
       output=[word_context_product, negative_context_product]) 

# Binary crossentropy is applied on the output 
model.compile(optimizer='rmsprop', loss='binary_crossentropy') 
print(model.summary()) 

model.fit_generator(v_gen.pretraining_batch_generator(reverse_vocab), 
        samples_per_epoch=10, 
        nb_epoch=1) 

Allerdings habe ich einen Fehler bei der Zusammenführung Teil erhalten Da die Einbettungsschicht ein 3D-Tensor ist, ist die Krümmung nur 2 Dimensionen. Ich nehme an, dass ich die Einbettung (die [?, 1, 100]) zu [1, 100] umformen muss, aber ich kann nicht finden, wie man mit der Funktions-API umformt. Ich verwende das Tensorflow-Backend.

Auch wenn jemand auf eine andere Implementierung von CBOW mit Keras zeigen kann (Gensim frei), würde ich gerne einen Blick darauf werfen!

Vielen Dank!

EDIT: Hier ist der Fehler

Traceback (most recent call last): 
    File "cbow.py", line 48, in <module> 
    word_context_product = merge([word_embedding, cbow], mode='dot') 
    . 
    . 
    . 
ValueError: Shape must be rank 2 but is rank 3 for 'MatMul' (op: 'MatMul') with input shapes: [?,1,100], [?,100]. 
+0

Können Sie den Fehler –

+0

zeigen, sorry. Total vergessen! –

Antwort

2
ValueError: Shape must be rank 2 but is rank 3 for 'MatMul' (op: 'MatMul') with input shapes: [?,1,100], [?,100]. 

der Tat müssen Sie den word_embedding Tensor neu zu gestalten. Zwei Möglichkeiten, es zu tun:

  • Entweder Sie verwenden, um die Reshape() Schicht, aus keras.layers.core importiert, dies ist wie gemacht:

    word_embedding = Reshape((100,))(word_embedding) 
    

    das Argument von Reshape ist ein Tupel mit der Zielform.

  • Oder Sie können Flatten() Schicht verwenden, auch aus keras.layers.core importiert, so benutzten:

    word_embedding = Flatten()(word_embedding) 
    

    nichts als Argument nehmen, wird es nur „leere“ Dimensionen entfernen.

Hilft Ihnen das?

EDIT:

der Tat die zweite merge() ist ein wenig komplizierter. Die dot Merge in Keras akzeptiert nur Tensoren des gleichen Rangs, also len(shape). Also, was Sie tun werden, ist eine Reshape() Schicht, um diese 1 leere Dimension hinzuzufügen, dann verwenden Sie die Funktion dot_axes anstelle von concat_axis, die für eine dot Zusammenführung nicht relevant ist. Dies ist, was ich vor Ihnen für die Lösung:

word_embedding = shared_embedding_layer(word_index) 
# Shape output = (None,1,emb_size) 
context_embeddings = shared_embedding_layer(context) 
# Shape output = (None, 2*window_size, emb_size) 
negative_words_embedding = shared_embedding_layer(negative_samples) 
# Shape output = (None, negative, emb_size) 

# Now the context words are averaged to get the CBOW vector 
cbow = Lambda(lambda x: K.mean(x, axis=1), 
        output_shape=(EMBEDDING_DIM,))(context_embeddings) 
# Shape output = (None, emb_size) 
cbow = Reshape((1,emb_size))(cbow) 
# Shape output = (None, 1, emb_size) 

# Context is multiplied (dot product) with current word and negative 
# sampled words 
word_context_product = merge([word_embedding, cbow], mode='dot') 
# Shape output = (None, 1, 1) 
word_context_product = Flatten()(word_context_product) 
# Shape output = (None,1) 
negative_context_product = merge([negative_words_embedding, cbow], mode='dot',dot_axes=[2,2]) 
# Shape output = (None, negative, 1) 
negative_context_product = Flatten()(negative_context_product) 
# Shape output = (None, negative) 

Funktioniert es? :)

Das Problem kommt von der Starrheit der TF bezüglich der Matrixmultiplikation. Zusammenführen mit dem "Punkt" -Modus ruft die Backend-Funktion auf und im Gegensatz zu Theano benötigt TensorFlow, dass die Matrix den gleichen Rang aufweist: .

+0

Ich helfe bei der ersten Zusammenführung ja, vielen Dank!Aber ich bekomme die gleiche Art von Fehler für die zweite, die ich nicht mit einem Flatten oder Umformen beheben kann, weil die Form von 'negative_samples' (5,) und nicht (1,) ist:' ValueError: Shape muss Rang 2 sein aber ist Platz 3 für 'MatMul' (op: 'MatMul') mit Eingabeformen: [?, 5,100], [?, 100] .' Was ich nicht verstehe, ist, dass dieser Code gut mit Theano funktioniert, aber nicht mit Tensorflow .. –

+0

entsprechend bearbeitet :) –

+0

Ich arbeite, vielen Dank! Und danke für die Klarstellung, ich weiß nichts über Theano! –