#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?), а не машинного обучения. Машинное обучение было бы лучше, если бы вы хотели обнаружить свои кластеры и центроиды.