[Перевод] Идёт? Бежит? Поднимается по лестнице? Intel Edison знает ответ

Сегодня мы расскажем о проекте, нацеленном на распознавание некоторых видов физической активности человека. Делается это с помощью платы Intel Edison, к которой подключён акселерометр ADXL345.
64e8bf5ae028c4bbb22c1e120cc518a1.gif

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

В нашем проекте для анализа данных акселерометра используется метод опорных векторов (Support Vector Machine, SVM). Программная часть реализована с применением популярной библиотеки LIBSVM. Код написан в двух вариантах: на Python и Node.js.

Система умеет распознавать следующие виды физической активности: бег, ходьба, подъём и опускание по лестнице. Так же она способна реагировать на состояние покоя. Мы собираем показания акселерометра с некоторыми интервалами, извлекаем интересующие нас значения, в данном случае — значения ускорения по осям X, Y и Z. Затем эти данные используются для создания системы машинного обучения, которая и узнаёт, чем именно занят человек.

612a4e045379b02f6a6192088070d644.gif

Аппаратная реализация


Вот, как акселерометр ADXL345 подключён к Intel Edison.

c26093cc9e7b6021f43af5aa458b4dd9.png
Подключение акселерометра к Edison

Реализация на Python


▍Настройка LIBSVM


Сначала надо загрузить библиотеку LIBSVM и перенести архив LibSVM в корневую папку Intel Edison с использованием WINSCP. Затем архив надо распаковать такой командой:
tar –xzf libsvm-3.21.tar.gz

Теперь надо запустить make в папке libsvm-3.21, далее — make в libsvm-3.21/python.
После этого создадим python-скрипт predict-activity.py в директории libsvm-3.21/python.

▍Чтение показателей акселерометра


Вот, как мы читаем данные акселерометра.
import pyupm_adxl345 as adxl345
# Создаём I2C-объект акселерометра
adxl = adxl345.Adxl345(0)
while True:
    adxl.update() # Получаем новые данные
    raw = adxl.getRawValues() # Считываем необработанные данные
    force = adxl.getAcceleration() # Получаем данные ускорения (g)
   
    forceX=format(force[0],'.2f')
    forceY=format(force[1],'.2f')
    forceZ=format(force[2],'.2f')

sleep(2)

▍Классификация различных видов физической активности


Файл с учебными данными содержит записи для следующих видов физической активности:
0 — ходьба.
1 — бег.
2 — подъём или опускание по лестнице.
3 — отдых.

Вот фрагмент этого файла:
289321279d29fdd799b0f94c336088d8.png

Файл с данными для обучения системы

▍Подбор наилучшего значения параметра C


Параметр C в реализации метода опорных векторов позволяет управлять соотношением между ошибками SVM на учебных данных и максимизацией ширины границы между классами. Он используется при обучении модели и указывает на учёт выбросов при нахождении опорных векторов. Этот параметры мы подбираем, используя метод поиска по сетке.
from svmutil import *
import numpy as nu

param = svm_parameter("-q -h 0")
y, x = svm_read_problem('activity.ds')
problem = svm_problem(y[:100], x[:100])
results = []
for c in range(-10,20):
  for g in range(-10,5):
    param.C, param.gamma = 2**c, 2**g
    m = svm_train(problem,param)
    p_lbl, p_acc, p_val = svm_predict(y[100:],x[100:],m)
    results.append([param.C, param.gamma, p_acc[0]])

bestIdx = nu.argmax(nu.array(results)[:,2])

print results[bestIdx]

35e4cd0d4651b166f4230f45edba81d7.png
Результаты поиска по сетке

▍Классификация физической активности


Вот код, который занят тем, что определяет, чем же занят человек.
#Загрузка библиотеки LIBSVM:
from svmutil import *
#Создание экземпляра svm_problem, здесь activity.ds содержит набор учебных данных
y, x = svm_read_problem('activity.ds')
#Здесь y – это набор меток, представляющих различные виды физической активности, x – набор записей, представляющих значения ускорения по осям X, Y, Z 
m = svm_train(y[0:], x[0:], '-c 0.03125 -h 0 -b 1 -q')
#y[0:] и x[0:] означает, что обучение модели проходит на всём наборе данных
#-h отключить сжатие
#-c : устанавливает параметр стоимости C в C-SVC
#-q: режим работы без вывода данных

values=[[float(forceX),float(forceY), float(forceZ)]]
#forceX,forceY и forceZ данные с акселерометра по соответствующим осям

 p_labels,p_acc,p_values = svm_predict([0]*len(values),values,m])
#передаём данные акселерометра для классификации в метод svm_predict(), который возвращает следующее:
#p_labels: список распознанных видов физической активности
#   p_acc: набор сведений о точности
#p_values: набор оценок вероятностей (если задан параметр '-b 1')
print p_labels
#вывод распознанных видов активности

Реализация на Node.js

▍Подготовка к работе с пакетом node-svm


Создадим папку для проекта в домашней директории платы и установим node-svm:
npm install node-svm

Скопируем папки build и lib из node-modules/node-svm в папку проекта. Далее — установим пакеты, необходимые для работы node-svm. Для этого нужна команда такого вида:
npm install 

Нам понадобятся следующие пакеты:

Stringify-object.

  • Mout.
  • Graceful-fs.
  • Optimist.
  • Osenv.
  • Numeric.
  • Q.
  • underscore.

▍Работа с акселерометром


Вот как выглядит код для чтения показаний акселерометра.
var adxl345 = require('jsupm_adxl345');
var adxl = new adxl345.Adxl345(0);

setInterval(function()
{
    adxl.update(); // Получаем новые данные
    var raw = adxl.getRawValues(); // Считываем необработанные данные
    var force = adxl.getAcceleration(); // Получаем данные ускорения (g)
    var rawvalues = raw.getitem(0) + " " + raw.getitem(1) + " " + raw.getitem(2);
    //console.log("Raw Values: " + rawvalues);
    var forceX=force.getitem(0).toFixed(2);
    var forceY=force.getitem(1).toFixed(2);
    var forceZ=force.getitem(2).toFixed(2);

}, 2000);

Теперь можно написать программу для анализа и классификации активности пользователя, используя значение параметра C, полученного после выполнения поиска по сетке с использованием Python.
var so = require('stringify-object');
var svm = require('./lib');
var numeric = require('numeric');
var fs = require('fs');
var fileName = './activity.ds';

//создаём новый объект классификатора
var clf = new svm.CSVC({
    c: 0.03125,
    normalize: false,
    reduce: false,
});

//Строим модель для обучения
svm.read(fileName)
    .then(function (dataset) {
        return clf.train(dataset)
            .progress(function (progress) {
                console.log('training progress: %d%', Math.round(progress * 100));
            });
    })
    .spread(function (model, report) {
        console.log('SVM trained. \nReport:\n%s', so(report));
    }).done(function () {
        console.log('done.');
    });

//Анализируем данные в некотором временном интервале
var prediction=clf.predictSync([forceX, forceY, forceZ]);
var probability=clf.predictProbabilitiesSync([forceX, forceY, forceZ]);
console.log(prediction);

c81243b60bfdf599be6c35eb841badb4.png
Результаты работы программы на Node.js

Итоги


Как видите, на Intel Edison можно создать систему распознавания физической активности человека, которая способна найти применение в сфере носимых устройств. Для этого понадобится лишь подключить к плате акселерометр и написать программу. Вычислительных возможностей Edison и объёма его оперативной памяти вполне хватает для реализации ресурсоёмкого алгоритма SVM.

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

Комментарии (0)

© Habrahabr.ru