Python - Кластеризация с помощью K-средних. Некоторые столбцы с нулевой дисперсией

У меня есть набор данных, состоящий из ~ 200 массивов частот 99x20, где сумма каждого столбца равна единице. Я построил их с помощью тепловых карт, например this. Каждый массив довольно разрежен, только около 1-7 / 20 значений на 99 позиций отличны от нуля.

Однако я хотел бы сгруппировать эти выборки с точки зрения того, насколько похожи их частотные профили (минимальное евклидово расстояние или что-то в этом роде). Я организовал каждый массив 99x20 в массив 1980x1 и собрал их в массив наблюдения 200x1980.

Прежде чем найти кластеры, я попробовал отбелить данные с помощью scipy.cluster.vq.whiten. whiten нормализует каждый столбец по его дисперсии, но из-за того, как я выровнял свои массивы данных, у меня есть несколько (8) столбцов со всеми нулевыми частотами, поэтому дисперсия равна нулю. Следовательно, белый массив имеет бесконечные значения, и определение центроида не выполняется (или дает ~ 200 центроидов).

Мой вопрос: как мне решить эту проблему? Пока я пробовал

  • Не отбеливайте данные. Это приводит к тому, что k-means при каждом запуске дает разные центроиды (что несколько ожидаемо), несмотря на значительное увеличение ключевого слова iter.
  • Транспонирование массивов перед их выравниванием. Столбцы с нулевой дисперсией просто сдвигаются.

Можно ли просто удалить некоторые из этих столбцов с нулевой дисперсией? Может ли это каким-либо образом повлиять на кластеризацию?

РЕДАКТИРОВАТЬ: Я также пробовал использовать свою собственную функцию отбеливания, которая просто делает

for i in range(arr.shape[1]):
    if np.abs(arr[:,i].std()) < 1e-8: continue
    arr[:,i] /= arr[:,i].std()

Кажется, это работает, но я не уверен, что это каким-либо образом влияет на кластеризацию.

Спасибо


person wflynny    schedule 21.03.2013    source источник
comment
В качестве незначительной точки кодирования при проверке значений 0,0 с плавающей запятой не используйте проверки равенства. if arr[:,i].std() == 0 должно быть if abs(arr[:,i].std()) < epsilon, где эпсилон - очень маленькое значение, например 0,0000001. В противном случае вы можете получить ошибки округления, из-за которых 0 значение с плавающей запятой будет отображаться как ненулевое. Для данной проблемы это всегда может работать нормально, но в целом описанный выше способ является лучшим способом выполнения плавающих проверок «равенства».   -  person Pyrce    schedule 21.03.2013
comment
@Pyrce Спасибо, отредактировал.   -  person wflynny    schedule 21.03.2013


Ответы (2)


Удаление столбца со всеми нулями не должно искажать данные. Если у вас есть N-мерные данные, но одно измерение - это одно и то же число, это в точности то же самое, что и N-1-мерные данные. Это свойство эффективной размерности называется рейтингом.

Рассмотрим трехмерные данные, но все ваши точки данных находятся на плоскости x = 0. Вы видите, как это в точности то же самое, что и 2D-данные?

person Erotemic    schedule 21.03.2013
comment
Не могли бы вы считать то, что я уже сделал, правильным решением? - person wflynny; 21.03.2013
comment
Я не уверен, но вам может потребоваться изменить if на: if all (np.abs (arr [:, i] .std ()) ‹1e-8): continue - person Erotemic; 22.03.2013
comment
arr[:,i].std() возвращает одно значение с плавающей запятой, поэтому я не думаю, что все это необходимо. - person wflynny; 22.03.2013

Во-первых, вполне нормально отбрасывать постоянные столбцы. Очевидно, что они не предоставляют информацию, поэтому нет причин их хранить.

Однако К-средние не особенно хороши для разреженных векторов. Проблема в том, что, скорее всего, результирующие «центроиды» будут больше похожи друг на друга, чем на элементы кластера. Видите ли, в разреженных данных каждый объект в некоторой степени является выбросом. К-средние довольно чувствительны к выбросам, потому что они пытаются минимизировать сумму квадратов.

Предлагаю вам сделать следующее:

  1. Найдите меру сходства, которая работает для вашего домена. Потратьте довольно много времени на то, как зафиксировать сходство для вашего конкретного варианта использования.

  2. Когда у вас есть это сходство, вычислите матрицу сходства 200x200. Поскольку ваш набор данных действительно крошечный, вы действительно можете использовать дорогостоящие методы кластеризации, такие как иерархическая кластеризация, которые не будут масштабироваться до тысяч объектов. Если хотите, вы также можете попробовать кластеризацию OPTICS или DBSCAN. Но, в частности, DBSCAN на самом деле более интересен, если ваш набор данных намного больше. Для крошечных наборов данных подойдет иерархическая кластеризация.

person Has QUIT--Anony-Mousse    schedule 22.03.2013