Я занялся этой точной проблемой несколько недель назад после размышления, что странно, как тестирующим библиотекам, кажется, нужен миллион различных версий Assert
для создания их сообщений описательными.
Краткий обзор - учитывая этот бит кода:
int x = 3;
string t = "hi";
Assert(() => 5*x + (2 / t.Length) < 99);
Мой Утверждать функцию может распечатать следующую сводку того, что передается ей:
(((5 * x) + (2 / t.Length)) < 99) == True where
{
((5 * x) + (2 / t.Length)) == 16 where
{
(5 * x) == 15 where
{
x == 3
}
(2 / t.Length) == 1 where
{
t.Length == 2 where
{
t == "hi"
}
}
}
}
, Таким образом, все имена идентификатора и значения и структура выражения, могли быть включены в сообщение об исключении без Вас имеющий необходимость вновь заявить о них в заключенных в кавычки строках.
Scipy's clustering implementations work well, and they include a k-means implementation.
There's also scipy-cluster, which does agglomerative clustering; ths has the advantage that you don't need to decide on the number of clusters ahead of time.
Из wikipedia , вы можете использовать scipy, K-средство кластеризации векторного квантования
Или , вы можете использовать оболочку Python для OpenCV, ctypes-opencv .
Или вы можете новый интерфейс Python OpenCV и их реализация kmeans .
Вы также можете использовать GDAL, который имеет множество функций для работы с пространственными данными.
SciPy's kmeans2 () имеет некоторые числовые проблемы: другие сообщают сообщения об ошибках, такие как «Матрица не является положительно определенной - разложение Холецкого не может быть вычислено» в версии 0.6.0, и я только что столкнулся с тем же в версии 0.7.1.
На данный момент я бы рекомендовал использовать вместо него PyCluster . Пример использования:
>>> import numpy
>>> import Pycluster
>>> points = numpy.vstack([numpy.random.multivariate_normal(mean,
0.03 * numpy.diag([1,1]),
20)
for mean in [(1, 1), (2, 4), (3, 2)]])
>>> labels, error, nfound = Pycluster.kcluster(points, 3)
>>> labels # Cluster number for each point
array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2], dtype=int32)
>>> error # The within-cluster sum of distances for the solution
1.7721661785401261
>>> nfound # Number of times this solution was found
1
Для непрерывных данных использовать k-среднее очень просто.
Вам нужен список ваших средних значений, и для каждой точки данных найдите среднее значение, наиболее близкое к нему, и усредните новую точку данных к нему. ваши средства будут представлять недавние заметные кластеры точек во входных данных.
Я выполняю усреднение постоянно, поэтому нет необходимости иметь старые данные для получения нового среднего. Учитывая старое среднее значение k
, следующую точку данных x
и константу n
, которая представляет собой количество прошлых точек данных, среднее значение которых сохраняется, новое среднее значение
k*(1-(1/n)) + n*(1/n)
Вот полный код на Python
from __future__ import division
from random import random
# init means and data to random values
# use real data in your code
means = [random() for i in range(10)]
data = [random() for i in range(1000)]
param = 0.01 # bigger numbers make the means change faster
# must be between 0 and 1
for x in data:
closest_k = 0;
smallest_error = 9999; # this should really be positive infinity
for k in enumerate(means):
error = abs(x-k[1])
if error < smallest_error:
smallest_error = error
closest_k = k[0]
means[closest_k] = means[closest_k]*(1-param) + x*(param)
, вы можете просто распечатать средства, когда все данные пройдут, но гораздо интереснее наблюдать, как они меняются в реальном времени. Я использовал его для частотных огибающих 20-миллисекундных битов звука, и после разговора с ним в течение минуты или двух у него были согласованные категории для краткого гласного «а», долгого гласного «о» и согласного «s». странно!