Hopkins Statistic判断irir数据集聚类性能
应用霍普金斯统计量(Hopkins Statistic) 可以判断数据在空间上的随机性,从而判断数据是否可以聚类。
1.算法原理:
首先,从所有样本中随机找n个点,然后为每一个点在样本空间中找到一个离他最近的点,并计算它们之间的距离xi,从而得到距离向量x1,x2,…,xn;
然后,从样本的可能取值范围内随机生成n个点,对每一个随机生产的点,找到一个离它最近的样本点,并计算它们之间的距离,得到y1,y2,…,yn。霍普金斯统计量H可以表示为:
如果样本接近随机分布,那么 和
的取值会比较接近,即H的值接近于0.5;如果聚类趋势明显,则随机生成的样本点距离应该远大于实际样本点的距离,即
,H的值接近于1.
因此使用Hopkins Statistic可以帮助我们评价该样本数据是否可以聚类,下面引入一个实例进行验证:
因此使用Hopkins Statistic可以帮助我们评价该样本数据是否可以聚类,下面引入一个实例进行验证:
2.IDLE:Jupyter Notebook
3.API:
4.霍普金斯统计数据的Python实现:
5.iris聚类可视化及霍普金斯统计量输出
在构建好霍普金斯统计量后选取数据进行验证,这里使用iris鸢尾花数据,众所周知,该数据集有150条数据,4个特征,3个目标值,我们首先使用PCA进行可视化显示:
通过可视化可以看到iris数据集分为三个目标值,该数据样本可以聚类,然后我们计算一下该数据集的霍普金斯统计量:
首先划分数据集:
下面输出iris数据集的霍普金斯统计量:
结果:
0.8706630933483493
0.8348276777799107
结果介于{0.7,…,0.99},因此有很高的聚集趋势。
6.随机矩阵霍普金斯统计量输出
同样,我们随机建立一个矩阵进行验证另一种情况:
结果如下:
0.5400050841597741
0.46500929146831366
该值接近于0.5,说明没有聚类趋势。
7.结论:
如果Hopkins Statistic在0.5左右,则是随机的
如果Hopkins Statistic介于{0.7,…,0.99},则有很高的聚集趋势。
附原码:
import numpy as np
from sklearn.neighbors import NearestNeighbors
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
from random import sample
from numpy.random import uniform
# 霍普金斯统计数据处理DataFrame的函数
def hopkins_statistic(X):
X=X.values #将dataframe转换为矩阵
sample_size = int(X.shape[0]*0.05) #0.05 (5%) based on paper by Lawson and Jures
#原始数据空间的均匀随机样本
X_uniform_random_sample = uniform(X.min(axis=0), X.max(axis=0) ,(sample_size , X.shape[1]))
#从原始数据中随机抽取一个样本
random_indices=sample(range(0, X.shape[0], 1), sample_size)
X_sample = X[random_indices]
#初始化无监督学习器以实现NN搜索
neigh = NearestNeighbors(n_neighbors=2)
nbrs=neigh.fit(X)
#u_distances = 均匀随机样本的最近邻距离
u_distances , u_indices = nbrs.kneighbors(X_uniform_random_sample , n_neighbors=2)
u_distances = u_distances[: , 0] #到第一个最近邻居的距离
#w_distances = 来自原始数据X的点样本的最近邻距离
w_distances , w_indices = nbrs.kneighbors(X_sample , n_neighbors=2)
#到第二个最近邻居的距离(因为第一个邻居将是点本身,距离= 0)
w_distances = w_distances[: , 1]
u_sum = np.sum(u_distances)
w_sum = np.sum(w_distances)
#计算并返回霍普金斯统计数据
H = u_sum/ (u_sum + w_sum)
return H
#读取鸢尾花数据
data=pd.read_csv('E://iris.data')
#data = data.drop(labels="Unnamed: 0",axis=1)
data.columns=['sepal length' , 'sepal width' , 'petal length', 'petal width', 'Class'] #命名列
X=data[['sepal length' , 'sepal width' , 'petal length', 'petal width']] #特征属性
y=data['Class'] #目标属性
# 输出iris数据集的霍普金斯统计量
H=hopkins_statistic(X)
print(H)
#跑100次求平均值
l = []
for i in range(100):
H=hopkins_statistic(X)
l.append(H)
print(np.mean(l))
#输出随机矩阵霍普金斯统计量
np.random.random_sample([100,4])
array = pd.DataFrame(array)
H=hopkins_statistic(array)
print(H)
l = []
for i in range(3):
H=hopkins_statistic(array)
l.append(H)
print(np.mean(l))