赞
踩
总结仅为个人学习使用。
学习资料有‘从零开始学python’,‘跟着迪哥学python数据分析与机器学习’
簇内平方和拐点法,在不同k值计算簇内离差平方和,然后通过可视化找到“拐点”所对应的k值。随着簇数量增加,簇中样本量会越来越少,导致目标函数值月腊月小。重点关注斜率的变化,当斜率突然由大变小时,且之后斜率变化缓慢,则认为突然变化的点就是寻找的目标点。
# 构造自定义函数,用于绘制不同k值和对应总的簇内离差平方和的折线图
def k_SSE(X, clusters):
# 选择连续的K种不同的值
K = range(1,clusters+1)
# 构建空列表用于存储总的簇内离差平方和
TSSE = []
for k in K:
# 用于存储各个簇内离差平方和
SSE = []
kmeans = KMeans(n_clusters=k)
kmeans.fit(X)
# 返回簇标签
labels = kmeans.labels_
# 返回簇中心
centers = kmeans.cluster_centers_
# 计算各簇样本的离差平方和,并保存到列表中
for label in set(labels):
SSE.append(np.sum((X.loc[labels == label,]-centers[label,:])**2))
# 计算总的簇内离差平方和
TSSE.append(np.sum(SSE))
# 中文和负号的正常显示
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
# 设置绘图风格
plt.style.use('ggplot')
# 绘制K的个数与GSSE的关系
plt.plot(K, TSSE, 'b*-')
plt.xlabel('簇的个数')
plt.ylabel('簇内离差平方和之和')
# 显示图形
plt.show()
# 将三组数据集汇总到数据框中
X = pd.DataFrame(np.concatenate([np.array([x1,y1]),np.array([x2,y2]),np.array([x3,y3])], axis = 1).T)
# 自定义函数的调用
k_SSE(X, 15)
综合考虑簇的密集性与分散性两个信息,如果数据集被分割为理想的K个簇,那么对应的簇内样本会很密集,而簇间样本会很分散。
轮廓系数最大,且最接近1时的k值是最为合适的聚类数
# 构造自定义函数,用于绘制不同k值和对应轮廓系数的折线图
def k_silhouette(X, clusters):
K = range(2,clusters+1)
# 构建空列表,用于存储个中簇数下的轮廓系数
S = []
for k in K:
kmeans = KMeans(n_clusters=k)
kmeans.fit(X)
labels = kmeans.labels_
# 调用字模块metrics中的silhouette_score函数,计算轮廓系数
S.append(metrics.silhouette_score(X, labels, metric='euclidean'))
# 中文和负号的正常显示
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
# 设置绘图风格
plt.style.use('ggplot')
# 绘制K的个数与轮廓系数的关系
plt.plot(K, S, 'b*-')
plt.xlabel('簇的个数')
plt.ylabel('轮廓系数')
# 显示图形
plt.show()
# 自定义函数的调用
k_silhouette(X, 15)
首次出现正值对应的k值数目
# 自定义函数,计算簇内任意两样本之间的欧氏距离
def short_pair_wise_D(each_cluster):
mu = each_cluster.mean(axis = 0)
Dk = sum(sum((each_cluster - mu)**2)) * 2.0 * each_cluster.shape[0]
return Dk
# 计算簇内的Wk值
def compute_Wk(data, classfication_result):
Wk = 0
label_set = set(classfication_result)
for label in label_set:
each_cluster = data[classfication_result == label, :]
Wk = Wk + short_pair_wise_D(each_cluster)/(2.0*each_cluster.shape[0])
return Wk
# 计算GAP统计量
def gap_statistic(X, B=10, K=range(1,11), N_init = 10):
# 将输入数据集转换为数组
X = np.array(X)
# 生成B组参照数据
shape = X.shape
tops = X.max(axis=0)
bots = X.min(axis=0)
dists = np.matrix(np.diag(tops-bots))
rands = np.random.random_sample(size=(B,shape[0],shape[1]))
for i in range(B):
rands[i,:,:] = rands[i,:,:]*dists+bots
# 自定义0元素的数组,用于存储gaps、Wks和Wkbs
gaps = np.zeros(len(K))
Wks = np.zeros(len(K))
Wkbs = np.zeros((len(K),B))
# 循环不同的k值,
for idxk, k in enumerate(K):
k_means = KMeans(n_clusters=k)
k_means.fit(X)
classfication_result = k_means.labels_
# 将所有簇内的Wk存储起来
Wks[idxk] = compute_Wk(X,classfication_result)
# 通过循环,计算每一个参照数据集下的各簇Wk值
for i in range(B):
Xb = rands[i,:,:]
k_means.fit(Xb)
classfication_result_b = k_means.labels_
Wkbs[idxk,i] = compute_Wk(Xb,classfication_result_b)
# 计算gaps、sd_ks、sk和gapDiff
gaps = (np.log(Wkbs)).mean(axis = 1) - np.log(Wks)
sd_ks = np.std(np.log(Wkbs), axis=1)
sk = sd_ks*np.sqrt(1+1.0/B)
# 用于判别最佳k的标准,当gapDiff首次为正时,对应的k即为目标值
gapDiff = gaps[:-1] - gaps[1:] + sk[1:]
# 中文和负号的正常显示
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
# 设置绘图风格
plt.style.use('ggplot')
# 绘制gapDiff的条形图
plt.bar(np.arange(len(gapDiff))+1, gapDiff, color = 'steelblue')
plt.xlabel('簇的个数')
plt.ylabel('k的选择标准')
plt.show()
# 自定义函数的调用
gap_statistic(X)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。