Классификация временных рядов для определения усталости у бегунов – Учебник

Определение усталости у бегунов по классификации временных рядов - Учебник

Пошаговое руководство по классификации между участниками и внутри участников, производимой на данных, полученных с носимых сенсоров бегунов

Картинка от автора

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

Данные содержат данные о движениях бегунов в нормальном и утомленном состояниях. Данные были собраны с использованием инерциальных измерительных блоков (IMU) в Университетском колледже Дублина, Ирландия. Данные, используемые в этом руководстве, можно найти по адресу https://zenodo.org/records/7997851. В этом руководстве представлена задача бинарной классификации, где мы пытаемся предсказать между “Утомлен” и “Не утомлен”. В этом руководстве мы используем специализированные пакеты Python, такие как Scikit-learn; инструментарий для машинного обучения на языке Python, и sktime; библиотека, специально созданная для машинного обучения на временных рядах.

В наборе данных содержится несколько каналов данных. Здесь мы моделируем проблему как одномерную для простоты, поэтому используется только один канал данных. Мы выбираем сигнал ускорения величины, поскольку он дает наилучшие результаты [1, 2]. Сигнал величины – это квадратный корень из суммы квадратов каждой из направленных компонент.

Более подробную информацию о сборе и обработке данных можно найти в следующих статьях, [1, 2].

Вкратце, в этом руководстве:

  • Выполняется задача классификации временных рядов с использованием передовых методов классификации временных рядов на данных, собранных с носимых датчиков.
  • Сравниваются модели классификации между участниками (глобальные) и модели классификации внутри участников (персонализированные) для обнаружения утомления у бегунов.

Настройка задачи классификации

Сначала нам нужно загрузить данные, необходимые для анализа. Для этой оценки мы используем данные из файла “Accel_mag_all.csv”. Мы используем библиотеку pandas для загрузки данных. Убедитесь, что вы скачали этот файл по адресу https://10.5281/zenodo.7997850.

import pandas as pdfilename = "Accel_mag_all.csv"data = pd.read_csv(filename, header = None)

Для начала анализа нам потребуются несколько функций из пакетов sktime и sklearn, поэтому мы загружаем их заранее:

from sktime.transformations.panel.rocket import Rocketfrom sklearn.pipeline import make_pipelinefrom sklearn.preprocessing import StandardScalerfrom sklearn.linear_model import RidgeClassifierCV, LogisticRegression, LogisticRegressionCVfrom sklearn.model_selection import LeaveOneGroupOut

Затем мы отделяем метки и номер участника. Данные будут представлены массивами.

import numpy as npX = data.iloc[:,2:].valuesy =  data[1].valuesparticipant_no =  data[0].values

Для этой задачи мы собираемся использовать преобразование Rocket вместе с классификатором Ridge Regression. Rocket – это передовая техника классификации временных рядов [3]. Rocket работает путем генерации случайных сверточных ядер, которые сверточно применяются по временным рядам для создания карты признаков. Затем простой линейный классификатор, такой как Ridge Classifier, используется на этой карте признаков. Можно создать конвейер, который сначала преобразует данные с помощью Rocket, стандартизирует признаки, а затем использует Ridge Classifier для классификации.

rocket_pipeline_ridge = make_pipeline(    Rocket(random_state=0),     StandardScaler(),     RidgeClassifierCV(alphas=np.logspace(-3, 3, 10)))

Глобализированная классификация

В приложениях, где у нас есть данные от нескольких участников, использование всех данных вместе означало бы, что данные отдельного человека могут появиться как в тренировочном, так и в тестовом наборе. Чтобы избежать этого, обычно выполняется анализ, оставляющий одного участника (leave-one-subject-out, LOSO), при котором модель обучается на всех, кроме одного участника, и тестируется на оставшемся участнике. Это повторяется для каждого участника. Такой метод позволяет проверить способность модели к обобщению между участниками.

logo = LeaveOneGroupOut()logo.get_n_splits(X, y, participant_no)Rocket_score_glob = []for i, (train_index, test_index) in enumerate(logo.split(X, y, participant_no)):    rocket_pipeline_ridge.fit(X[train_index], y[train_index])    Rocket_score = rocket_pipeline_ridge.score(X[test_index],y[test_index])    Rocket_score_glob = np.append(Rocket_score_glob, Rocket_score)

Вывод резюме по результатам выше:

print("Результаты глобальной модели")print(f"Средняя точность: {np.mean(Rocket_score_glob)}")print(f"Стандартное отклонение: {np.std(Rocket_score_glob)}")print(f"Минимальная точность: {np.min(Rocket_score_glob)}")print(f"Максимальная точность: {np.max(Rocket_score_glob)}")

Вывод вышеупомянутого кода:

Результаты глобальной моделиСредняя точность: 0.5919805636306338Стандартное отклонение: 0.10360659996594646Минимальная точность: 0.4709480122324159Максимальная точность: 0.8283582089552238

Точность этого анализа LOSO заметно низкая, в некоторых наборах данных результаты даже хуже случайного угадывания. Это указывает на то, что данные одного участника могут плохо обобщаться на другого участника. Это общая проблема при работе с данными личных ощущений, поскольку способность к выполнению упражнений и общая физиология отличаются от одного человека к другому. Кроме того, в этом приложении то, как один человек компенсирует усталость, может отличаться от того, как другой человек компенсирует усталость. Посмотрим, сможем ли мы повысить производительность, персонализируя модели.

Персонализированная классификация

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

Rocket_score_pers = []for i, (train_index, test_index) in enumerate(logo.split(X, y, participant_no)):        #print(f"Participant: {participant_no[test_index][0]}")    label = y[test_index]    X_S = X[test_index]        # Идентификация индексов для каждого класса    class_0_indices = np.where(label == 'NF')[0]    class_1_indices = np.where(label == 'F')[0]        # Разделение каждого класса на тренировочные и тестовые с помощью индексации    class_0_split_index = int(0.66 * len(class_0_indices))    class_1_split_index = int(0.66 * len(class_1_indices))    X_train = np.concatenate((X_S[class_0_indices[:class_0_split_index]], X_S[class_1_indices[:class_1_split_index]]), axis=0)    y_train = np.concatenate((label[class_0_indices[:class_0_split_index]], label[class_1_indices[:class_1_split_index]]), axis=0)        X_test = np.concatenate((X_S[class_0_indices[class_0_split_index:]],X_S[class_1_indices[class_1_split_index:]]), axis=0)    y_test = np.concatenate((label[class_0_indices[class_0_split_index:]], label[class_1_indices[class_1_split_index:]]), axis=0)        rocket_pipeline_ridge.fit(X_train, y_train)    Rocket_score_pers = np.append(Rocket_score_pers, rocket_pipeline_ridge.score(X_test,y_test))

Вывод резюме по вышепоказанным результатам, как и раньше:

print("Результаты персонализированной модели")
print(f"средняя точность: {np.mean(Rocket_score_pers)}")
print(f"стандартное отклонение: {np.std(Rocket_score_pers)}")
print(f"минимальная точность: {np.min(Rocket_score_pers)}")
print(f"максимальная точность: {np.max(Rocket_score_pers)}")

Вывод из приведенного кода:

Результаты персонализированной модели
средняя точность: 0.9517626092184379
стандартное отклонение: 0.07750979452994386
минимальная точность: 0.7037037037037037
максимальная точность: 1.0

Персонализация моделей приводит к значительному улучшению производительности. Таким образом, в данном приложении ясно, что есть трудности в обобщении результатов с одного человека на другого.

Заключение

Для классификации данных временных рядов с помощью носимых датчиков была использована передовая техника Rocket. Анализ показал, что в данной области персонализация моделей приводит к лучшей производительности классификационных моделей.

Точность, полученная через глобальную классификацию по сравнению с персонализированной классификацией для каждого участника

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

Код, представленный в этом руководстве, также можно найти на GitHub: https://github.com/bahavathyk/TSC_for_Fatigue_Detection

Ссылки:

[1] B. Kathirgamanathan, T. Nguyen, G. Ifrim, B. Caulfield, P. Cunningham. Исследование усталости бегунов с использованием временных рядов датчиков носимых устройств, XKDD 2023: 5-ая международная конференция по поиску объяснительного знания в датамайнинге, ECML PKDD, 2023, http://xkdd2023.isti.cnr.it/papers/223.pdf

[2] B. Kathirgamanathan, B. Caulfield and P. Cunningham, “На пути к глобализированным моделям классификации упражнений с использованием инерциальных измерительных устройств”, 2023 IEEE 19-я международная конференция по сенсорным сетям (BSN), Бостон, МА, США, 2023, с. 1–4, doi: 10.1109/BSN58485.2023.10331612.

[3] A. Dempster, F. Petitjean и G. I.Webb. ROCKET: исключительно быстрая и точная классификация временных рядов с использованием случайных сверточных ядер. Data Mining and Knowledge Discovery, 34(5):1454–1495, 2020.