Керас SimpleRNN

Я пытаюсь сделать классификацию Кераса. У меня есть 1043 слова, представленные в виде матриц с горячим кодированием (длиной 20 букв по 26 возможностей для каждой буквы). Каждый из них принадлежит к одной из 19 различных категорий.

X.shape >>>>>> (1043, 20, 26)
Y.shape >>>>>> (1043, 19)

Вот моя попытка построить модель.

model = Sequential()
model.add(SimpleRNN(50, input_shape=(20, 26), return_sequences=True))

model.add(Dense(40, activation='relu'))

model.add(Dense(num_categories, activation='softmax'))

model.compile(loss='categorical_crossentropy', optimizer='adam')
model.fit(X, Y, epochs=20, batch_size=5, verbose=1)

Это вылетает со словами: ValueError: Error when checking target: expected dense_91 to have 3 dimensions, but got array with shape (1043, 19)

Я чувствую, что упускаю что-то очевидное с полем input_shape, или есть какой-то другой трюк с конфигурацией? Я также не смог найти четких примеров такого типа проблем в Интернете.


Обновление: я подозреваю, что мне нужно свернуть временные отрезки в один окончательный ответ, но я не уверен, как это сделать. Есть TimeDistributed, кажется, что он на правильном пути, но я не могу заставить его работать.


person ddg    schedule 02.05.2019    source источник


Ответы (1)


Добавьте слой Flatten() перед добавлением плотного слоя сразу после вывода RNN. Поскольку у вас есть return_sequences=True, keras будет выдавать все скрытые состояния из каждого временного шага обработанной последовательности, что приведет к ошибке при отправке трехмерного тензора (batch_size, timesteps, 50) в плотный слой.

>>> model = Sequential()
>>> model.add(SimpleRNN(50, input_shape=(20, 26), return_sequences=True))
>>> from keras.layers import Flatten
>>> model.add(Flatten())
>>> model.add(Dense(40, activation='relu'))
>>> model.add(Dense(num_categories, activation='softmax'))
>>> model.compile(loss='categorical_crossentropy', optimizer='adam')
>>> model.fit(X, Y, epochs=20, batch_size=5, verbose=1)
1043/1043 [==============================] - 3s 3ms/step - loss: -0.0735

Однако я бы порекомендовал, чтобы вместо того, чтобы return_sequences было True, вы вместо этого не включали этот параметр и направляли его прямо в плотный слой. Вы не решаете проблему seq2seq, для чего в основном используется return_sequences. Вместо этого иди с,

>>> model = Sequential()
>>> model.add(SimpleRNN(50, input_shape=(20, 26)))
>>> model.add(Dense(40, activation='relu'))
>>> model.add(Dense(num_categories, activation='softmax'))
>>> model.compile(loss='categorical_crossentropy', optimizer='adam')
>>> model.fit(X, Y, epochs=20, batch_size=5, verbose=1)
Epoch 1/20
 910/1043 [=========================>....] - ETA: 0s - loss: -0.3609

Окончательные рекомендации заключаются в том, чтобы использовать другую модель RNN, такую ​​как GRU, а также использовать слой Embedding с предварительно обученные векторы слов, такие как из GLoVE. Неиспользование предварительно обученных вложений слов приведет к низкой производительности проверки на небольших наборах данных. Вы можете увидеть 51328897">этот ответ SO, чтобы помочь с использованием этих вложений. Вы также можете ознакомиться с функциональным API keras — он лучше.

person modesitt    schedule 02.05.2019
comment
Большое спасибо! Это именно то, что мне было нужно ‹3 - person ddg; 03.05.2019
comment
Я уже использовал вложения раньше, но этот проект посвящен тому, как слова звучат, а не тому, что они означают, поэтому на этот раз я их пропускаю. Спасибо еще раз! - person ddg; 03.05.2019