一、对两种不同的数据集进行K-means聚类并使用Calinski-Harabasz指数评价聚类模型
1.正态分布随机数据
首先生成正态分布数据并导入
import numpy
import pylab as pl
import matplotlib.pyplot as plt
plt.figure(1)
plt.figure(2)
x1 = numpy.round(numpy.random.normal(1,1,100),2)
y1 = numpy.round(numpy.random.normal(120,5,100),2)
x2 = numpy.round(numpy.random.normal(3,0.4,100),2)
y2 = numpy.round(numpy.random.normal(120,2,100),2)
#存入数据
a=[]
b=[]
for i in x1:
a.append(i)
for i in x2:
a.append(i)
for i in y1:
b.append(i)
for i in y2:
b.append(i)
#一维列表转二维
data = list(zip(a,b))
print('随机产生的正态分布的数据为:', data) #输出随机产生的正态分布的数据
然后K-means聚类并计算CH指数
from sklearn.metrics import calinski_harabaz_score
from sklearn.cluster import KMeans
for i in range(2,10):
#构建并训练模型
kmeans = KMeans(n_clusters = i,random_state=123).fit(data)
score = calinski_harabaz_score(data,kmeans.labels_)
print('数据聚%d类calinski_harabaz指数为:%f'%(i,score))
输出结果:
数据聚2类calinski_harabaz指数为:177.332261
数据聚3类calinski_harabaz指数为:266.221531
数据聚4类calinski_harabaz指数为:282.666507
数据聚5类calinski_harabaz指数为:270.155436
数据聚6类calinski_harabaz指数为:272.692595
数据聚7类calinski_harabaz指数为:300.101177
数据聚8类calinski_harabaz指数为:314.748953
数据聚9类calinski_harabaz指数为:332.111703
2.图片数据集
首先导入数据集
#导入本地图片集
import os
import cv2
array_of_img = [] #用于储存图像
#此函数用于读取图片,参数为本地路径名
def read_directory(directory_name):
#循环读取这个路径中的每个图像
for filename in os.listdir(directory_name):
#print(filename)
#img用于储存图像数据
img = cv2.imread(directory_name + "/" + filename)#根据文件夹名称与文件名进行图像的读取
array_of_img.append(img) #将图像数据存储到array_of_img中
#print(img)
#print(array_of_img)
#使用read_directory函数加载本地图片集,图片放在D盘下的flowerpictures文件夹
read_directory('D:/data/flowerpictures/')
其次进行降维,这里使用PCA降维,LLE降维方法见另一篇博客
#处理图片集样本
n_points = len(array_of_img)
X, color = datasets.samples_generator.make_s_curve(n_points, random_state=0)
n_neighbors = 5
#PCA降维
import numpy as np
from sklearn.decomposition import PCA
#pca = PCA(n_components=2)保留2个主成分
pca = PCA(0.9)#保留90%的信息
impca = pca.fit_transform(X)
最后进行K-means聚类并且计算CH指数
from sklearn.metrics import calinski_harabaz_score
from sklearn.cluster import KMeans
for i in range(2,10):
#构建并训练模型
kmeans = KMeans(n_clusters = i,random_state=123).fit(impca)
score = calinski_harabaz_score(impca,kmeans.labels_)
print('数据聚%d类calinski_harabaz指数为:%f'%(i,score))
输出结果:
数据聚2类calinski_harabaz指数为:154.883766
数据聚3类calinski_harabaz指数为:134.363731
数据聚4类calinski_harabaz指数为:186.040865
数据聚5类calinski_harabaz指数为:196.966283
数据聚6类calinski_harabaz指数为:241.618319
数据聚7类calinski_harabaz指数为:294.634954
数据聚8类calinski_harabaz指数为:362.175894
数据聚9类calinski_harabaz指数为:378.628481
二、计算CH指数的算法程序
Calinski-Harabaz是评价聚类模型好坏的参考,就像考试的分数。
对于聚类模型来说,我们希望聚类结果为相同类别之间的数据距离越近越好,而不同类别之间的数据距离越远越好;因此,对于K个聚类,Calinski-Harabaz的分数S被定义为组间离散与组内离散的比率,该分值越大说明聚类效果越好。
(算法来自Calinski-Harbasz Score 详解)
我查了一下资料,几乎所有计算CH指数的程序用的都是函数calinski_harabaz_score或函数calinski_harabasz_score,基本上没有人自己写算法了。
这里我把python的源码粘上来,作为学习算法的参考。我进行了微小的改动(修改函数名之类的),不影响计算结果,仅作为学习参考。
from sklearn.utils import check_X_y
from sklearn.preprocessing import LabelEncoder
import numpy as np
def calinski_harabaz(X, labels):
#计算CH指数
X, labels = check_X_y(X, labels)
#print(X.shape)
le = LabelEncoder()
labels = le.fit_transform(labels)
n_samples, _ = X.shape
n_labels = len(le.classes_)
extra_disp, intra_disp = 0., 0.
mean = np.mean(X, axis=0)
for k in range(n_labels):
cluster_k = X[labels == k]
mean_k = np.mean(cluster_k, axis=0)
extra_disp += len(cluster_k) * np.sum((mean_k - mean) ** 2)
intra_disp += np.sum((cluster_k - mean_k) ** 2)
return (1. if intra_disp == 0. else
extra_disp * (n_samples - n_labels) /
(intra_disp * (n_labels - 1.)))
感谢学习指导:
kMeans–正态分布数据分组
sklearn构建K-means聚类模型以及使用FMI,轮廓系数法,Calinski-Harabasz评价模型
层次聚类(hierarchical clustering)和聚类模型评估(calinski-harabaz index)