Модель распределенной памяти Doc2Vec векторов абзацев (PV-DM) не классифицируется - PullRequest
0 голосов
/ 03 октября 2018

Я использую Keras для кодирования DM согласно статье Миколова.

Документы, с которыми мы сталкиваемся, очень специфичны: у нас много разных документов (около 20 000), но очень мало разных слов (только100).

Когда я использую вложение документа для классификации своих документов, оно, похоже, не работает ...

Я не знаю, связано ли это сконкретные данные или мой способ кодирования DM.

Любая подсказка будет принята с благодарностью!

Это мой код:

## Libraries

import numpy as np
import pandas as pd
import keras.backend as K
from keras.models import Model
from keras.layers import Dense, Embedding, Lambda,concatenate, Input, Flatten
from keras.utils.data_utils import get_file
from keras.utils import np_utils
from keras.preprocessing import sequence
from keras.preprocessing.text import Tokenizer
from keras import optimizers
from keras.constraints import non_neg
import random as rd


## Parameters

seuil = 0.0001 # Mikolov threshold
loss = 'categorical_crossentropy'
dim=20 # dimension of words and documents embeddings
lr = 0.005 # learning rate
epochs = 15
shuffle=True
steps_per_epoch = 10000
window_size = 7
seed=123
rd.seed(seed)

V1 = 100 # number of words
V2 = 20000 # number of documents

Вот так выглядит мой корпус:

new_corpus =
[[2],
 [33, 33, 11],
 [8, 16],
 [27, 10],
 [13],
 [],
 [21, 21, 32, 10, 1],
 [],
 [1, 27],
 ... ]

Используемая нейронная сеть:

input_words=Input((window_size*2,))
cbow_words = Embedding(input_dim=V1, output_dim=dim, input_length=window_size*2 ,embeddings_constraint=non_neg())(input_words)

input_texts=Input((V2,))
cbow_texts = Embedding(input_dim=V2, output_dim=dim, input_length=V2 ,embeddings_constraint=non_neg())(input_texts)

concat = concatenate([cbow_words,cbow_texts],axis=1)
lambd = Lambda(lambda x: K.mean(x, axis=1), output_shape=(dim,))(concat)
output = Dense(V1+1, activation='softmax')(lambd) # V1+1 because words are indexed from 1

cbow = Model(inputs=[input_words,input_texts], outputs=output)

cbow.compile(loss=loss, optimizer=optimizers.Adadelta(lr=lr, rho=0.95, epsilon=None, decay=0.0))
cbow.summary()

Она печатает:

Layer (type)                    Output Shape         Param #     Connected to                     
==================================================================================================
input_47 (InputLayer)           (None, 14)           0                                            
__________________________________________________________________________________________________
input_48 (InputLayer)           (None, 20000)        0                                            
__________________________________________________________________________________________________
embedding_47 (Embedding)        (None, 14, 20)       2160        input_47[0][0]                   
__________________________________________________________________________________________________
embedding_48 (Embedding)        (None, 20000, 20)    400000      input_48[0][0]                   
__________________________________________________________________________________________________
concatenate_24 (Concatenate)    (None, 20000, 20)    0           embedding_47[0][0]               
                                                                 embedding_48[0][0]               
__________________________________________________________________________________________________
lambda_24 (Lambda)              (None, 20)           0           concatenate_24[0][0]             
__________________________________________________________________________________________________
dense_24 (Dense)                (None, 101)          2121        lambda_24[0][0]                  
==================================================================================================

. Таким образом, данные преобразуются в генетатор:

generatedData=generate_data(new_corpus, window_size, V1)

for x, y in generatedData:
    print(x,y)

Элемент Fisrt представляет контекст.

Второй элемент представляет идентификатор документа с одним горячим вектором.

Третий элемент представляет предсказанное слово как один горячий вектор.

Это две первые строки

[array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4]]), array([[0., 0., 0., ..., 0., 0., 0.]], dtype=float32)] [[... 0. 0. 0. 0. 1. ... 0. 0. 0. 0.]]
[array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 23]]), array([[0., 0., 0., ..., 0., 0., 0.]], dtype=float32)] [[... 0. 0. 1. .... 0. 0. 0. 0.]]
...

Тогда мне подходит модel:

cbow.fit_generator(generatedData,steps_per_epoch=steps_per_epoch,epochs=epochs,shuffle=shuffle)

Модель сходится.

E1=pd.DataFrame(cbow.layers[2].get_weights()[0]) # words embedding
E2=pd.DataFrame(cbow.layers[3].get_weights()[0]) # docs embedding

Документы в конечном итоге классифицируются как случайные ...

...