Необычный результат кластеризации HDBScan для матрицы косинусоподобия - PullRequest
0 голосов
/ 19 сентября 2019

Я пытаюсь кластеризовать похожие сообщения в файлах журнала машины (например, не могу игнорировать числа).Отладка моего кода с помощью подмножества сообщений, которые имеют одинаковую « степень сходства », я обнаружил очень странную находку: ниже определенного числа этих сообщений HDBScan выдает ожидаемый результат (который принадлежит всем сообщениям, принадлежащимдо одного или без кластера), но выше определенного количества сообщений HDBScan внезапно начинает находить разные кластеры, что для меня интуитивно не имеет смысла.

И еще более странно: предел, в котором я начинаю видеть несколько кластеров, составляет 18 сообщений для алгоритма ' generic ' в HDBScan, но 61 при использовании ' best '.Ну, может быть, 'best' выбирает ' generic ' над 60 сообщениями, не уверен, как это проверить ...

Я пробовал различные настройки для min_cluster_size и min_samples иразличные метрики расстояния, но проблема остается той же.Ниже приведен отдельный код, чтобы узнать, можете ли вы воспроизвести проблему.Просто измените n_msg на любой number >= 18 (или >=61 при использовании ' best '), и вы получите более одного идентификатора кластера.Код также печатает матрицу косинусного сходства, чтобы вы могли видеть, насколько симметричен этот пример.

from sklearn.feature_extraction.text import CountVectorizer
from sklearn.metrics.pairwise import cosine_similarity
import hdbscan
import pandas as pd

# set number of dummy messages to be created
n_msg = 17

# create dummy messages with three identical and one variable term
msgs = pd.DataFrame()
for i in range(0, n_msg):
    msg = ['bli bla blub ' + str(i)]
    msgs = msgs.append(msg)
msgs.columns = ['msg']

# tokenizer to split at space only so numbers will not be ignored
def space_tokenizer(msg):
   return msg.split()

# Vectorize dummy messages
TFvectorizer = CountVectorizer(tokenizer = space_tokenizer)
msgs_vect = TFvectorizer.fit_transform(msgs.msg)

# Compute cosine similarity between message vectors
msgs_CosSim = pd.DataFrame(cosine_similarity(msgs_vect, msgs_vect))
print(msgs_CosSim,'\n')

# Cluster the cosine similarity results
hdbs = hdbscan.HDBSCAN(min_cluster_size=2, min_samples=1, metric='euclidean', \
                       algorithm='generic').fit(msgs_CosSim)
CosSim_clstr_ID = pd.DataFrame(hdbs.labels_)
CosSim_clstr_ID.columns = ['msg_ID']
print(CosSim_clstr_ID,'\n')

# Check number of cluster IDs generated
print('Number of cluster IDs:', len(CosSim_clstr_ID.msg_ID.unique()))

Итак, опять же, с этими фиктивными сообщениями выше, я ожидаю того же результата (все сообщения принадлежат одному ID кластераили кластер выбросов -1), не зависящий от количества сообщений, но я начинаю получать различные кластеры выше определенного количества сообщений (в зависимости от выбора алгоритма в HDBScan).

Есть идеи, что происходит?

Обновление: провел еще несколько исследований по этому вопросу, используя только allow_single_cluster=True (!) И перебрал все значения algorithm, а также различные типы сообщений (от одного до четырех фиксированных терминов плюс числа), и вот результат, где'generic', будучи самым быстрым, похоже, скорее всего, даст странные результаты случайным образом: enter image description here

...