2017-02-28 8 views
2

ためKeras functionnal APIとのレイヤーを結合hereが見つかりました:製品は、私は次のコード、Kerasと負のサンプリングでWord2Vec CBOWを実装しようとしていますWord2Vecモデル

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) 

はしかし、私は、マージ部分の間にエラーが発生します埋め込みレイヤは3Dテンソルであり、梁は2次元のみであるためです。私は埋め込み([1,100])を[1,100]に再形成する必要があると想定していますが、機能的APIでどのように変形するかを見つけることはできません。 私はTensorflowバックエンドを使用しています。

また、誰かがKeras(Gensimフリー)でCBOWの他の実装を指し示すことができるなら、私はそれを見てみたいです!

ありがとうございました!

編集:ここでエラーあなたがword_embeddingテンソルを再構築する必要があります実際に

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

エラーを表示できますか? –

+0

本当に、ごめんなさい。完全に忘れてしまった! –

答えて

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

です。 Reshapeの引数が目標形状を持つタプルです

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

:それを行うには、2つの方法:よう

  • あなたはkeras.layers.coreから輸入Reshape()層を、使用するかは、これが行われます。

  • それとも、このように使用もkeras.layers.coreから輸入Flatten()層、使用することができます。引数として何を取っていない

    word_embedding = Flatten()(word_embedding) 
    

    を、それだけで「空」の次元を削除します。

これは役に立ちますか?

EDIT:

実際二merge()もう少しトリッキーです。ケラスのdotマージは同じランクのテンソルしか受け入れないので、同じlen(shape)と同じです。 だから、Reshape()レイヤーを使用して1つの空のディメンションを追加し、dotマージには関係のないconcat_axisの代わりにdot_axesフィーチャーを使用します。 これは私が解決策のためにあなたを提案するものである:

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) 

それが動作していますか? :)

問題は、行列乗算に関するTFの剛性から来ます。 「ドット」モードでマージするとバックエンドbatch_dot()関数が呼び出され、Theanoとは対照的に、TensorFlowではマトリックスのランクが同じであることが必要です:read here

+0

私は最初のマージのために助けますはい、ありがとう!しかし、 'negative_samples'の形は(5、)で、(1、)ではないので、私は平坦な形や形を変えることで修正できない2番目のエラーと同じ種類のエラーを受け取ります:ValueError:Shapeはランク私が得ないのは、このコードがTheanoではうまく動作するが、そうではないことである。というのは、入力文字列が[?、5,100]、[?、100]である 'MatMul'(op: 'MatMul' Tensorflow .. –

+0

編集: –

+0

私は働いています、ありがとう!そして、明確化のおかげで、私はTheanoについて何も知らない! –

関連する問題