Понимание встраивания слов, сверточного уровня и максимального уровня пула в LSTM и RNN для текстовой классификации НЛП - PullRequest
0 голосов
/ 05 декабря 2018

Вот мои входные данные:

data['text'].head()

0    process however afforded means ascertaining di...
1          never occurred fumbling might mere mistake 
2    left hand gold snuff box which capered hill cu...
3    lovely spring looked windsor terrace sixteen f...
4    finding nothing else even gold superintendent ...
Name: text, dtype: object

А вот одна метка с горячим кодированием (классификация нескольких классов, где количество классов = 3)

[[1 0 0]
 [0 1 0]
 [1 0 0]
 ...
 [1 0 0]
 [1 0 0]
 [0 1 0]]

Вотчто я думаю происходит шаг за шагом, пожалуйста, исправьте меня, если я ошибаюсь:

  1. Преобразование моего входного текста data['text'] в пакет индексов (последовательностей)

    vocabulary_size = 20000
    
    tokenizer = Tokenizer(num_words = vocabulary_size)
    tokenizer.fit_on_texts(data['text'])
    sequences = tokenizer.texts_to_sequences(data['text'])
    
    data = pad_sequences(sequences, maxlen=50)
    

Происходит то, что мой data['text'].shape, имеющий форму (19579, ), преобразуется в массив индексов формы (19579, 50), где каждое слово заменяется индексом, найденным в tokenizer.word_index.items()

Загрузка вектора слов glove 100d

embeddings_index = dict()
f = open('/Users/abhishekbabuji/Downloads/glove.6B/glove.6B.100d.txt')
for line in f:
    values = line.split()
    word = values[0]
    coefs = np.asarray(values[1:], dtype='float32')
    embeddings_index[word] = coefs
f.close()

print(embedding_index)
    {'the': array([-0.038194, -0.24487 ,  0.72812 , -0.39961 ,  0.083172,  0.043953,
    -0.39141 ,  0.3344  , -0.57545 ,  0.087459,  0.28787 , -0.06731 ,
     0.30906 , -0.26384 , -0.13231 , -0.20757 ,  0.33395 , -0.33848 ,
    -0.31743 , -0.48336 ,  0.1464  , -0.37304 ,  0.34577 ,  0.052041,
     0.44946 , -0.46971 ,  0.02628 , -0.54155 , -0.15518 , -0.14107 ,
    -0.039722,  0.28277 ,  0.14393 ,  0.23464 , -0.31021 ,  0.086173,
     0.20397 ,  0.52624 ,  0.17164 , -0.082378, -0.71787 , -0.41531 ,
     0.20335 , -0.12763 ,  0.41367 ,  0.55187 ,  0.57908 , -0.33477 ,
    -0.36559 , -0.54857 , -0.062892,  0.26584 ,  0.30205 ,  0.99775 ,
    -0.80481 , -3.0243  ,  0.01254 , -0.36942 ,  2.2167  ,  0.72201 ,
    -0.24978 ,  0.92136 ,  0.034514,  0.46745 ,  1.1079  , -0.19358 ,
    -0.074575,  0.23353 , -0.052062, -0.22044 ,  0.057162, -0.15806 ,
    -0.30798 , -0.41625 ,  0.37972 ,  0.15006 , -0.53212 , -0.2055  ,
    -1.2526  ,  0.071624,  0.70565 ,  0.49744 , -0.42063 ,  0.26148 ,
    -1.538   , -0.30223 , -0.073438, -0.28312 ,  0.37104 , -0.25217 ,
     0.016215, -0.017099, -0.38984 ,  0.87424 , -0.72569 , -0.51058 ,
    -0.52028 , -0.1459  ,  0.8278  ,  0.27062 ], dtype=float32),

Итак, теперь мы имеем векторы слов для каждого слова из 100 измерений.

Создание матрицы внедрения с использованием вектора слова перчатки

vocabulary_size = 20000
embedding_matrix = np.zeros((vocabulary_size, 100))

for word, index in tokenizer.word_index.items():
    if index > vocabulary_size - 1:
        break
    else:
        embedding_vector = embeddings_index.get(word)
        if embedding_vector is not None:
            embedding_matrix[index] = embedding_vector

Итак, теперь у нас есть vector из 100 измерений для КАЖДОГО из 20000 слов.

А вот и архитектура:

model_glove = Sequential()
model_glove.add(Embedding(vocabulary_size, 100, input_length=50, weights=[embedding_matrix], trainable=False))
model_glove.add(Dropout(0.5))
model_glove.add(Conv1D(64, 5, activation='relu')) 
model_glove.add(MaxPooling1D(pool_size=4))
model_glove.add(LSTM(100))
model_glove.add(Dense(3, activation='softmax'))
model_glove.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
print(model_glove.summary())

Я получаю

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding_7 (Embedding)      (None, 50, 100)           2000000   
_________________________________________________________________
dropout_7 (Dropout)          (None, 50, 100)           0         
_________________________________________________________________
conv1d_7 (Conv1D)            (None, 46, 64)            32064     
_________________________________________________________________
max_pooling1d_7 (MaxPooling1 (None, 11, 64)            0         
_________________________________________________________________
lstm_7 (LSTM)                (None, 100)               66000     
_________________________________________________________________
dense_7 (Dense)              (None, 3)                 303       
=================================================================
Total params: 2,098,367
Trainable params: 98,367
Non-trainable params: 2,000,000
_________________________________________________________________

Входными данными для вышеуказанной архитектуры будут тренировочные данные

array([[    0,     0,     0, ...,  4867,    22,   340],
       [    0,     0,     0, ...,    12,   327,  2301],
       [    0,     0,     0, ...,   255,   388,  2640],
       ...,
       [    0,     0,     0, ...,    17, 15609, 15242],
       [    0,     0,     0, ...,  9517,  9266,   442],
       [    0,     0,     0, ...,  3399,   379,  5927]], dtype=int32)

формы (19579, 50)

и помечены как горячие кодировки ..

Моя проблема в том, чтобы понять следующее, что именно происходит с моим (19579, 50), когда он проходит через каждый изследующие строки:

model_glove = Sequential()
model_glove.add(Embedding(vocabulary_size, 100, input_length=50, weights=[embedding_matrix], trainable=False))
model_glove.add(Dropout(0.5))
model_glove.add(Conv1D(64, 5, activation='relu')) 
model_glove.add(MaxPooling1D(pool_size=4))

Я понимаю, почему нам нужно model_glove.add(Dropout(0.5)), это означает отключение некоторых скрытых модулей с вероятностью 0,5, чтобы избежать чрезмерной сложности модели.Но я понятия не имею, зачем нам нужны Conv1D(64, 5, activation='relu'), MaxPooling1D(pool_size=4) и как это входит в мой model_glove.add(LSTM(100)) блок ..

1 Ответ

0 голосов
/ 10 декабря 2018

Самый простой способ понять convolution - это думать о нем как о сопоставлении, которое сообщает нейронной сети, какие функции (пиксели в случае распознавания изображений, где вы будете использовать двумерную свертку; или слова до или послезаданное слово для текста, где вы будете использовать 1D свертки) находятся поблизости.Без этого сеть не может знать, что слова непосредственно перед или сразу после данного слова более актуальны, чем слова, которые находятся намного дальше.Как правило, это также приводит к тому, что информация представляется в гораздо более плотно упакованном формате, что значительно сокращает количество параметров (в вашем случае - с 2 миллионов до 30 тысяч).Я нахожу, что этот ответ объясняет техническую часть его работы довольно хорошо: https://stackoverflow.com/a/52353721/141789

Max pooling - это метод, который уменьшает ваши данные.Он часто используется непосредственно после сверток и достигает двух вещей:

  1. Это снова уменьшает количество параметров.В вашем случае это будет представлять четыре значения с одним значением (максимум из четырех значений).Это делается путем взятия первых четырех значений, затем «шага» четвертого размера и следующих четырех значений и т. Д. Другими словами, между пулами не будет перекрытия.(Это то, что делает keras по умолчанию, но вы также можете установить шаг 2, например)
  2. Во-вторых, потому что он принимает значение max, теоретически в «резкости» контраст междупулы, взяв максимальное значение вместо, например, взяв среднее.

Максимальное объединение не «изучено»;это всего лишь простой арифметический расчет.Именно поэтому количество параметров задано равным нулю.То же самое для dropout.

. LSTM ожидает трехмерный ввод формы (number of samples, number of timesteps, number of features).Выполнив предыдущие шаги свертки и максимального объединения, вы сократили представление вашего начального вложения до number of timesteps = 11 и number of features = 64.Первое значение number of samples = None является заполнителем для batch size, который вы планируете использовать.Инициализируя LSTM с помощью 100 units (также известного как hidden states), вы параметризуете размер «памяти» LSTM: по существу, накопление его входных, выходных и забытых шлюзов во времени.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...