Скажімо, у вас є дані часового ряду з рядками і 700 стовпцями, які ви хочете подати на шар у Керасі. Перш ніж подавати їх у RNN, вам потрібно переробити попередні дані до 3D-тензора. Так він стає N × 700 × 1 .N700SimpleRNN(200, return_sequence=True)
N×700×1
Зображення взято з https://colah.github.io/posts/2015-08-Understanding-LSTMs
У RNN ваші стовпці ("700 стовпців") - це часові кроки RNN. Ваші дані обробляються від . Після подачі даних в RNN, тепер він має 700 виходів, що h від 1 до h 700 , а не h 1 до h 200 . Пам'ятайте, що тепер форма ваших даних становить N × 700 × 200, що є зразками (рядками) x часовими кроками (стовпцями) x каналами .t=1 to 700h1h700h1h200N×700×200
А потім, застосовуючи a TimeDistributedDense
, ви наносите Dense
шар на кожен часовий крок, а це означає, що ви наносите Dense
шар на кожен , h 2 , ..., h t відповідно. Що означає: фактично ви застосовуєте повністю підключену операцію на кожному з її каналів ("200") відповідно від h 1 до h 700 . 1-й " 1 × 1 × 200 " до 700-го " 1 × 1 × 200 ".h1h2hth1h7001×1×2001×1×200
Чому ми це робимо? Тому що ви не хочете згладжувати вихід RNN.
Чому б не згладити вихід RNN? Тому що ви хочете зберігати значення кожного кроку часу окремо.
Навіщо тримати значення кожного кроку часу окремо? Тому що:
- ви хочете взаємодіяти між значеннями між власним часовим кроком
- ви не хочете мати випадкову взаємодію між різними часовими кроками та каналами.