评估聚类效果
A:采用轮廓系数评估基于wordvec和dbscan的聚类结果
ChatGPT: 轮廓系数是一种常用的聚类评估方法,可以用来评估聚类结果的质量。其数学定义为: 轮廓系数(s) = (b-a)/max(a,b) 其中,a表示同簇内样本之间的平均距离,b表示样本与最近其他簇的平均距离。轮廓系数越接近1,表示聚类效果越好;越接近-1,表示聚类效果越差。 对于基于wordvec和dbscan的聚类结果,可以先用轮廓系数评估每个簇的质量,然后计算整个聚类结果的平均轮廓系数。具体步骤如下:
- 对于每个簇,计算其中所有样本之间的距离,并求出平均距离a。
- 对于每个样本,计算其与最近其他簇的平均距离,并求出平均距离b。
- 根据公式计算每个样本的轮廓系数,并将其加权平均得到整个聚类结果的平均轮廓系数。
- 根据平均轮廓系数的大小,评估聚类结果的质量。如果平均轮廓系数接近1,则说明聚类效果比较好;如果接近0,则说明聚类效果一般;如果接近-1,则说明聚类效果比较差。 需要注意的是,轮廓系数评估方法并不是绝对可靠的,因为它只能评估聚类结果的局部质量,而不能反映整个数据集的全局结构。因此,在使用轮廓系数评估聚类结果时,需要结合其他方法和领域知识来综合评估。
A: python示例代码
ChatGPT: 示例代码:
###### 评估聚类效果
from sklearn.metrics import silhouette_score
# 直接聚类
for eps in np.arange(0.1, 0.3, 0.02):
# 使用dbscan进行聚类
dbscan = DBSCAN(eps=eps, min_samples=10, metric='cosine')
dbscan.fit(tfidf_pca)
labels = dbscan.labels_
score = silhouette_score(tfidf_pca, labels)
print("eps:", eps,"轮廓系数为:", score)
实际测试eps很低的时候0.015左右,轮廓系数可以达到0.3,但是只能分出来一个类别,其他都是噪声。 eps调到0.15,轮廓系数0.09左右,可以分出来39个类别,所以对于中文文本分析,本来词向量比较稀疏,轮廓系数不能很好地作为评价标准。
A:采用可视化评估基于wordvec和dbscan的聚类结果,python示例
ChatGPT: 下面是一个基于wordvec和dbscan的聚类结果的Python可视化示例
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.manifold import TSNE
from sklearn.cluster import DBSCAN
from gensim.models import Word2Vec
#读入数据
df = pd.read_csv('data.csv')
# 训练word2vec模型
sentences = [s.split() for s in df['text']]
model = Word2Vec(sentences, min_count=1)
# 获取所有词向量
vocab = list(model.wv.vocab)
X = model[vocab]
#降维
tsne = TSNE(n_components=2, random_state=42)
X_tsne = tsne.fit_transform(X)
# 进行聚类
dbscan = DBSCAN(eps=0.5, min_samples=5)
dbscan.fit(X_tsne)
# 可视化
plt.scatter(X_tsne[dbscan.labels_ ==0,0], X_tsne[dbscan.labels_ ==0,1], c='blue', label='Cluster1')
plt.scatter(X_tsne[dbscan.labels_ ==1,0], X_tsne[dbscan.labels_ ==1,1], c='red', label='Cluster2')
plt.scatter(X_tsne[dbscan.labels_ == -1,0], X_tsne[dbscan.labels_ == -1,1], c='green', label='Noise')
plt.legend()
plt.show()
说明:
- data.csv是包含文本数据的CSV文件; -代码首先读入数据,并使用训练数据训练word2vec模型;
- TSNE将高维的词向量降到二维;
- 使用DBSCAN进行聚类,并将结果可视化。其中,标签为0和1的是聚类结果,标签为-1的是噪声点。
我把上面的代码改了下,引入了distinctipy来生成几十种颜色,绘制各个类别:
from distinctipy import distinctipy
# number of colours to generate
N = max(labels)
# generate N visually distinct colours
colors = distinctipy.get_colors(N)
# text = [distinctipy.get_text_color(color) for color in colors]
# 可视化
for i in range(0,N):
cname='cluster'+str(i)
plt.scatter(X_pca[labels ==i,0], X_pca[labels ==i,1], c=np.array(colors[i]).reshape(1,-1), label=cname)
# plt.scatter(X_pca[labels == -1,0], X_pca[labels == -1,1], c='green', label='Noise')
plt.legend()
plt.show()
一些bug
使用中会有个warning:
*c* argument looks like a single numeric RGB or RGBA sequence, which should be avoided as value-mapping will have
precedence in case its length matches with *x* & *y*. Please use the *color* keyword-argument or provide a 2-D
array with a single row if you intend to specify the same RGB or RGBA value for all points.
原因是我们上述代码中自定义的颜色是一个元组,不符合规定的二维数组,需将其转换二维数组,采用np.array(colors[i]).reshape(1,-1) 来解决。 将我们的自定颜色的元组转换成一维数组再进行增维:
- 转换成数组:np.array(color1)
- 使用reshape进行增维,使用reshape(1,-1)进行行上增维
- 备注:如果是列上增维度,可以使用reshape(-1,1) 列上维度增加一
最后输出效果: