Python机器学习——K-Means聚类
2017-09-14 23:03
99 查看
样本集D={x⃗ 1,x⃗ 2,...,x⃗ N},假设聚类的簇划分C={C1,C2,...,CK}。k均值算法的目标是最小化平方误差:err=∑k=1K∑x⃗ i∈Ck||x⃗ i−μk→||22 其中,μ⃗ k=1Ck∑x⃗ i∈Ckx⃗ i是簇Ck的均值向量。上式刻画了簇类样本围绕簇均值向量的紧密程度,err越小,则簇内样本簇均值向量越紧密。
现在要求最优化问题:minC∑k=1K∑x⃗ i∈Ck||x⃗ i−μk→||22 该问题的求解需要考察样本集合D的所有可能的簇划分。k均值算法采用贪心算法,通过迭代优化来近似求解。其原理为:k均值算法首先假设一组向量作为所有簇的簇均值限量,然后根据假设的簇均值向量给出了数据集D的一个簇划分,再根据这个簇划分来计算真实的簇均值向量。
如果真实的簇均值向量等于假设的簇均值向量,则说明假设正确。根据假设簇均值向量给出的数据集D的一个簇划分确实是元问题的解。
如果真实的簇均值向量等不于假设的簇均值向量,则可以将真实的簇均值向量作为新的假设簇均值向量,继续求解。
这里的一个关键就是:给定假设簇均值向量,如何计算出数据集D的一个簇划分?k均值算法的策略是:样本距离哪个簇的簇均值向量最近,则该样本就划归到那个簇。
下面给出k均值算法:
输入:
样本集D={x⃗ 1,x⃗ 2,...,x⃗ N}
聚类簇数K
输出:簇划分C={C1,C2,...,CK}
算法步骤:
从数据集D中随机选取K个样本作为初始均值向量{μ⃗ 1,μ⃗ 2,...,μ⃗ K}
重复迭代直到算法收敛,迭代内容如下:
初始化阶段:取Ck=∅,k=1,2,...,K
划分阶段:令i=1,2,...,N
计算x⃗ i的簇标记如下:λi=argmink||x⃗ i−μ⃗ k||2,k∈1,2,...,K
然后将样本x⃗ i划入相应的簇:Cλi=Cλi⋃(x⃗ i)
重计算阶段:计算μ⃗ ′′kμ⃗ ”k=1|Ck|∑x⃗ i∈Ckx⃗ i
终止条件判断:
如果对所有的k∈1,2,…,K,都有μ⃗ ∗k=μ⃗ k,则算法收敛,终止迭代
否则重赋值μ⃗ k=μ⃗ ∗k
Python实战
KMeans是scikit-learn提供的聚类算法模型,其原型为:
参数
n_clusters:一个整数,指定分类簇的数量
init:一个字符串,指定初始均值向量的策略。可以为如下:
K-Means++:该初始化策略选择的初始均值向量相互之间距离都较远,它的效果较好
random:从数据集中随机选取K个样本作为初始均值向量
或者提供一个数组,数组的形状为(n_clusters.n_features),该数组作为初始均值向量
n_init:一个整数,指定了k均值算法运行的次数。每一次都会选择一组不同的初始化均值向量,最终算法会选择最佳的分类簇作为最终的结果。
max_iter:一个整数,指定了单轮k均值算法中,最大的迭代次数。算法总的最大迭代次数为max_iter * n_init。
precompute_distance:可以为布尔值或字符串’auto’。该参数指定是否提前计算好样本之间的距离(如果提前计算距离,则需要更多的内存,但是算法会运行的更快)。
auto:如果n_samples * n_clusters > 12 million,则不提前计算
True:总是提前计算
False :总是不提前计算
tol:一个浮点数,指定了算法收敛的阈值
n_jobs:一个正数,指定任务并行时的CPU数量。如果为-1则使用所有可用的CPU
verbose:一个整数,如果为0,则不输出日志信息;如果为1,则每隔一段时间打印一次日志信息;如果大于1,则打印日志信息更频繁
random_state:一个整数或一个RandomState实例,,或者为None
如果为整数,则它指定了随机数生成器的种子
如果为RandomState实例,则它指定了随机数生成器
如果为None,则使用默认的随机数生成器
copy_x:布尔值,主要用于precompute_distance=True的情况
如果为True,则预计算距离的时候,并不修改原始数据
如果为False,则预计算距离的时候,会修改原数数据用于节省内存,但后当算法结束的时候,会将原数据返回。但是可能会因为浮点数的表示,会有一些精度误差
属性
cluster_centers_:给出分类簇的均值向量
labels_:给出了每个样本所属的簇的标记
inertia_:给出了每个样本距离它最近的簇中心的距离之和
方法
fit(X[,y]):训练模型
fitpredict(X[,y]):训练模型并预测每个样本所属的簇,它等价于先调用fit方法,后调用predict方法
predict:预测样本所属的簇
score(X[,y]):给出了样本距离一个簇中心的偏移量的相反数。
现在要求最优化问题:minC∑k=1K∑x⃗ i∈Ck||x⃗ i−μk→||22 该问题的求解需要考察样本集合D的所有可能的簇划分。k均值算法采用贪心算法,通过迭代优化来近似求解。其原理为:k均值算法首先假设一组向量作为所有簇的簇均值限量,然后根据假设的簇均值向量给出了数据集D的一个簇划分,再根据这个簇划分来计算真实的簇均值向量。
如果真实的簇均值向量等于假设的簇均值向量,则说明假设正确。根据假设簇均值向量给出的数据集D的一个簇划分确实是元问题的解。
如果真实的簇均值向量等不于假设的簇均值向量,则可以将真实的簇均值向量作为新的假设簇均值向量,继续求解。
这里的一个关键就是:给定假设簇均值向量,如何计算出数据集D的一个簇划分?k均值算法的策略是:样本距离哪个簇的簇均值向量最近,则该样本就划归到那个簇。
下面给出k均值算法:
输入:
样本集D={x⃗ 1,x⃗ 2,...,x⃗ N}
聚类簇数K
输出:簇划分C={C1,C2,...,CK}
算法步骤:
从数据集D中随机选取K个样本作为初始均值向量{μ⃗ 1,μ⃗ 2,...,μ⃗ K}
重复迭代直到算法收敛,迭代内容如下:
初始化阶段:取Ck=∅,k=1,2,...,K
划分阶段:令i=1,2,...,N
计算x⃗ i的簇标记如下:λi=argmink||x⃗ i−μ⃗ k||2,k∈1,2,...,K
然后将样本x⃗ i划入相应的簇:Cλi=Cλi⋃(x⃗ i)
重计算阶段:计算μ⃗ ′′kμ⃗ ”k=1|Ck|∑x⃗ i∈Ckx⃗ i
终止条件判断:
如果对所有的k∈1,2,…,K,都有μ⃗ ∗k=μ⃗ k,则算法收敛,终止迭代
否则重赋值μ⃗ k=μ⃗ ∗k
Python实战
KMeans是scikit-learn提供的聚类算法模型,其原型为:
class sklearn.cluster.KMeans(n_clusters=8, init=’k-means++’, n_init=10, max_iter=300, tol=0.0001, precompute_distances=’auto’, verbose=0, random_state=None, copy_x=True,n_jobs=1,algorithm=’auto’)
参数
n_clusters:一个整数,指定分类簇的数量
init:一个字符串,指定初始均值向量的策略。可以为如下:
K-Means++:该初始化策略选择的初始均值向量相互之间距离都较远,它的效果较好
random:从数据集中随机选取K个样本作为初始均值向量
或者提供一个数组,数组的形状为(n_clusters.n_features),该数组作为初始均值向量
k均值算法总能够收敛,但是其收敛情况高度依赖于初始化的向量。有可能收敛于局部极小值。因此通常都是用多组初始向量来计算若干次,选择其中最优的一次。而k-means++策略选择的初始均值向量可以在一定程度上解决这个问题。
n_init:一个整数,指定了k均值算法运行的次数。每一次都会选择一组不同的初始化均值向量,最终算法会选择最佳的分类簇作为最终的结果。
max_iter:一个整数,指定了单轮k均值算法中,最大的迭代次数。算法总的最大迭代次数为max_iter * n_init。
precompute_distance:可以为布尔值或字符串’auto’。该参数指定是否提前计算好样本之间的距离(如果提前计算距离,则需要更多的内存,但是算法会运行的更快)。
auto:如果n_samples * n_clusters > 12 million,则不提前计算
True:总是提前计算
False :总是不提前计算
tol:一个浮点数,指定了算法收敛的阈值
n_jobs:一个正数,指定任务并行时的CPU数量。如果为-1则使用所有可用的CPU
verbose:一个整数,如果为0,则不输出日志信息;如果为1,则每隔一段时间打印一次日志信息;如果大于1,则打印日志信息更频繁
random_state:一个整数或一个RandomState实例,,或者为None
如果为整数,则它指定了随机数生成器的种子
如果为RandomState实例,则它指定了随机数生成器
如果为None,则使用默认的随机数生成器
copy_x:布尔值,主要用于precompute_distance=True的情况
如果为True,则预计算距离的时候,并不修改原始数据
如果为False,则预计算距离的时候,会修改原数数据用于节省内存,但后当算法结束的时候,会将原数据返回。但是可能会因为浮点数的表示,会有一些精度误差
属性
cluster_centers_:给出分类簇的均值向量
labels_:给出了每个样本所属的簇的标记
inertia_:给出了每个样本距离它最近的簇中心的距离之和
方法
fit(X[,y]):训练模型
fitpredict(X[,y]):训练模型并预测每个样本所属的簇,它等价于先调用fit方法,后调用predict方法
predict:预测样本所属的簇
score(X[,y]):给出了样本距离一个簇中心的偏移量的相反数。
#-*-coding:gbk-*- ''' Created on 2017年9月15日 @author: ''' from sklearn import cluster from sklearn.metrics import adjusted_rand_score import numpy as np import matplotlib.pyplot as plt from sklearn.datasets.samples_generator import make_blobs from matplotlib.pyplot import plot """ 产生数据 """ def create_data(centers,num=100,std=0.7): X,labels_true = make_blobs(n_samples=num,centers=centers, cluster_std=std) return X,labels_true """ 数据作图 """ def plot_data(*data): X,labels_true=data labels=np.unique(labels_true) fig=plt.figure() ax=fig.add_subplot(1,1,1) colors='rgbycm' for i,label in enumerate(labels): position=labels_true==label ax.scatter(X[position,0],X[position,1],label="cluster %d"%label), color=colors[i%len(colors)] ax.legend(loc="best",framealpha=0.5) ax.set_xlabel("X[0]") ax.set_ylabel("Y[1]") ax.set_title("data") # plt.show() """ 测试数据 """ def test_KMeans(*data): X,labels_true=data clst=cluster.KMeans() clst.fit(X) predicted_labels=clst.predict(X) print("ARI:%s"% adjusted_rand_score(labels_true, predicted_labels)) print("Sum center distance %s"%clst.inertia_) """ 考察簇的数量的影响 """ def test_KMeans_nclusters(*data): X,labels_true=data nums=range(1,50) ARIs=[] Distances=[] for num in nums: clst=cluster.KMeans(n_clusters=num) clst.fit(X) predicted_labels=clst.predict(X) ARIs.append(adjusted_rand_score(labels_true, predicted_labels)) Distances.append(clst.inertia_) fig=plt.figure() ax=fig.add_subplot(1,2,1) ax.plot(nums,ARIs,marker="+") ax.set_xlabel("n_clusters") ax.set_ylabel("ARI") ax=fig.add_subplot(1,2,2) ax.plot(nums,Distances,marker="o") ax.set_xlabel("n_clusters") ax.set_ylabel("inertia") fig.suptitle("KMeans") # plt.show() """ 考察运行次数和初始中心选择策略的影响 """ def test_KMeans_n_init(*data): X,labels_true=data nums=range(1,50) fig=plt.figure() ARIs_k=[] Distances_k=[] ARIs_r=[] Distances_r=[] for num in nums: clst=cluster.KMeans(n_init=num,init='k-means++') clst.fit(X) predicted_labels=clst.predict(X) ARIs_k.append(adjusted_rand_score(labels_true, predicted_labels)) Distances_k.append(clst.inertia_) clst=cluster.KMeans(n_init=num,init='random') clst.fit(X) predicted_labels=clst.predict(X) ARIs_r.append(adjusted_rand_score(labels_true, predicted_labels)) Distances_r.append(clst.inertia_) ax=fig.add_subplot(1,2,1) ax.plot(nums,ARIs_k,marker="+",label="k-means++") ax.plot(nums,ARIs_r,marker="+",label="random") ax.set_xlabel("n_init") ax.set_ylabel("ARI") ax.set_ylim(0,1) ax.legend(loc="best") ax=fig.add_subplot(1,2,2) ax.plot(nums,Distances_k,marker="o",label="k-means++") ax.plot(nums,Distances_r,marker="o",label="random") ax.set_xlabel("n_init") ax.set_ylabel("inertia") ax.legend(loc="best") fig.suptitle("KMeans") plt.show() centers=[[1,1],[2,2],[1,2],[10,20]] X,labels_true=create_data(centers, 1000, 0.5) test_KMeans(X,labels_true) plot_data(X,labels_true) test_KMeans_nclusters(X,labels_true) test_KMeans_n_init(X,labels_true)
可以看到,当n_clusters=4时,ARI指数最大,因为确实是从四个中心点产生的簇。而inertia_在n_clusters=1时最大,因为产生的测试数据有三个中心点较为接近,一个中心点较远。因此如果指定簇的数量为1,及所有的样本都属于一个簇,确实样本离簇中心的距离之和最大。
可以看到ARI指数和inertia_总距离随着n_init震荡,因此这两项指标与n_init影响不是很大,而且随机选择和使用'k-means++'策略选择初始中心向量,对于聚类效果的影响也不大。
相关文章推荐
- 用VLFeat库进行k-means聚类
- k-means聚类java实现
- 机器学习算法-K-means聚类
- K-means聚类
- 《Python机器学习及实践:从零开始通往Kaggle竞赛之路》
- 机器学习实战-10k-means聚类
- 《Python机器学习》读书笔记(十四)集成学习概述
- OpenCV k-means聚类
- 机器学习算法-K-means聚类
- K-Means聚类
- 一个很好的学习Python机器学习的网站
- OpenCV官方文档 理解k - means聚类
- 【ML算法】无监督学习——K-means聚类
- 分享《Python机器学习—预测分析核心算法》高清中文版PDF+高清英文版PDF+源代码
- K-means聚类
- 聚类算法实践(1)——层次、K-means聚类
- k-means聚类
- K-means聚类
- python k-means聚类
- Python机器学习之决策树算法实例详解