Вы можете решить это различными способами. Одним из очевидных при использовании ключевого слова «кластеризация» является использование kmeans (см. Другие ответы).
Однако вы можете сначала лучше понять, что вы на самом деле делаете или пытаетесь сделать. Вместо того, чтобы просто использовать случайную функцию для ваших данных.
Насколько я могу судить по вашему вопросу, у вас есть ряд одномерных значений, и вы хотите разделить их на неизвестное количество групп, верно? Что ж, k-means может сработать, но на самом деле вы можете просто найти самые большие различия в вашем наборе данных k .
То есть для любого индекса i > 0
вычислите k[i] - k[i-1]
и выберите индексы k
, где это больше, чем для остальных. Скорее всего, ваш результат будет на лучше и быстрее, чем при использовании k-means .
В коде Python:
k = 2
a = [1, 2, 3, 60, 70, 80, 100, 220, 230, 250]
a.sort()
b=[] # A *heap* would be faster
for i in range(1, len(a)):
b.append( (a[i]-a[i-1], i) )
b.sort()
# b now is [... (20, 6), (20, 9), (57, 3), (120, 7)]
# and the last ones are the best split points.
b = map(lambda p: p[1], b[-k:])
b.sort()
# b now is: [3, 7]
b.insert(0, 0)
b.append(len(a) + 1)
for i in range(1, len(b)):
print a[b[i-1]:b[i]],
# Prints [1, 2, 3] [60, 70, 80, 100] [220, 230, 250]
(Между прочим, это можно рассматривать как простую одноканальную кластеризацию!)
Более продвинутый метод, который фактически избавляется от параметра k
, вычисляет среднее значение и стандартное отклонение b[*][1]
и разбивает, где значение больше, чем, скажем, mean+2*stddev
. Тем не менее, это довольно грубая эвристика. Другим вариантом было бы предположить фактическое распределение значений, такое как k
нормальные распределения, а затем использовать, например, Levenberg-Marquardt для соответствия распределений вашим данным.
Но действительно ли это то, что вы хотите сделать?
Сначала попытайтесь определить , что должно быть кластером, а что , а не . Вторая часть гораздо важнее.