Как подготовить данные со значениями времени для кластеризации?

#c# #ml.net

#c# #ml.net

Вопрос:

Я пытаюсь применить кластеризацию KMeans к набору данных со значениями временных меток. В наборе данных есть другие столбцы, такие как Id (int), Side (логическое значение), Quarter (int), Half (int). Но я хочу выполнить кластеризацию только с использованием столбца timestamp. Как я могу создать конвейер, используя MLContext для этого?

Набор данных выглядит следующим образом:

 DataSet
{
        public int Contract_Id { get; set; }
        public System.DateTime TimeStamp { get; set; }
        public bool Side { get; set; }
        public int Quarter { get; set; }
        public int Half { get; set; }
}
  

У меня есть утилита, возвращающая набор данных, с которым мне нужно работать, из базы данных SQL. Я использую набор данных для загрузки MLContext, а затем использую функцию Kmeans для создания конвейера, используя столбец TimeStamp в качестве входных данных объекта и ClusterId в качестве имени выходных данных.

 var data = unitOfWork.Repository.GetPastFiveSeconds(); // get past 5 sec data from now

var trainData = mlContext.Data.LoadFromEnumerable(data);

var pipeline = mlContext.Clustering.Trainers.KMeans("TimeStamp", "ClusterId", Convert.ToInt32(Math.Ceiling(  (double)5 / data.Count()   ))); // C# stuff to convert to int :/

var model = pipeline.Fit(trainData);
  

Я хочу получить массив кластеров с точками данных, правильно назначенными кластеру, но я получаю исключение — столбец ClusterId ‘Weight’ не найден

РЕДАКТИРОВАТЬ: Попробовал удалить параметр ClusterId из функции KMeans и присвоить ему значение null и добавил шаг преобразования

 mlContext.Transforms.Conversion.ConvertType("TimeStampFloat", "TimeStamp", DataKind.Single)
.Append(mlContext.Clustering.Trainers.KMeans("TimeStampFloat",null, Convert.ToInt32(Math.Ceiling(  (double)5 / trades.Count()   ))))
  

но теперь я получаю сообщение об ошибке «Несоответствие схемы для столбца объектов ‘TimeStampFloat’: ожидаемый вектор, получено имя параметра R4 r nParameter: inputSchema»

Ответ №1:

Второй параметр в KMeans, в вашем случае вы передаете «ClusterId», — это название столбца начальных весов.

Похоже, у вас нет свойства ClusterId в вашем типе набора данных, поэтому он не может его найти.

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

Итак, попробуйте:

 var pipeline = mlContext.Clustering.Trainers.KMeans("TimeStamp");

  

Вам потребуется некоторая предварительная обработка вашей временной метки, поскольку она является системной.Тип DateTime. KMeans (и большинство ML.NET алгоритмы) будут ожидать типы с плавающей запятой. Добавьте Transforms.Conversion.ConvertType в свой конвейер.

Комментарии:

1. Не могли бы вы, пожалуйста, проверить мою правку? Я попытался сделать то, что вы сказали, и теперь это выдает мне другую ошибку

2. Отредактировано снова .. исправлены параметры для KMeans. Теперь какая-то ошибка схемы

Ответ №2:

Ответ на редактирование:

Столбец объектов KMeans должен быть вектором значений с плавающей точкой, потому что обычно существует много столбцов объектов, объединенных вместе. Это взлом, но если вы добавите Concatenate в свой конвейер, после Convert и перед KMeans, он должен быть успешным:

 mlContext.Transforms.Conversion.ConvertType("TimeStampFloat", "TimeStamp", DataKind.Single)
.Append(ml.Transforms.Concatenate("TimeStampFloat", new [] {"TimeStampFloat"}))
.Append(mlContext.Clustering.Trainers.KMeans("TimeStampFloat",null, 5))
  

Комментарии:

1. Да, это сработало. Но все данные назначаются одному кластеру, даже если они разделены более чем на минуту!

2. Как выглядят данные? Если они представляют собой большие значения с плавающей запятой, одной минуты может быть недостаточно, чтобы кластеризировать их по отдельности.

3. Некоторые значения временных меток данных отличаются друг от друга несколькими секундами или несколькими минутами, например: 15:47:00 15:47:03 15:49:00 15:49:03 15:49:03 15:49:52 15:54:57 16:00:00 17:07:49 17:08:12 17:08:12 17:09:13 17:09:13 10:00:05 10:01:00 10:01:00 10:01:00 11:10:00 11:10:00 11:10:15 11:01:00 11:02:00 11:03:00

4. На самом деле, если я задаю количество кластеров равным 5, KMeans выдает исключение — «Слишком мало примеров», и если я задаю ему значение Math.Ceil(5 / data.count()) , которое, вероятно, равно 1, оно помещает все примеры в один кластер. Для приведенных выше данных, как мне объединить их в 13 кластеров — по одному на каждую минуту

5. Если данные являются непрерывными, как это, может помочь предварительная обработка и отделение минуты от секунды, каждого в отдельном столбце. Вы можете использовать минуты в качестве столбца признаков, если это ваш единственный критерий. Но, если вы знаете, что хотите сгруппировать данные в кластеры, и каждый кластер будет минутным индикатором, возможно, было бы проще сделать это с помощью более простого кода (linq, просто инструкции switch?), а не машинного обучения. Машинное обучение было бы лучше, если бы вы хотели обнаружить свои кластеры и центроиды.