【火炉炼AI】机器学习024-无监督学习模型的性能评估--轮廓系数
(本文所使用的Python库和版本号: Python 3.6, Numpy 1.14, scikit-learn 0.19, matplotlib 2.2 )
前面我们学习过监督学习模型的性能评估,由于数据集有标记,所以我们可以将模型预测值和真实的标记做比较,计算两者之间的差异,从而来评估监督学习模型的好坏。
但是,对于无监督学习模型,由于没有标记数据,我们该怎么样评估一个模型的好坏了?显然,此时我们不能采用和监督学习模型一样的评估方式了,而要另辟蹊径。
1. 度量聚类模型的好坏---轮廓系数
有很多种度量聚类模型的算法,其中一个比较好用的算法就是轮廓系数(Silhouette Coefficient)指标。这个指标度量模型将数据集分类的离散程度,即判断数据集是否分离的合理,判断一个集群中的数据点是不是足够紧密(即内聚度),一个集群中的点和其他集群中的点相隔是否足够远(即分离度),故而轮廓系数结合了内聚度和分离度这两种因素,可以用来在相同原始数据的基础上用来评价不同算法,或者算法不同运行方式对聚类结果所产生的影响。
以下是百度对轮廓系数的说明,此处我直接搬过来用了。
2. 使用轮廓系数评估K-means模型
首先是用pandas加载数据集,查看数据集加载是否正确,这部分可以看我的具体代码,此处省略。
然后我随机的构建一个K-means模型,用这个模型来训练数据集,并用轮廓系数来评估该模型的优虐,代码如下:
from sklearn.cluster import KMeans
# 构建一个聚类模型,此处用K-means算法
model=KMeans(init='k-means++',n_clusters=3,n_init=10)
# 原始K-means算法最开始随机选取数据集中K个点作为聚类中心,
# 分类结果会因为初始点的选取不同而有所区别
# 而K-means++算法改变这种随机选取方法,能显著的改善分类结果的最终误差
# 此处我随机的指定n_cluster=3,看看评估结果
model.fit(dataset)
# 使用轮廓系数评估模型的优虐
from sklearn.metrics import silhouette_score
si_score=silhouette_score(dataset,model.labels_,
metric='euclidean',sample_size=len(dataset))
print('si_score: {:.4f}'.format(si_score))
-------------------------------------输---------出--------------------------------
si_score: 0.5572
--------------------------------------------完-------------------------------------
从上面的代码可以看出,计算轮廓系数是非常简单的。
########################小**********结###############################
1, sklearn中已经集成了轮廓系数的计算方法,我们只需要调用该函数即可,使用非常简单。
2, 有了模型的评估指标,我们就可以对模型进行一些优化,提升模型的性能,或者用该指标来比较两个不同模型在相同数据集上的效果,从而为我们选择模型提供指导。
#################################################################
3. K-means模型性能的提升方法
上面在评价K-means模型时,我们随机指定了划分的族群数量,即K值,但是有了评估指标之后,我们就可以优化这个K值,其基本思路是:遍历各种可能的K值,计算每种K值之下的轮廓系数,选择轮廓系数最大的K值,即为最优的族群数量。
下面我先定义一个函数,专门用来计算K-means算法的最优K值,这个函数具有一定的通用性,也可以用于其它场合。如下为代码:
# K-means模型的提升
# 在定义K-means时,往往我们很难知道最优的簇群数量,即K值,
# 故而可以通过遍历得到最优值
def get_optimal_K(dataset,K_list=None):
k_lists=K_list if K_list else range(2,15)
scores=[]
for k in k_lists:
kmeans=KMeans(init='k-means++',n_clusters=k,n_init=10)
kmeans.fit(dataset)
scores.append(silhouette_score(dataset,kmeans.labels_,
metric='euclidean',
sample_size=len(dataset)))
return k_lists[scores.index(max(scores))],scores
有了这个通用性求解最优K值的函数,我们就可以用来获取这个数据集的最佳K值,如下为代码:
optimal_K, scores=get_optimal_K(dataset)
print('optimal_K is: {}, all scores: {}'.format(optimal_K,scores))
# or:
# optimal_K, scores=get_optimal_K(dataset,[2,4,6,8,10,12])
# print('optimal_K is: {}, all scores: {}'.format(optimal_K,scores))
-------------------------------------输---------出--------------------------------
optimal_K is: 5, all scores: [0.5290397175472954, 0.5551898802099927, 0.5832757517829593, 0.6582796909760834, 0.5823584119482567, 0.5238070812131604, 0.4674788136779971, 0.38754867890367795, 0.41013511008667664, 0.41972398760085106, 0.41614459998617975, 0.3485105795903397, 0.357222732243728]
--------------------------------------------完-------------------------------------
从上面的结果可以看出,函数计算出来的最优K值为5,即最好的情况是将本数据集划分为5个类别,且在K=5时的轮廓系数为0.6583。
下面我们来看一下这个数据集在平面上的分布情况,看看是不是数据集有5种类别,如下所示是使用visual_2D_dataset()函数之后得到的平面分布图。
从上图中可以看出,的确数据集中到五个不同的簇群中。那么用最优的参数来聚类这些数据集,得到什么样的效果了?如下是平面的聚类效果图。
########################小**********结###############################
1, 使用轮廓系数可以对模型进行参数优化,此处我们定义了一个通用性函数,可以直接计算出数据集的最佳K值。
2, 当然,也可以用轮廓系数来优化其他参数,只要稍微修改一下上面的通用函数即可。
#################################################################
注:本部分代码已经全部上传到(我的github)上,欢迎下载。
参考资料:
1, Python机器学习经典实例,Prateek Joshi著,陶俊杰,陈小莉译