- PVSM.RU - https://www.pvsm.ru -
Обнаружение аномалий — одна из важнейших функций для решений в области «интернета вещей» (IoT), которые собирают и анализируют временные изменения в потоке данных от различных датчиков. Во многих случаях поток данных со временем не претерпевает значительных изменений. Однако если они появляются, это чаще всего означает, что в системе возникла аномалия, способная нарушить её работу. В этой статье я расскажу, как использовать модуль Time Series Anomaly Detection сервиса машинного обучения Azure Machine Learning для определения аномальных показателей датчиков.
Для раскрытия темы я расширю функционал приложения RemoteCamera Universal Windows Platform (UWP), разработанного мною к предыдущей статье [1], и добавлю список, в котором будут отображаться аномальные значения. Приложение RemoteCamera получает изображение с веб-камеры и вычисляет его яркость, которая при условии неизменности сцены в кадре колеблется вокруг определённых значений. Яркость легко изменить, например, прикрыв камеру рукой, что приведёт к заметному отклонению в потоке данных. Это помогает получить хорошую выборку для обнаружения аномалий во временном ряду.
Согласно недавней статье [2] Джеймса Маккефри, стандартный метод обнаружения аномалий основан на регрессии временного ряда. Наложив модель на данные, вы можете спрогнозировать тенденции, а затем проверить, все ли показатели соответствуют им. Для этого нужно сравнить спрогнозированные и фактические показатели. Значительная разница укажет на отклонение или аномалию.
Сначала я покажу, как находить такие отклонения, анализируя z-оценки. Чем эта оценка больше, тем выше вероятность того, что в потоке значений есть отклонение. Чтобы найти аномалии, нужно определить границы z-оценок, принимаемых за нормальные. Все z-оценки, выходящие за заданные пределы, будут считаться аномальными. Следует принимать во внимание, что из-за фиксированного порога, задаваемого в этом сценарии, возможны многочисленные ложные срабатывания. Чтобы уменьшить их число, применяют более сложные алгоритмы. В нашем случае, модуль Azure Time Series Anomaly Detection основан на перестановочных мартингалах [3], анализирующих, может ли ряд данных быть произвольно реорганизован без потери вероятности обнаружения определённого значения. Проще говоря, может ли каждое значение быть обнаружено в наборе данных с равной вероятностью. Коммутативный набор данных отличается низким коэффициентом аномалий. Если коммутативность нарушена, коэффициент аномалий растёт, указывая на нестандартные значения.
В этой статье я расскажу, как создавать такие алгоритмы машинного обучения. Я буду использовать решение Microsoft Azure Machine Learning Studio. Об этом продукте также рассказывал [4] Джеймс Маккефри в сентябре 2014 года. Я расширю тему этой статьи и продемонстрирую эксперименты с машинным обучением. Кроме того, я покажу, как развернуть полученное решение в виде веб-службы, а затем — как использовать эту службу в приложении RemoteCamera.
Сначала расширим приложение RemoteCamera, добавив вкладку, в которой можно собирать данные для обучения, а также включать или выключать режим обнаружения аномалий при помощи флажка.
Кнопка Acquire training dataset становится активной, если запустить предпросмотр изображения с камеры (при помощи кнопок управления на главной вкладке). При нажатии этой кнопки приложение начинает сбор данных для обучения. Этот процесс проходит в фоновом режиме, его ход сопровождается круговой анимацией. В итоге будет создан набор данных для обучения, состоящий из 100 точек данных. Каждая из них будет представлена экземпляром структуры BrightnessDataPoint:
public struct BrightnessDataPoint
{
public DateTime Time { get; private set; }
public byte Brightness { get; private set; }
public BrightnessDataPoint(byte brightness)
{
Time = DateTime.Now;
Brightness = brightness;
}
}
Структура BrightnessDataPoint сохраняет значение яркости, а также время, в которое оно было зафиксировано. Затем набор таких значений экспортируется в файл BrightnessData.csv, который выглядит следующим образом:
Time,Brightness
9/8/2017 11:30:00,103
9/8/2017 11:30:01,103
9/8/2017 11:30:02,102
9/8/2017 11:30:03,42
9/8/2017 11:30:04,46
9/8/2017 11:30:05,149
9/8/2017 11:30:06,99
9/8/2017 11:30:07,101
9/8/2017 11:30:08,104
Затем в текстовом поле отобразится точное расположение набора данных для обучения. Я использую значения, разделённые запятыми (файл CSV). Их легко загрузить в Machine Learning Studio.
Чтобы реализовать этот функционал, я написал два класса: BrightnessFileStorage и AnomalyDetector. Первый класс BrightnessFileStorage определяется файлом BrightnessFileStorage.cs во вложенной папке AnomalyDetection сопроводительного кода. Класс BrightnessFileStorage сохраняет набор объектов BrightnessDataPoint в файл CSV с использованием класса DataWriter [5].
Второй класс AnomalyDetector обрабатывает логику, относящуюся к обнаружению аномалий. В частности, он включает публичный метод Add-TrainingValue, который вызывается сразу после вычисления яркости изображения (см. обработчик событий ImageProcessor_ProcessingDone в файле MainPage.xaml.cs в сопроводительном коде). AddTrainingValue работает следующим образом. Сначала я создаю экземпляр BrightnessDataPoint, который затем добавляется в набор. Когда набор насчитывает 100 элементов, я сохраняю его в файл CSV. Затем я запускаю событие TrainingDataReady, которое обрабатывается в MainPage. Цель — прервать сбор данных для обучения и отобразить в интерфейсе пользователя местонахождение файла:
private async void AnomalyDetector_TrainingDataReady(
object sender, TrainingDataReadyEventArgs e)
{
await ThreadHelper.InvokeOnMainThread(() =>
{
remoteCameraViewModel.IsTrainingActive = false;
remoteCameraViewModel.TrainingDataSetFilePath = e.FilePath;
});
}
private const int trainingDataSetLength = 100;
private List<BrightnessDataPoint> trainingDataSet =
new List<BrightnessDataPoint>();
public event EventHandler<TrainingDataReadyEventArgs> TrainingDataReady;
public async Task AddTrainingValue(byte brightness)
{
trainingDataSet.Add(new BrightnessDataPoint(brightness));
// Check if all data points were acquired
if (trainingDataSet.Count == trainingDataSetLength)
{
// If so, save them to csv file
var brightnessFileStorage =
await BrightnessFileStorage.CreateAsync();
await brightnessFileStorage.WriteData(trainingDataSet);
// ... and inform listeners that the training data set is ready
TrainingDataReady?.Invoke(this,
new TrainingDataReadyEventArgs(
brightnessFileStorage.FilePath));
}
}
Расположение набора данных для обучения будет отображено в текстовом поле, откуда его можно легко скопировать, вставить в Проводник Windows и просмотреть полученные данные.
После получения набора данных для обучения я подготовлю первый эксперимент в Machine Learning Studio согласно инструкциям, описанным в статье Джеймса Маккефри в 2014 году. Для начала я загружаю файл BrightnessData.csv, затем планирую эксперимент с использованием визуального конструктора. Короче говоря, все компоненты находятся в меню в левой части окна Machine Learning Studio. Чтобы разместить элемент на плане вашего эксперимента, просто перетащите его в область эксперимента (это центральная часть окна Machine Learning Studio). У каждого компонента свои входные и выходные данные. Вам нужно соединить совместимые узлы, чтобы контролировать потоки данных между модулями. У компонентов могут быть дополнительные настройки, которые можно задать в окне свойств (в правой части окна Machine Learning Studio).
Алгоритм машинного обучения, изображённый выше, может работать в двух режимах: эксперимент и веб-служба. Различие лишь во входных данных. В режиме эксперимента в их роли выступает загруженный набор данных для обучения (BrightnessData), а в режиме веб-службы — её собственные входные данные. Вне зависимости от режима, входные данные преобразовываются в набор данных, после чего значения столбца яркости нормализуются с помощью преобразования в z-оценки [6]. В ходе этого преобразования значения яркости пересчитываются в z-оценки, которые показывают их разброс относительно среднего значения. Разброс измеряется в среднеквадратичных отклонениях. Чем значительнее этот разброс, тем выше вероятность того, что текущее значение является аномальным. Я применяю нормализацию z-оценок, поскольку зачастую базовый или нормальный уровень яркости зависит от того, что фиксирует камера. Таким образом, преобразование в z-оценку обеспечивает корректный уровень яркости, когда нормализация близка к 0. Необработанные значения яркости различаются в примерном диапазоне от 40 до 150. После нормализации все значения яркости укладываются в пределы примерно от –4.0 до +4.0. Следовательно, чтобы найти аномальные значения, мне нужно лишь применить пороговый фильтр. Я применяю пороговый фильтр OutOfRange в Azure Machine Learning с нижним порогом –2 и верхним 1.5. Я выбрал эти значения на основе графика z-оценок и задал их в панели свойств порогового фильтра в Machine Learning Studio.
После указания порога набор данных представляет собой столбец данных логического типа, где указывается, находится ли в конкретный момент точка вне заданного диапазона. Чтобы дополнить эту информацию фактическими значениями яркости, которые были определены как аномальные, я совмещаю этот столбец с первоначальным набором данных, а затем разбиваю полученный набор на два подмножества. Одно содержит только аномальные значения, второе — стандартные. Перед разбивкой я меняю тип данных в столбце, поскольку модуль Split Data не поддерживает логические значения. После этого в результате эксперимента выдается первое подмножество. В случае с веб-службой, этот результат передаётся клиенту. Чтобы просмотреть значения какого-либо набора данных, нужно использовать опцию Results dataset | Visualize из контекстного меню набора данных в Machine Learning Studio. Эта опция будет доступна, если вы уже запускали данный эксперимент.
А теперь научимся применять модуль Azure Time Series Anomaly Detection (ATSAD) для определения аномалий. Как показано ниже, процесс этого эксперимента напоминает предыдущий. Первоначальный набор данных нормализуется преобразованием в z-оценки и передаётся в модуль ATSAD (он находится в узле Time Series в Machine Learning Studio). Для этого необходимо настроить [7] несколько входных параметров в окне свойств (bit.ly/2xUGTg2). Сначала нужно указать столбцы данных и времени, затем настроить тип мартингала. В нашем случае я буду использовать мартингал Power. Станет доступным ещё одно текстовое поле — Epsilon, где можно ввести любое значение чувствительности детектора в диапазоне от 0 до 1. Затем нужно настроить три параметра функции определения странности значений:
Далее нужно задать максимальное количество значений мартингала и странности в журнале. Можно ввести любое целое число от 10 до 1000. Методом проб и ошибок я остановился на следующих настройках детектора:
Последний параметр детектора — это порог предупреждения. Он задаёт минимальный коэффициент аномальности значений. По умолчанию задан порог предупреждения 3.5. Для своего эксперимента я поменял это значение на 2.
Запросив визуализацию выходных данных модуля ATSAD, можно увидеть, что к набору входных данных добавляется два столбца: коэффициент аномальности, измеряющий отклонения, и индикатор предупреждения с двоичным значением (0 или 1), указывающим на аномальность значения. На основании показаний второго индикатора я разбиваю набор данных на два подмножества: стандартные и аномальные значения. В результате эксперимента выдаётся только подмножество аномальных значений. В остальных деталях эксперимент идентичен предыдущему, и я не буду описывать их заново. Замечу только, что самый важный аспект эксперимента для веб-службы — это описание входных и выходных данных. Назовем эти данные следующим образом: Data (входные данные веб-службы) и AnomalyDetectionResult (выходные данные веб-службы).
После настройки экспериментов я могу развернуть их в виде веб-служб, получить к ним доступ через приложение RemoteCamera и выявлять аномальные показатели яркости изображения. Чтобы создать веб-службу, нужно запустить эксперимент, а затем нажать значок Deploy Web Service в нижней области окна Machine Learning Studio. Если вы не добавили в эксперимент модули ввода и вывода веб-службы, в этой области отобразится кнопка Set Up Web Service. После ее нажатия в эксперимент будут добавлены модули ввода и вывода веб-службы, а название кнопки изменится на Deploy Web Service.
Когда процесс развёртывания веб-службы завершится, откроется панель управления веб-службой. На этой панели отображается сводная информация о развёрнутой веб-службе, ключ API, а также инструкции по отправке запросов и обработке ответов (API Help Page). В частности, при нажатии гиперссылки request/response отображаются URL веб-службы и детальная структура запросов и ответов в формате JSON.
Далее я сохраняю ключ API и создаю маппинги из JSON в C# с помощью службы JSONUtils (jsonutils.com). Затем я сохраняю полученные классы в соответствующие файлы — AnomalyDetectionRequest.cs и AnomalyDetectionResponse.cs во вложенной папке AnomalyDetection. Их структуры схожи — оба файла обычно содержат классы со свойствами, которые по большей части реализуются автоматически. AnomalyDetectionRequest и AnomalyDetectionResponse представляют собой передачу соответствующих объектов JSON между клиентом и веб-службой. К примеру, определение класса AnomalyDetectionRequest и зависимых объектов показано ниже. Обратите внимание, что для преобразования набора точек данных яркости в формат входных данных для веб-службы Machine Learning Studio (двумерные массивы строк) я использую вспомогательный класс ConversionHelper. Полное определение этого вспомогательного класса содержится в сопроводительном коде. Этот класс имеет два публичных метода. С их помощью набор точек данных яркости преобразуются в тип string[,] (BrightnessDataToStringTable) и обратно (AnomalyDetectionResponseToBrightnessData).
public class AnomalyDetectionRequest
{
public Inputs Inputs { get; set; }
public GlobalParameters GlobalParameters { get; set; }
public AnomalyDetectionRequest(
IList<BrightnessDataPoint> brightnessData)
{
Inputs = new Inputs()
{
Data = new Data()
{
ColumnNames = new string[]
{
"Time",
"Brightness"
},
Values = ConversionHelper.
BrightnessDataToStringTable(brightnessData)
}
};
}
}
public class Inputs
{
public Data Data { get; set; }
}
public class Data
{
public string[] ColumnNames { get; set; }
public string[,] Values { get; set; }
}
public class GlobalParameters { }
После создания маппинга объектов из JSON в C# можно приступить к написанию клиента веб-службы. Для этого я сначала установлю пакет Microsoft.AspNet.WebApi.Client NuGet, а затем использую его для определения класса AnomalyDetectionClient (см. соответствующий файл в сопроводительном коде). В этом классе есть три закрытых поля: baseAddress, apiKey and httpClient. В первом поле содержится URL веб-службы Machine Learning Studio, во втором — ключ API. Оба этих значения используются для создания экземпляра класса HttpClient (из установленного ранее пакета NuGet):
public AnomalyDetectionClient()
{
httpClient = new HttpClient()
{
BaseAddress = new Uri(baseAddress),
};
httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", apiKey);
}
После создания клиента я могу начать отправку запросов в веб-службу Machine Learning Studio при помощи метода AnomalyDetectionClient.DetectAnomalyAsync. Этот метод обеспечивает получение набора точек данных яркости в качестве тестовых данных. Эти тестовые данные используются вместо файла CSV, который я использовал для экспериментов. С их помощью создается экземпляр запроса AnomalyDetection. Экземпляр этого класса затем отправляется в веб-службу для анализа при помощи метода расширения PostAsJsonAsync. Полученный ответ JSON преобразуется в экземпляр класса AnomalyDetectionResponse, который в итоге выдаётся функцией DetectAnomalyAsync. Смотрим, нет ли ошибок. Если необходимо, «выбрасываем» исключения.
public async Task<IList<BrightnessDataPoint>>
DetectAnomalyAsync(IList<BrightnessDataPoint> brightnessData)
{
var request = new AnomalyDetectionRequest(brightnessData);
var response = await httpClient.PostAsJsonAsync(string.Empty, request);
IList<BrightnessDataPoint> result;
if (response.IsSuccessStatusCode)
{
var anomalyDetectionResponse = await
response.Content.ReadAsAsync<AnomalyDetectionResponse>();
result = ConversionHelper.
AnomalyDetectionResponseToBrightnessData(anomalyDetectionResponse);
}
else
{
throw new Exception(response.ReasonPhrase);
}
return result;
}
AnomalyDetectionClient используется в методе AddTestValue класса AnomalyDetector. Как и AddTrainingValue, AddTestValue также вызывается обработчиком событий ImageProcessor_ProcessingDone (см. файл MainPage.xaml.cs в сопроводительном коде). Однако AddTestValue работает немного иначе, чем метод AddTrainingValue. В AddTrainingValue я добавляю точки данных яркости в экземпляр класса BrightnessDataset, который на внутреннем уровне использует универсальный класс List для введения скользящего интервала. В этом интервале хранятся тестовые значения (см. октябрьскую статью Джеймса Маккефри). По умолчанию скользящий интервал насчитывает 30 элементов, но это значение можно менять при помощи конструктора BrightnessDataset. Как показано на ниже, я отправляю данные для анализа после заполнения интервала. Затем проверяю наличие элементов в наборе аномальных значений, выданном веб-службой. Если элементы присутствуют, я запускаю событие AnomalyDetected, которое также используется для передачи аномалий в прослушиватели.
public event EventHandler<AnomalyDetectedEventArgs> AnomalyDetected;
private BrightnessDataset dataSet = new BrightnessDataset();
public async Task AddTestValue(byte brightness)
{
dataSet.Add(new BrightnessDataPoint(brightness));
if (dataSet.IsFull)
{
try
{
var anomalousValues = await anomalyDetectionClient.
DetectAnomalyAsync(dataSet.Data);
if (anomalousValues.Count > 0)
{
AnomalyDetected?.Invoke(this,
new AnomalyDetectedEventArgs(anomalousValues));
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
}
}
Чтобы отобразить аномальные значения в интерфейсе, я обрабатываю событие AnomalyDetected в классе MainPage следующим образом.
private async void AnomalyDetector_AnomalyDetected(
object sender, AnomalyDetectedEventArgs e)
{
await ThreadHelper.InvokeOnMainThread(() =>
{
foreach (var anomalousValue in e.AnomalousValues)
{
if (!remoteCameraViewModel.AnomalousValues.Contains(anomalousValue))
{
remoteCameraViewModel.AnomalousValues.Add(anomalousValue);
}
}
});
}
Я выполняю итерацию набора полученных значений, проверяя, не были ли они уже добавлены в локальное хранилище данных (свойство AnomalousValues модели просмотра). Если нет, то я добавляю их в набор наблюдаемых значений. В результате этого в списке, показанном на первой картинке, появятся только новые аномальные значения. Эта дополнительная проверка нужна, поскольку за время между двумя последовательными запросами в веб-службу в скользящем интервале изменился только один элемент.
Для тестирования моего решения нужно запустить приложение RemoteCamera, начать предпросмотр изображения с камеры и включить поиск аномалий, установив флажок на вкладке Anomaly Detection. После этого можно создавать аномальные значения, прикрывая камеру рукой. Детектор машинного обучения быстро выявит эти аномальные значения и отобразит их в окне списка.
Я показал процедуру создания двух разных эксперимента по обнаружению аномалий в Azure Machine Learning Studio. Оба эксперимента были развёрнуты также в виде веб-служб и совмещены с клиентским приложением RemoteCamera, которое отправляет локально полученные данные временных рядов для машинного анализа с целью обнаружения аномалий. В данном случае я использовал веб-службу приложения Universal Windows Platform (UWP). Этот же код можно использовать для доступа к веб-службе через веб-приложение ASP.NET, в котором логика машинного обучения обрабатывается серверной частью, а не в конечной точке. В контексте IoT такой точкой может быть простой датчик.
28-30 ноября в Киеве впервые пройдет школа разработчиков в формате Open Hack.
Команды по 2–5 человек смогут поработать над существующим в их компании проектом либо познакомиться с технологическим стеком другого релевантного проекта.
Главными темами станут:
Для участия в мероприятии необходимо зарегистрироваться [8].
Автор: Александр Гуреев
Источник [9]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/microsoft/269201
Ссылки в тексте:
[1] статье: http://msdn.com/magazine/mt809116
[2] статье: http://msdn.com/magazine/mt826350
[3] перестановочных мартингалах: http://bit.ly/2wjBYUU
[4] рассказывал: http://msdn.com/magazine/dn781358
[5] DataWriter: http://bit.ly/2wS31dq
[6] преобразования в z-оценки: http://bit.ly/2eWwHAa
[7] необходимо настроить: http://bit.ly/2xUGTg2
[8] зарегистрироваться: https://events.techdays.ru/Microsoft-Developer-School/2017-11/
[9] Источник: https://habrahabr.ru/post/343188/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best
Нажмите здесь для печати.