参考https://www.cnblogs.com/think90/p/7133753.html
- 组内平方误差和——拐点图(肘部法则SSE)
- 轮廓系数
1. 组内平方误差和——拐点图(肘部法则SSE)
随着聚类数目增多,每一个类别中数量越来越少,距离越来越近,因此WSS值肯定是随着聚类数目增多而减少的,所以关注的是斜率的变化,但WWS减少得很缓慢时,就认为进一步增大聚类数效果也并不能增强,存在得这个“肘点”就是最佳聚类数目,从一类到三类下降得很快,之后下降得很慢,所以最佳聚类个数选为3。
2. 轮廓系数
轮廓系数是类的密集与分散程度的评价指标。
a(i)是测量组内的样本i在到其它点的平均距离,b(i)是测量组间的样本i到最近不同类别中样本的平均距离,s(i)范围从-1到1,值越大说明组内吻合越高,组间距离越远——也就是说,轮廓系数值越大,聚类效果越好。
3. 实现
参考 https://www.cnblogs.com/feffery/p/12325741.html
我是直接拷贝https://github.com/arvkevi/kneed/blob/master/kneed/knee_locator.py 的实现,这就不用安装kneed模块了。
(输入参数)KneeLocator是kneed中用于检测拐点的模块,其主要参数如下:
x:待检测数据对应的横轴数据序列,如时间点、日期等
y:待检测数据序列,在x条件下对应的值,如x为星期一,对应的y为降水量
S:float型,默认为1,敏感度参数,越小对应拐点被检测出得越快
curve:str型,指明曲线之上区域是凸集还是凹集,concave代表凹,convex代表凸
direction:str型,指明曲线初始趋势是增还是减,increasing表示增,decreasing表示减
online:bool型,用于设置在线/离线识别模式,True表示在线,False表示离线;在线模式下会沿着x轴从右向左识别出每一个局部拐点,并在其中选择最优的拐点;离线模式下会返回从右向左检测到的第一个局部拐点
KneeLocator在传入参数实例化完成计算后,可返回的我们主要关注的属性如下:
knee及elbow:返回检测到的最优拐点对应的x
knee_y及elbow_y:返回检测到的最优拐点对应的y
all_elbows及all_knees:返回检测到的所有局部拐点对应的x
all_elbows_y及all_knees_y:返回检测到的所有局部拐点对应的y
import matplotlib.pyplot as plt
from matplotlib import style
import numpy as np
from kneed import KneeLocator
style.use('seaborn-whitegrid')
x = np.arange(1, 3, 0.01)*np.pi
y = np.cos(x)
# 计算各种参数组合下的拐点
kneedle_cov_inc = KneeLocator(x,
y,
curve='convex',
direction='increasing',
online=True)
kneedle_cov_dec = KneeLocator(x,
y,
curve='convex',
direction='decreasing',
online=True)
kneedle_con_inc = KneeLocator(x,
y,
curve='concave',
direction='increasing',
online=True)
kneedle_con_dec = KneeLocator(x,
y,
curve='concave',
direction='decreasing',
online=True)
fig, axe = plt.subplots(2, 2, figsize=[12, 12])
axe[0, 0].plot(x, y, 'k--')
axe[0, 0].annotate(s='Knee Point', xy=(kneedle_cov_inc.knee+0.2, kneedle_cov_inc.knee_y), fontsize=10)
axe[0, 0].scatter(x=kneedle_cov_inc.knee, y=kneedle_cov_inc.knee_y, c='b', s=200, marker='^', alpha=1)
axe[0, 0].set_title('convex+increasing')
axe[0, 0].fill_between(np.arange(1, 1.5, 0.01)*np.pi, np.cos(np.arange(1, 1.5, 0.01)*np.pi), 1, alpha=0.5, color='red')
axe[0, 0].set_ylim(-1, 1)
axe[0, 1].plot(x, y, 'k--')
axe[0, 1].annotate(s='Knee Point', xy=(kneedle_cov_dec.knee+0.2, kneedle_cov_dec.knee_y), fontsize=10)
axe[0, 1].scatter(x=kneedle_cov_dec.knee, y=kneedle_cov_dec.knee_y, c='b', s=200, marker='^', alpha=1)
axe[0, 1].fill_between(np.arange(2.5, 3, 0.01)*np.pi, np.cos(np.arange(2.5, 3, 0.01)*np.pi), 1, alpha=0.5, color='red')
axe[0, 1].set_title('convex+decreasing')
axe[0, 1].set_ylim(-1, 1)
axe[1, 0].plot(x, y, 'k--')
axe[1, 0].annotate(s='Knee Point', xy=(kneedle_con_inc.knee+0.2, kneedle_con_inc.knee_y), fontsize=10)
axe[1, 0].scatter(x=kneedle_con_inc.knee, y=kneedle_con_inc.knee_y, c='b', s=200, marker='^', alpha=1)
axe[1, 0].fill_between(np.arange(1.5, 2, 0.01)*np.pi, np.cos(np.arange(1.5, 2, 0.01)*np.pi), 1, alpha=0.5, color='red')
axe[1, 0].set_title('concave+increasing')
axe[1, 0].set_ylim(-1, 1)
axe[1, 1].plot(x, y, 'k--')
axe[1, 1].annotate(s='Knee Point', xy=(kneedle_con_dec.knee+0.2, kneedle_con_dec.knee_y), fontsize=10)
axe[1, 1].scatter(x=kneedle_con_dec.knee, y=kneedle_con_dec.knee_y, c='b', s=200, marker='^', alpha=1)
axe[1, 1].fill_between(np.arange(2, 2.5, 0.01)*np.pi, np.cos(np.arange(2, 2.5, 0.01)*np.pi), 1, alpha=0.5, color='red')
axe[1, 1].set_title('concave+decreasing')
axe[1, 1].set_ylim(-1, 1)
# 导出图像
plt.savefig('图2.png', dpi=300)