как положить несколько LSTM в одном слое? - PullRequest
0 голосов
/ 02 ноября 2019

Я новичок в Керасе. Я пытаюсь реализовать эту модель https://www.aclweb.org/anthology/D15-1167 для классификации документов, и я хочу использовать LSTM для получения представления предложений. Я обучил векторное представление отдельно с помощью модели скип-граммы в моем наборе данныхТеперь, после преобразования каждого документа в отдельное предложение, а затем преобразования каждого предложения в отдельное слово, а затем преобразования каждого слова в соответствующее целое число в словаре, у меня есть что-то подобное для каждого документа: [[54,32,13], [21,43,2] ... [28,1,9]] который я должен передать каждое предложение в LSTM, чтобы получить вектор предложения, и после этого я должен передать каждый вектор предложения в другой LSTM на верхнем уровне в порядкечтобы получить представление документа, а затем применить к нему классификацию. моя проблема в первом слое. как мне передать каждое предложение одновременно каждому LSTM (поэтому на каждом временном шаге каждый LSTM должен применяться к вектору слов из каждого предложения)?

edit : я только что использовал TimeDistributed икажется, что работает, хотя я не уверен, что он делает то, что я хочу. Я использовал оболочку с распределением времени над слоем внедрения, а затем поверх первого слоя Lstm. это модель, которую я реализовал (очень простая):

model.add(tf.keras.layers.TimeDistributed(embeding_layer))
model.add(tf.keras.layers.TimeDistributed 
(layers.LSTM(50,activation=’relu’)))
model.add(layers.LSTM(50,activation=’relu’))
model.add(layers.Dense(1,activation=’sigmoid’))

Правильно ли мое понимание сети? моя интерпретация: мой вклад в слой внедрения (документ, предложения, слова). Я добавил в документ 30 предложений, а также добавил 200 слов. У меня есть 20000 документов, поэтому моя форма ввода (20000,30,200). после подачи его в сеть он сначала проходит через слой эмерации, длина которого составляет 300 для каждого вектора слова. поэтому после применения внедряющего слоя сначала для документа с формой (1,30,200), затем я получаю (1,30,200,300), который будет входом для распределенного по времени LSTM. затем распределитель времени сделает 30 копий слоя LSTM с общими точками, где каждый LSTM будет выводить вектор предложения, а затем следующий LSTM будет применен к этим 30 векторам предложений. я прав?

1 Ответ

0 голосов
/ 05 ноября 2019

В приведенном ниже примере может быть то, что вы ищете, или, по крайней мере, направить вас в правильном направлении. Это немного экспериментально с моей стороны, но я считаю, что оно имеет правильную структуру. Он был создан в Google Colab с Tensorflow 2.0. Первый раздел предназначен для обеспечения воспроизводимости обработки, а остальная часть иллюстрирует общую идею использования «TimeDistributed Layer» наряду с маскированием и заполнением. Кстати, я считаю, что эта идея похожа на то, что предлагал @El Sheikh (первый комментарий выше). Примечание. Я использовал здесь SimpleRNN, но я считаю, что эта идея применима и к LSTM. Я надеюсь, что это поможет вам двигаться в правильном направлении.

%tensorflow_version 2.x
import numpy as np
import tensorflow as tf
import random as rn

# The below is necessary for starting Numpy generated random numbers
# in a well-defined initial state.

np.random.seed(42)

# The below is necessary for starting core Python generated random numbers
# in a well-defined state.

rn.seed(12345)

# Force TensorFlow to use single thread.
# Multiple threads are a potential source of non-reproducible results.
# For further details, see: https://stackoverflow.com/questions/42022950/

session_conf = tf.compat.v1.ConfigProto(intra_op_parallelism_threads=1,
                                        inter_op_parallelism_threads=1)

# The below tf.set_random_seed() will make random number generation
# in the TensorFlow backend have a well-defined initial state.
# For further details, see:
# https://www.tensorflow.org/api_docs/python/tf/set_random_seed

tf.compat.v1.set_random_seed(1234)

sess = tf.compat.v1.Session(graph=tf.compat.v1.get_default_graph(), config=session_conf)
tf.compat.v1.keras.backend.set_session(sess)

# The code above here is provided to make the below reproducible each time you
# run.

#
# Main code follows:

from tensorflow import keras
from tensorflow.keras import layers

# Input structure
#                Sentence1                   .....         SentenceM
#    Word11  Word21   Word31  ..... Wordn11          Word11   ....  WordnM1
#    Word12  Word22   Word32        Wordn12          Word12         WordnM2
#    Word13  Word23   Word33        Wordn13          Word13         WordnM3

# example parameters
word_vec_dimension = 3   # dimension of the embedding
sentence_representation = 4 # dimensionality of sentence vector

#
# This represents a single test document.
# Each row is a sentence and the words are represented by 3 dimensionsal 
# integer vectors.
#
raw_inputs = [ [ [1, 5, 7], [2, 6, 7] ], 
               [ [9, 6, 3], [1, 8, 2], [4, 5, 9], [8, 2, 1] ],
               [ [1, 6, 2], [4, 2, 9] ],
               [ [2, 6, 2], [8, 2, 9] ],
               [ [3, 6, 2], [2, 2, 9], [1, 6, 2] ],

]

print(raw_inputs)
# Create the model
#
# Allow for variable number of words per sentence and variable number of 
# sentences:
# Input shape(num_samples, [SentenceCount], [WordCount], word_vector_dim)
# 
# Note:  Using None for Sentence Count, and None for Word count to allow
# for variable sequences length in both these dimensions.
#
inputs = keras.Input(shape=(None, None, word_vec_dimension), name='inputlayer')
x = tf.keras.layers.Masking(mask_value=0.0)(inputs)  # Force RNNs to ignore timesteps with zero vectors.
x = tf.keras.layers.TimeDistributed(layers.SimpleRNN(sentence_representation, 
                                                     use_bias=False, 
                                                     activation=None), 
                                                     name='TD1')(x)

outputs = x
# more layers here if needed:

model = tf.keras.Model(inputs=inputs, outputs=outputs, name='Sentiment')
model.compile(optimizer='rmsprop', loss='mse', accuracy='mse' )
model.summary()

# Set up fitting calls
import numpy as np

# document 1
x_train = raw_inputs # use the dummy document for testing
# Set zeros in locations where there is no data to indicate mask to RNN's so
# they ignore that timestep.
padded_inputs = tf.keras.preprocessing.sequence.pad_sequences(x_train, 
                                                              padding='post')

print(x_train)
# Insert a dummy dimension 1 to represent the sample dimension.
padded_inputs = np.expand_dims(padded_inputs,axis=0)/1.0  # Make float type
print(padded_inputs)
print(padded_inputs.shape)

y_train = np.array([[ 1.0, 2.0, 3.0, 4.0 ]])
print(y_train.shape)

# Train model:
model.fit(padded_inputs,y_train,epochs=1)

print('get_weights:')
print(model.get_layer(name='TD1').get_weights())

print('get_predictions:')
print(model.predict(padded_inputs))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...