Последовательности

Коротко

Definition

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

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

Примеры последовательностей:

  • текст как последовательность токенов;
  • временной ряд как последовательность измерений;
  • аудиосигнал как последовательность отсчётов;
  • ДНК или белок как последовательность символов;
  • история действий пользователя;
  • последовательность событий в системе.

Что это за данные

Последовательность обычно можно записать так:

где:

  • — элемент последовательности на шаге ;
  • — длина последовательности;
  • — весь объект.

Каждый элемент может быть:

  • числом;
  • вектором признаков;
  • словом или токеном;
  • событием;
  • символом;
  • изображением или другим объектом.

Важная особенность: длина последовательности может быть разной. Один текст может содержать 10 токенов, другой — 1000. Один временной ряд может длиться час, другой — месяц.

Как обычно представлены

Последовательности можно представлять разными способами.

Как список элементов

Пример текстовой последовательности:

ШагЭлемент
1machine
2learning
3model

Порядок важен: machine learning model и model learning machine имеют разный смысл.

Как матрица признаков

Если каждый шаг описан вектором признаков, последовательность можно представить как матрицу:

где:

  • — длина последовательности;
  • — размерность признаков на каждом шаге;
  • — последовательность признаков.

Например, во временном ряду на каждом шаге могут быть температура, давление и влажность.

Как токены и embeddings

В NLP текст сначала разбивают на токены, а затем каждый токен превращают в векторное представление.

Например:

ТокенEmbedding
machineвектор
learningвектор
modelвектор

Такие представления используются в LSTM, Seq2Seq и трансформерах.

Какие задачи решают

На последовательностях решают разные задачи.

Классификация последовательности

Нужно отнести всю последовательность к классу.

Примеры:

  • определить тональность текста;
  • классифицировать сигнал как нормальный или аномальный;
  • определить тип активности по временным измерениям;
  • классифицировать белковую последовательность.

Это вариант классификации.

Регрессия по последовательности

Нужно предсказать число по всей последовательности.

Примеры:

  • предсказать спрос по истории продаж;
  • предсказать температуру через несколько часов;
  • оценить риск события по истории пациента;
  • предсказать численное свойство белковой последовательности.

Это вариант регрессии.

Предсказание следующего элемента

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

Примеры:

  • language modeling;
  • прогнозирование временного ряда;
  • предсказание следующего действия пользователя.

Sequence-to-sequence

Нужно преобразовать одну последовательность в другую.

Примеры:

  • машинный перевод;
  • суммаризация текста;
  • распознавание речи;
  • генерация ответа;
  • преобразование временного ряда в другой временной ряд.

Для таких задач используется идея Seq2Seq.

Разметка каждого элемента

Нужно предсказать метку для каждого шага последовательности.

Примеры:

  • named entity recognition;
  • part-of-speech tagging;
  • разметка событий во временном ряду;
  • сегментация сигнала.

Какие модели подходят

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

Классические варианты:

  • n-gram models для текстов;
  • Hidden Markov Models для последовательных состояний;
  • autoregressive models для временных рядов;
  • простые признаки по окнам и агрегатам.

Нейросетевые варианты:

  • Рекуррентный слой — базовый механизм обработки последовательности шаг за шагом;
  • LSTM — рекуррентная архитектура, лучше работающая с долгими зависимостями;
  • Seq2Seq — архитектура для преобразования одной последовательности в другую;
  • Attention — механизм выбора важных элементов последовательности;
  • Трансформер — архитектура, основанная на attention и хорошо подходящая для длинных последовательностей.

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

Типичная предобработка

Предобработка последовательностей зависит от типа данных.

Для текста:

  • очистка текста, если она не разрушает смысл;
  • токенизация;
  • построение словаря или использование готового tokenizer;
  • преобразование токенов в embeddings;
  • ограничение максимальной длины;
  • padding и masks для последовательностей разной длины.

Для временных рядов:

  • сортировка по времени;
  • обработка пропусков;
  • ресемплинг;
  • сглаживание, если это оправдано;
  • построение лаговых признаков;
  • нормализация;
  • разбиение train/test по времени, а не случайно.

Для событийных последовательностей:

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

Важно: при работе с последовательностями особенно легко допустить data leakage. Нельзя использовать будущие элементы для предсказания прошлого.

Частые проблемы

Последовательности разной длины

Модели часто требуют батчи одинаковой формы, а реальные последовательности имеют разную длину.

Для этого используют:

  • padding;
  • masks;
  • truncation;
  • batching по похожим длинам.

Длинные зависимости

Иногда важная информация находится далеко в прошлом.

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

LSTM частично решает эту проблему, а Трансформер часто работает лучше за счёт attention.

Неправильное разбиение данных

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

Если данные из будущего попадут в train, оценка качества будет завышенной. Часто нужно использовать временное разбиение: обучаться на прошлом, проверяться на будущем.

Слишком длинные последовательности

Длинные последовательности требуют много памяти и вычислений. Иногда приходится:

  • обрезать последовательность;
  • разбивать её на окна;
  • использовать агрегированные признаки;
  • выбирать архитектуру, рассчитанную на длинный контекст.

Потеря порядка

Если превратить последовательность в простой набор признаков, можно потерять информацию о порядке.

Например, фразы dog bites man и man bites dog содержат похожие слова, но имеют разный смысл.

Минимальный пример

Допустим, нужно классифицировать отзыв как положительный или отрицательный.

Исходный текст:

ШагТокен
1this
2movie
3is
4good

Модель получает последовательность токенов и должна предсказать класс:

ПоследовательностьЦелевой класс
this movie is goodpositive
this movie is badnegative

Это задача классификации последовательности.

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

Практические замечания

Хороший workflow для последовательностей:

  1. Понять, что является элементом последовательности.
  2. Проверить, важен ли порядок.
  3. Определить задачу: классификация, регрессия, next-step prediction или sequence-to-sequence.
  4. Выбрать способ представления элементов.
  5. Обработать последовательности разной длины.
  6. Сделать корректное train/test split.
  7. Построить простой baseline.
  8. Обучить модель, подходящую для последовательностей.
  9. Оценить качество подходящими метриками.
  10. Проверить ошибки на длинных, коротких и редких последовательностях.

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

Связанные понятия