У меня проблема с оценкой результата кластеров.
У меня 3 списка:
# 10 objects in my corpus
TOT = [1,2,3,4,5,6,7,8,9,10]
# .... clustering into k=5 clusters
# For each automatic cluster:
# Objects with ID 2 and 8 are stored into this
predicted = [2,8]
# For each cluster in the ground truth:
true = [2,4,9]
# computes TP, FP, TN, FN
A = set(docs_in_cluster)
B = set(constraints)
TP = list(A & B)
FP = list(A - (A & B))
TN = list((TOT - A) & (TOT - B))
FN = list(B - A)
Мой вопрос: могу ли я вычислить TP, FP, TN, FN для каждого кластер? Есть ли в этом смысл?
РЕДАКТИРОВАТЬ: воспроизводимый код
Краткая история:
Я занимаюсь НЛП, у меня есть корпус документов размером 9k, который Я обработал с помощью Gensim Word2Ve c, извлек векторы и вычислил «вектор документа» для каждого документа. После этого я вычислил косинусное сходство между векторами документа, получив матрицу 9k x 9k.
Наконец, используя эту матрицу, я выполнил KMeans и иерархическую кластеризацию.
Давайте рассмотрим результаты HA C с 14 кластерами:
id label
0 1
1 8
....
9k 12
Теперь проблема: как я могу оценить качество моих кластеров? Мой профессор прочитал 100 из этих 9k документов и создал несколько «кластеров», в которых говорится: «Хорошо, в этом документе говорится о: label1
» или «Хорошо, это другой разговор о label2
и label3
.
Обратите внимание, что ярлыки, предоставленные моим профессором, совершенно не связаны с процессом кластеризации и представляют собой просто сводку топовых c, но число то же самое (в этом примере = 14).
Код
У меня есть два фрейма данных, один выше из кластеризации HA C и один из 100 документов от моих профессоров, который выглядит так: (с примером, сделанным ранее)
GT
id label1 label2 label3 .... label14
5 1 0 0 0
34 0 1 1 0
...........................
И, наконец, мой код делает это:
# since I have labels only for 100 of my 9k documents
indexes = list(map(int, ground_truth['id'].values.tolist()))
reduced_df = clusters.loc[clusters['id'].isin(indexes), :]
# now reduced_df contains only the documents that have been read by my prof
TOT = set(reduced_df['id'].values.tolist())
for each cluster from HAC
doc_in_this_cluster = [ .... ]
for each cluster from GT
doc_in_this_label = [ ... ]
A = set(doc_in_this_cluster )
B = set(doc_in_this_label )
TP = list(A & B)
FP = list(A - (A & B))
TN = list((TOT - A) & (TOT - B))
FN = list(B - A)
И код:
indexes = list(map(int, self.ground_truth['id'].values.tolist()))
# reduce clusters_file matching only manually analyzed documents: --------> TOT
reduced_df = self.clusters.loc[self.clusters['id'].isin(indexes), :]
TOT = set(reduced_df['id'].values.tolist())
clusters_groups = reduced_df.groupby('label')
for label, df_group in clusters_groups:
docs_in_cluster = df_group['id'].values.tolist()
row = []
for col in self.ground_truth.columns[1:]:
constraints = list(
map(int, self.ground_truth.loc[self.ground_truth[col] == 1, 'id'].values.tolist())
)
A = set(docs_in_cluster)
B = set(constraints)
TP = list(A & B)
FP = list(A - (A & B))
TN = list((TOT - A) & (TOT - B))
FN = list(B - A)
print(f"HAC Cluster: {label} - GT Label: {col}")
print(TP, FP, TN, FN)