之前一直用R,现在开始学python之后就来尝试用Python来实现Kmeans。 之前用R来实现kmeans的博客:笔记︱多种常见聚类模型以及分群质量评估(聚类注意事项、使用技巧)
聚类分析在客户细分中极为重要。有三类比较常见的聚类模型,K-mean聚类、层次(系统)聚类、最大期望EM算法。在聚类模型建立过程中,一个比较关键的问题是如何评价聚类结果如何,会用一些指标来评价。 .
scikit-learn 是一个基于Python的Machine Learning模块,里面给出了很多Machine Learning相关的算法实现,其中就包括K-Means算法。
官网scikit-learn案例地址:http://scikit-learn.org/stable/modules/clustering.html#k-means 部分来自:scikit-learn 源码解读之Kmeans——简单算法复杂的说
各个聚类的性能对比:
优点: 原理简单 速度快 对大数据集有比较好的伸缩性 缺点: 需要指定聚类 数量K 对异常值敏感 对初始值敏感
参考:K-means算法及文本聚类实践
k-meams算法的能够保证收敛,但不能保证收敛于全局最优点,当初始中心点选取不好时,只能达到局部最优点,整个聚类的效果也会比较差。可以采用以下方法:k-means中心点
选择彼此距离尽可能远的那些点作为中心点; 先采用层次进行初步聚类输出k个簇,以簇的中心点的作为k-means的中心点的输入。 多次随机选择中心点训练k-means,选择效果最好的聚类结果
k-means的误差函数有一个很大缺陷,就是随着簇的个数增加,误差函数趋近于0,最极端的情况是每个记录各为一个单独的簇,此时数据记录的误差为0,但是这样聚类结果并不是我们想要的,可以引入结构风险对模型的复杂度进行惩罚:
λλ是平衡训练误差与簇的个数的参数,但是现在的问题又变成了如何选取λλ了,有研究[参考文献1]指出,在数据集满足高斯分布时,λ=2mλ=2m,其中m是向量的维度。
另一种方法是按递增的顺序尝试不同的k值,同时画出其对应的误差值,通过寻求拐点来找到一个较好的k值,详情见下面的文本聚类的例子。
参考博客:python之sklearn学习笔记 来看看主函数KMeans:
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' )
参数的意义:
虽然有很多参数,但是都已经给出了默认值。所以我们一般不需要去传入这些参数,参数的。可以根据实际需要来调用。
参考博客:python之sklearn学习笔记 本案例说明了,KMeans分析的一些类如何调取与什么意义。
import numpy as np from sklearn.cluster import KMeans data = np.random.rand(100, 3) #生成一个随机数据,样本大小为100, 特征数为3 #假如我要构造一个聚类数为3的聚类器 estimator = KMeans(n_clusters=3)#构造聚类器 estimator.fit(data)#聚类 label_pred = estimator.labels_ #获取聚类标签 centroids = estimator.cluster_centers_ #获取聚类中心 inertia = estimator.inertia_ # 获取聚类准则的总和
estimator初始化Kmeans聚类;estimator.fit聚类内容拟合; estimator.label_聚类标签,这是一种方式,还有一种是predict;estimator.cluster_centers_聚类中心均值向量矩阵 estimator.inertia_代表聚类中心均值向量的总和
案例来源于:使用scikit-learn进行KMeans文本聚类
from sklearn.cluster import KMeans num_clusters = 3 km_cluster = KMeans(n_clusters=num_clusters, max_iter=300, n_init=40, \ init='k-means++',n_jobs=-1) #返回各自文本的所被分配到的类索引 result = km_cluster.fit_predict(tfidf_matrix) print "Predicting result: ", result
km_cluster是KMeans初始化,其中用init的初始值选择算法用’k-means++’; km_cluster.fit_predict相当于两个动作的合并:km_cluster.fit(data)+km_cluster.predict(data),可以一次性得到聚类预测之后的标签,免去了中间过程。
其中:
km_cluster.labels_ km_cluster.predict(data)
这是两种聚类结果标签输出的方式,结果貌似都一样。都需要先km_cluster.fit(data),然后再调用。
Kmeans算法之后的一些分析,参考来源:用Python实现文档聚类
from sklearn.cluster import KMeans num_clusters = 5 km = KMeans(n_clusters=num_clusters) %time km.fit(tfidf_matrix) clusters = km.labels_.tolist()
分为五类,同时用%time来测定运行时间,把分类标签labels格式变为list。
from sklearn.externals import joblib # 注释语句用来存储你的模型 joblib.dump(km, 'doc_cluster.pkl') km = joblib.load('doc_cluster.pkl') clusters = km.labels_.tolist()
frame = pd.DataFrame(films, index = [clusters] , columns = ['rank', 'title', 'cluster', 'genre']) frame['cluster'].value_counts()
选择更靠近质心的点,其中 km.cluster_centers_代表着一个 (聚类个数*维度数),也就是不同聚类、不同维度的均值。 该指标可以知道: 一个类别之中的,那些点更靠近质心; 整个类别组内平方和。
类别内的组内平方和要参考以下公式:
通过公式可以看出: 质心均值向量每一行数值-每一行均值(相当于均值的均值) 注意是平方。其中,n代表样本量,k是聚类数量(譬如聚类5) 其中,整篇的组内平方和可以通过来获得总量:
km.inertia_
.
部分内容参考来源:scikit-learn学习之K-means聚类算法与 Mini Batch K-Means算法 当数据量很大的时候,Kmeans 显然还是很弱的,会比较耗费内存速度也会收到很大影响。scikit-learn 提供了MiniBatchKMeans算法,大致思想就是对数据进行抽样,每次不使用所有的数据来计算,这就会导致准确率的损失。
MiniBatchKmeans 继承自Kmeans 因为MiniBathcKmeans 本质上还利用了Kmeans 的思想.从构造方法和文档大致能看到这些参数的含义,了解了这些参数会对使用的时候有很大的帮助。batch_size 是每次选取的用于计算的数据的样本量,默认为100.
Mini Batch K-Means算法是K-Means算法的变种,采用小批量的数据子集减小计算时间,同时仍试图优化目标函数,这里所谓的小批量是指每次训练算法时所随机抽取的数据子集,采用这些随机产生的子集进行训练算法,大大减小了计算时间,与其他算法相比,减少了k-均值的收敛时间,小批量k-均值产生的结果,一般只略差于标准算法。
该算法的迭代步骤有两步: 1:从数据集中随机抽取一些数据形成小批量,把他们分配给最近的质心 2:更新质心 与K均值算法相比,数据的更新是在每一个小的样本集上。对于每一个小批量,通过计算平均值得到更新质心,并把小批量里的数据分配给该质心,随着迭代次数的增加,这些质心的变化是逐渐减小的,直到质心稳定或者达到指定的迭代次数,停止计算 Mini Batch K-Means比K-Means有更快的 收敛速度,但同时也降低了聚类的效果,但是在实际项目中却表现得不明显 一张k-means和mini batch k-means的实际效果对比图
来看一下 MiniBatchKMeans的python实现: 官网链接、案例一则链接
MiniBatchKMeans(n_clusters=8, init=’k-means++’, max_iter=100, batch_size=100, verbose=0, compute_labels=True, random_state=None, tol=0.0, max_no_improvement=10, init_size=None, n_init=3, reassignment_ratio=0.01)
相关参数解释(来自博客:用scikit-learn学习K-Means聚类):
import time import numpy as np import matplotlib.pyplot as plt from sklearn.cluster import MiniBatchKMeans, KMeans from sklearn.metrics.pairwise import pairwise_distances_argmin from sklearn.datasets.samples_generator import make_blobs # 获取数据 np.random.seed(0) batch_size = 45 centers = [[1, 1], [-1, -1], [1, -1]] n_clusters = len(centers) X, labels_true = make_blobs(n_samples=3000, centers=centers, cluster_std=0.7) # kmeans # Compute clustering with Means k_means = KMeans(init='k-means++', n_clusters=3, n_init=10) t0 = time.time() k_means.fit(X) t_batch = time.time() - t0 # MiniBatchKMeans mbk = MiniBatchKMeans(init='k-means++', n_clusters=3, batch_size=batch_size, n_init=10, max_no_improvement=10, verbose=0) t0 = time.time() mbk.fit(X) t_mini_batch = time.time() - t0
内容跟kmeans很像,只是一般多加一个参数,batch_size。
.
参考博客:python之sklearn学习笔记
import numpy as np from sklearn import cluster data = np.random.rand(100, 3) #生成一个随机数据,样本大小为100, 特征数为3 k = 3 # 假如我要聚类为3个clusters [centroid, label, inertia] = cluster.k_means(data, k)
.
data_zs = 1.0*(data - data.mean())/data.std() #数据标准化
.
来源于博客:使用python-sklearn-机器学习框架针对140W个点进行kmeans基于密度聚类划分
from sklearn.cluster import KMeans from sklearn.externals import joblib import numpy import time import matplotlib.pyplot as plt if __name__ == '__main__': ## step 1: 加载数据 print "step 1: load data..." dataSet = [] fileIn = open('./data.txt') for line in fileIn.readlines(): lineArr = line.strip().split(' ') dataSet.append([float(lineArr[0]), float(lineArr[1])]) #设定不同k值以运算 for k in range(2,10): clf = KMeans(n_clusters=k) #设定k !!!!!!!!!!这里就是调用KMeans算法 s = clf.fit(dataSet) #加载数据集合 numSamples = len(dataSet) centroids = clf.labels_ print centroids,type(centroids) #显示中心点 print clf.inertia_ #显示聚类效果 mark = ['or', 'ob', 'og', 'ok', '^r', '+r', 'sr', 'dr', '延伸三:模型保存
from sklearn.externals import joblib joblib.dump(km_cluster, "/..../train_model.m") km_cluster = joblib.load(".../train_model.m") kmeans_SSE.labels_