Как обучить модель LSTM с различными метками N-измерений?

Я использую keras (ver. 2.0.6 с TensorFlow backend) для простой нейронной сети:

model = Sequential()
model.add(LSTM(32, return_sequences=True, input_shape=(100, 5)))
model.add(LSTM(32, return_sequences=True)) 
model.add(TimeDistributed(Dense(5)))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy',
              optimizer='rmsprop',
              metrics=['accuracy'])

это только тест для меня, я "тренирую" модель со следующими фиктивными данными.

x_train = np.array([
    [[0,0,0,0,1], [0,0,0,1,0], [0,0,1,0,0]],
    [[1,0,0,0,0], [0,1,0,0,0], [0,0,1,0,0]],
    [[0,1,0,0,0], [0,0,1,0,0], [0,0,0,1,0]],
    [[0,0,1,0,0], [1,0,0,0,0], [1,0,0,0,0]],
    [[0,0,0,1,0], [0,0,0,0,1], [0,1,0,0,0]],
    [[0,0,0,0,1], [0,0,0,0,1], [0,0,0,0,1]]
])

y_train = np.array([
    [[0,0,0,0,1], [0,0,0,1,0], [0,0,1,0,0]],
    [[1,0,0,0,0], [0,1,0,0,0], [0,0,1,0,0]],
    [[0,1,0,0,0], [0,0,1,0,0], [0,0,0,1,0]],
    [[1,0,0,0,0], [1,0,0,0,0], [1,0,0,0,0]],
    [[1,0,0,0,0], [0,0,0,0,1], [0,1,0,0,0]],
    [[1,0,0,0,0], [0,0,0,0,1], [0,0,0,0,1]]
])

затем я делаю:

model.fit(x_train, y_train, batch_size=2, epochs=50, shuffle=False)

print(model.predict(x_train))

результат:

[[[ 0.11855114  0.13603994  0.21069065  0.28492314  0.24979511]
  [ 0.03013871  0.04114409  0.16499813  0.41659597  0.34712321]
  [ 0.00194826  0.00351031  0.06993906  0.52274817  0.40185428]]

 [[ 0.17915446  0.19629011  0.21316603  0.22450975  0.18687972]
  [ 0.17935558  0.1994358   0.22070852  0.2309722   0.16952793]
  [ 0.18571526  0.20774922  0.22724937  0.23079531  0.14849086]]

 [[ 0.11163659  0.13263632  0.20109797  0.28029731  0.27433187]
  [ 0.02216373  0.03424517  0.13683401  0.38068131  0.42607573]
  [ 0.00105937  0.0023865   0.0521594   0.43946937  0.50492537]]

 [[ 0.13276921  0.15531689  0.21852671  0.25823513  0.23515201]
  [ 0.05750636  0.08210614  0.22636817  0.3303588   0.30366054]
  [ 0.01128351  0.02332032  0.210263    0.3951444   0.35998878]]

 [[ 0.15303896  0.18197381  0.21823004  0.23647803  0.21027911]
  [ 0.10842207  0.15755147  0.23791778  0.26479205  0.23131666]
  [ 0.06472684  0.12843341  0.26680911  0.28923658  0.25079405]]

 [[ 0.19560908  0.20663913  0.21954383  0.21920268  0.15900527]
  [ 0.22829761  0.22907974  0.22933882  0.20822221  0.10506159]
  [ 0.27179539  0.25587022  0.22594844  0.18308094  0.063305  ]]]

ок, это работает, но это просто тест, я действительно не заботятся о точности и т. д. Хотелось бы понять, как я могу работать с выходом разного размера.

например: передача последовательности (numpy.array) нравится:

[[0,0,0,0,1], [0,0,0,1,0], [0,0,1,0,0]]

Я хотел бы получить 4 измерения вывода в качестве прогноза:

[[..first..], [..second..], [..third..], [..four..]]

это как-то возможно? Размер может варьироваться я бы обучил модель с разными метками, которые могут иметь разные N-размеры.

спасибо

3 ответов


этот ответ для не меняя размеров, но для меняя размеров,обивка идея в ответе Джузеппе кажется, что путь, возможно, с помощью "маскировка" предложено в документации Keras.


выходная форма в Keras полностью зависит от количества "единиц/нейронов/клеток", которые вы помещаете в последний слой, и, конечно же, от типа слоя.

я вижу, что ваши данные не совпадают код ваш вопрос, это невозможно, но, предположим, ваш код прав и забудьте данные на некоторое время.

An форма входа (100,5) в слое LSTM означает тензор формы (None, 100, 5), которая составляет

  • None - это размер пакета. Первое измерение ваших данных зарезервировано для примеры у вас есть. (X и y должны иметь одинаковое количество примеров).
  • каждый пример-это sequence with 100 time steps
  • каждый шаг-это 5-dimension vector.

и 32 клеток в этом же слое LSTM означает, что результирующие векторы будут меняться от 5 до 32-мерных векторов. С return_sequences=True, все 100 шагов времени появятся в результате. Таким образом, форма результата первого слоя (None, 100, 32):

  • такое же количество примеров (это никогда не изменится вдоль модели)
  • еще 100 шагов времени в Примере (потому что return_sequences=True)
  • каждый шаг времени является 32-мерным вектором (из-за 32 ячеек)

теперь второй слой LSTM делает то же самое. Сохраняет 100 шагов времени, и поскольку он также имеет 32 ячейки, сохраняет 32-размерные векторы, поэтому выход также (None, 100, 32)

наконец, время распределено плотным слоем также сохранит 100 шагов времени (из-за TimeDistributed), и измените свои векторы на 5-dimensoin векторы снова (из-за 5 units), в результате чего (None, 100, 5).


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

но во всех из них вам нужно освободиться от временных шагов и перестроить данные с другой формой.


предложение

предложение от меня (что только одна возможность), чтобы изменить свой результат, и применить другой плотный слой только для достижения конечной формы expeted.

Предположим, вы хотите результат, как (None, 4, 5) (никогда не забывайте, что первое измерение ваших данных-это число примеры, это может быть любое число, но вы должны учитывать его при организации ваших данных). Мы можем добиться этого преобразование данных в форму, содержащую 4 во втором измерении:

#after the Dense layer:

model.add(Reshape((4,125)) #the batch size doesn't appear here, 
   #just make sure you have 500 elements, which is 100*5 = 4*125

model.add(TimeDistributed(Dense(5))
#this layer could also be model.add(LSTM(5,return_sequences=True)), for instance

#continue to the "Activation" layer

это даст вам 4 шага времени (потому что размерность после изменения формы была: (None, 4, 125), каждый шаг является 5-мерным вектором(из-за плотного (5)).

использовать model.summary() команда для просмотра фигур, выводимых каждым слоем.


Я не знаю, Керрас, но с практической и теоретической точки зрения это вполне возможно.

идея заключается в том, что у вас есть входной последовательности и выходной последовательности. Обычно начало и конец каждой последовательности разделяются каким-либо специальным символом (например, последовательность символов "cat" переводится в "^cat#" с начальным символом "^" и конечным символом "#"). Затем последовательность дополняется другим специальным символом, вплоть до максимальная длина последовательности (например, "^cat#$$$$$$ "с символом заполнения"$").

Если символ заполнения соответствует нулевому вектору, это не повлияет на ваше обучение.

ваша выходная последовательность теперь может принимать любую длину до максимальной, потому что реальная длина-это одна из позиций символа от начала до конца.

другими словами, у вас всегда будет одинаковая длина входной и выходной последовательности (т. е. максимальная), но реальная длина-это расстояние между начальным и конечным символами.

(очевидно, что в выходной последовательности ничего после символа конца не следует учитывать в функции потерь)


Кажется, есть два метода для выполнения метода последовательности последовательности, который вы описываете. Первый напрямую используя keras используя (код ниже)

from keras.layers import Input, LSTM, RepeatVector
from keras.models import Model

inputs = Input(shape=(timesteps, input_dim))
encoded = LSTM(latent_dim)(inputs)

decoded = RepeatVector(timesteps)(encoded)
decoded = LSTM(input_dim, return_sequences=True)(decoded)

sequence_autoencoder = Model(inputs, decoded)
encoder = Model(inputs, encoded)

где вектор повтора повторяет начальный временной ряд n раз, чтобы соответствовать количеству выходных векторов временных меток. Это все равно будет означать, что вам нужно фиксированное количество временных шагов в выходном векторе, однако может быть метод заполнения векторов, которые имеют меньше временных меток, чем максимальное количество временные шаги.

или вы можете вы seq2seq модуль, который построен на вершине keras.