У меня есть набор образцов, каждый из которых представляет собой последовательность набора атрибутов (например, образец может состоять из 10 последовательностей, каждая из которых имеет 5 атрибутов). Количество атрибутов всегда фиксировано, но количество последовательностей (которые являются отметками времени) может варьироваться от образца к образцу. Я хочу использовать этот набор образцов для обучения сети LSTM в Keras для решения проблемы классификации, и поэтому я должен добавить размер ввода для всех пакетных образцов, чтобы он был одинаковым. Но процессор pad_sequences
в keras получает фиксированное количество последовательностей с переменными атрибутами и дополняет отсутствующие атрибуты в каждой последовательности, а мне нужно добавлять в каждую выборку больше последовательностей фиксированной длины атрибута. Поэтому я думаю, что не могу его использовать, и поэтому я дополнил свои образцы отдельно и сделал унифицированный набор данных, а затем загрузил его в свою сеть. Но есть ли для этого ярлык с функциями Keras?
Также я слышал о маскировании дополненных входных данных во время обучения, но я не уверен, действительно ли мне это нужно, поскольку мой классификатор присваивает одну метку класса после обработки всей последовательности образцов. мне это нужно? И если да, не могли бы вы помочь мне с простым примером того, как это сделать?
К сожалению, документация вводит в заблуждение, но pad_sequences
делает именно то, что вам нужно. Например, этот код
length3 = np.random.uniform(0, 1, size=(3,2))
length4 = np.random.uniform(0, 1, size=(4,2))
pad_sequences([length3, length4], dtype='float32', padding='post')
приводит к
[[[0.0385175 0.4333343 ]
[0.332416 0.16542904]
[0.69798684 0.45242336]
[0. 0. ]]
[[0.6518417 0.87938637]
[0.1491589 0.44784057]
[0.27607143 0.02688376]
[0.34607577 0.3605469 ]]]
Итак, здесь у нас есть две последовательности разной длины, каждый временной шаг имеет две функции, и результатом является один пустой массив, где более короткая из двух последовательностей дополняется нулями.
Что касается вашего другого вопроса: по моему опыту, маскировка - сложная тема. Но с LSTM должно быть все в порядке. Просто используйте слой Masking()
в качестве самого первого. По умолчанию это заставит LSTM игнорировать все нули, поэтому в вашем случае именно те, которые вы добавили с помощью заполнения. Но вы можете использовать любое значение для маскирования, так же как вы можете использовать любое значение для заполнения. Если возможно, выберите значение, которое не встречается в вашем наборе данных.
Если вы не используете маскирование, это может привести к тому, что ваш LSTM узнает, что дополненные значения действительно имеют какое-то значение, хотя на самом деле это не так.
Например, если во время тренировки вы кормите последовательность
[[1,2],
[2,1],
[0,0],
[0,0],
[0,0]]
а позже в обученной сети вы только подаете
[[1,2],
[2,1]]
Вы можете получить неожиданные результаты (хотя и не обязательно). Маскирование позволяет избежать этого, исключая замаскированное значение из обучения.
@Shahriar49 просто поставил None
для этого измерения
Я попробовал некоторые симуляции классификации растительного покрова на моих выборочных данных (серия последовательностей изображений Landsat с 6 атрибутами для каждого наблюдения) с некоторыми сетями LSTM малого и среднего размера, и я пробовал как предварительное, так и пост-заполнение, а также включение / отключение маскирования. Я обнаружил, что пост-заполнение иногда превосходит предварительное заполнение по точности вывода, и, что более удивительно, отсутствие маскирования иногда лучше, чем маскирование (а не наоборот). У вас есть комментарий?
@ Shahriar49 это было бы действительно удивительно. Насколько велик ваш набор данных? Если слишком мало, это может быть просто совпадением. Кроме того, что именно вы подразумеваете под «точностью вывода»? Не сравнивайте точность, достигнутую на тренировках! В них нет никакого смысла! Убедитесь, что вы тестируете свою обученную модель на достаточно большом наборе тестовых данных (она не должна быть затронута во время обучения!). Убедитесь, что все разные модели обучены на одних и тех же данных и протестированы на одних и тех же данных. Только тогда точность теста имеет какое-то значение, и вы можете их сравнивать.
Спасибо за ответ. Да, я смотрел на точность тестирования (и данные тестирования были полностью отделены от обучения), но размер тестовых данных был порядка десяти тысяч последовательностей, что не очень много. Я постараюсь увеличить размер тестовых данных и посмотрим, как все пойдет. Но должны ли у меня быть большие данные поезда или тестовые данные, чтобы иметь правильное сравнение? Я думаю, что размер обучающих данных более важен, потому что маскирование повлияет на обученный классификатор.
Также я столкнулся с проблемой, которая не позволяет мне использовать маскирование в моих следующих испытаниях на моем графическом процессоре Nvidia: LSTM CuDNN не поддерживает маскирование :(
Извините, у меня другая проблема! Я могу применять pad_sequences, когда я загружаю свою модель массивами numpy, поскольку у меня есть доступ ко всем данным, но как я могу это сделать, когда я загружаю свою модель через API набора данных? В API набора данных моя обработка выполняется на основе одного примера (parse_single_example), и я не знаю, как обрабатывать пакет, поскольку у меня нет к нему доступа (сам генератор данных передается в функцию model.fit() и он будет генерировать пакеты и автоматически передавать их в сеть).
@ Shahriar49, извините, но это выходит за рамки того, что можно было бы легко уточнить в комментарии. Я предлагаю вам открыть отдельные вопросы для всего этого. Что касается LSTM на GPU: это одна из «сложных» вещей маскировки. Он просто не поддерживается для всех слоев, которые нам нужны :(
Ты прав! Приносим извинения за неудобства и благодарим за постоянное внимание. На самом деле я создал еще один пост для моего последнего вопроса несколько минут назад.
Еще один вопрос: когда я определяю свою модель, я должен указать форму ввода на входном слое LSTM (который включает в себя как длину последовательности, так и количество атрибутов). Как я могу сделать его переменным, не переопределяя модель для каждой партии?