python_sklearn机器学习算法系列之K-Means(硬聚类算法)

          本文主要目的是通过一段及其简单的小程序来快速学习python 中sklearn的K-Means这一函数的基本操作和使用,注意不是用python纯粹从头到尾自己构建K-Means,既然sklearn提供了现成的我们直接拿来用就可以了,当然K-Means原理还是十分重要,这里简单说一下实现这一算法的过程:

1)从N个文档随机选取K个文档作为质心

2)对剩余的每个文档测量其到每个质心的距离,并把它归到最近的质心的类

3)重新计算已经得到的各个类的质心

4)迭代2~3步直至新的质心与原质心相等或小于指定阈值,算法结束

详细可以参考https://baike.so.com/doc/6953641-7176056.html

在介绍代码之前先来看两个概念:平均畸变程度和轮廓系数

通过平均畸变程度可以确定一个范围内(人为给定)的最佳类簇的数量即K值,通过轮廓系数(Silhouette Coefficient)评价聚类算法的性能

每个类的畸变程度简单来说其实等于该类重心与其内部成员位置距离的平方和,显而易见该值越小说明该类中的样本越紧凑的聚集在一起,

平均畸变程度越小说明整体来说分类的效果越好了对吧,所以这个概念还是比较好理解的,也可以从下面的代码中清楚的看到这一概念的具体含义。

关于轮廓系数有点复杂,它由两个因数通过决定:簇内不相似度和簇间不相似度

簇内不相似度定义为样本n到同簇其他样本的平均距离,记为dist1_n

样本n到其他某簇C(i) 的所有样本的平均距离dis_n-C(i)则簇间不相似度定义为dist2_n=min{dis_n-C(1), dis_n-C(2), ...,dis_n-C(k)}

轮廓系数s为(图片旋转一下看):

s接近1,则说明样本n聚类合理;

s接近-1,则说明样本n更应该分类到另外的簇;

若s 近似为0,则说明样本n在两个簇的边界上。

本程序源数据用的是一部分城市的经纬度即city.txt

上海上海,121.48,31.22  
上海嘉定,121.24,31.4  
上海宝山,121.48,31.41  
上海川沙,121.7,31.19  
上海南汇,121.76,31.05  
上海奉贤,121.46,30.92  
上海松江,121.24,31  
云南昆明,102.73,25.04  
云南富民,102.48,25.21  
云南晋宁,102.58,24.68  
云南呈贡,102.79,24.9  
云南安宁,102.44,24.95  
云南昭通,103.7,29.32  
云南永善,103.63,28.22  
云南大姚,101.34,25.73  
云南永仁,101.7,26.07  
云南禄劝,102.45,25.58  
云南牟定,101.58,25.32  
云南双柏,101.67,24.68  
云南姚安,101.24,25.4  
云南下关,100.24,25.45  
云南剑川,99.88,26.53  
云南洱源,99.94,26.1  
云南宾川,100.55,25.82  
云南弥渡,100.52,25.34  
云南永平,99.52,25.45  
云南鹤庆,100.18,26.55  
云南大理,100.19,25.69  
云南漾濞,99.98,25.68  
北京北京,116.46,39.92  
北京平谷,117.1,40.13  
北京密云,116.85,40.37  
北京顺义,116.65,40.13  
北京通县,116.67,39.92  
北京怀柔,116.62,40.32  
北京大兴,116.33,39.73  
北京房山,115.98,39.72    
吉林长春,125.35,43.88  
吉林吉林,126.57,43.87  
吉林农安,125.15,44.45  
吉林德惠,125.68,44.52  
吉林榆树,126.55,44.83  
吉林九台,126.83,44.15  
吉林双阳,125.68,43.53  
吉林永吉,126.57,43.87  
吉林舒兰,126.97,44.4  
吉林蛟河,127.33,43.75  
吉林桦甸,126.72,42.97  
吉林磐石,126.03,42.93  
吉林延吉,129.52,42.93  
吉林汪清,129.75,43.32  
吉林珲春,130.35,42.85  
吉林大安,124.18,45.5  
吉林扶余,124.82,45.2  
吉林乾安,124.02,45  
吉林长岭,123.97,44.3  
吉林通榆,123.13,44.82  
吉林洮安,122.75,45.35   
四川成都,104.06,30.67  
四川金堂,104.32,30.88  
四川双流,104.94,30.57  
四川蒲江,103.29,30.2  
四川郫县,103.86,30.8  
四川新都,104.13,30.82  
四川来易,102.15,26.9  
四川盐边,101.56,26.9  
天津天津,117.2,39.13  
天津宁河,117.83,39.33  
天津静海,116.92,38.93  
天津蓟县,117.4,40.05  
天津宝坻,117.3,39.75  
天津武清,117.05,39.4  
宁夏回族自治区银川,106.27,38.47  
宁夏回族自治区永宁,106.24,38.28  
宁夏回族自治区贺兰,106.35,38.55  
宁夏回族自治区石嘴山,106.39,39.04  
宁夏回族自治区平罗,106.54,38.91  
宁夏回族自治区陶乐,106.69,38.82  
宁夏回族自治区吴忠,106.21,37.99  
宁夏回族自治区同心,105.94,36.97  
宁夏回族自治区灵武,106.34,38.1
安徽郎溪,119.17,31.14  
安徽广德,119.41,30.89  
安徽泾县,118.41,30.68  
安徽南陵,118.32,30.91  
安徽繁昌,118.21,31.07  
安徽宁国,118.95,30.62  
安徽青阳,117.84,30.64  
安徽屯溪,118.31,29.72  
安徽休宁,118.19,29.81  
安徽旌得,118.53,30.28  
安徽绩溪,118.57,30.07  
安徽歙县,118.44,29.88  

好了前期工作介绍完毕,终于可以看程序了

其中,模块一是平均畸变程度和轮廓系数; 模块二是预测效果

我在这里将两模块都注释掉了,读者可以分别运行

代码:

#K-Means   
import numpy as np  
import matplotlib.pyplot as plt  
from sklearn.cluster import KMeans
from sklearn.externals import joblib     #模块二
import pandas as pd
import matplotlib as mpl
from scipy.spatial.distance import cdist #模块一
from sklearn import metrics              #模块一

#从磁盘读取城市经纬度数据  
X = []  
f = open('city.txt')  
for v in f:
    X.append([float(v.split(',')[1]),float(v.split(',')[2])])
f.close()

#转换成numpy array,形如:[[1.2 , 3.2],[2.3 , 6.3 ],[1.0 , 2.3]],转化前X是一个列表
X = np.array(X)

mpl.rcParams['font.sans-serif'] = [u'SimHei']            #绘图时用来正常显示中文标签    
mpl.rcParams['axes.unicode_minus'] = False               #绘图时用来正常显示负号


'''
#模块一:
#通过平均畸变程度来确定类簇的数量,通过轮廓系数(Silhouette Coefficient)评价聚类算法(具体来自https://blog.csdn.net/wangxiaopeng0329/article/details/53542606)
#d=cdist(X,Y,'euclidean')#假设X有M个元素,Y有N个元素,最终会生成M行N列的array,用来计算X、Y中每个相对元素之间的欧拉距离
#numpy.min(d,axis=1) #如果d为m行n列,axis=0时会输出每一列的最小值,axis=1会输出每一行最小值
n_clusters = range(2,5) #假设分别在2,3,4中选取一个最合适的n_clusters
meandistortions=[]
metrics_silhouette=[]
for k in n_clusters:
    clf=KMeans(n_clusters=k)
    cls = clf.fit(X)
    meandistortions.append(sum(np.min(cdist(X,clf.cluster_centers_,'euclidean'),axis=1))/X.shape[0])#平均畸变程度值,越小越好
    metrics_silhouette.append(metrics.silhouette_score(X,clf.labels_,metric='euclidean'))           #轮廓系数,越接近1越好   
#平均畸变程度图   
plt.subplot(121)
plt.plot(n_clusters,meandistortions,'rx-')
plt.xlabel('k')
plt.ylabel('平均畸变程度')
plt.title('K-Means平均畸变程度图(越小越好) ')
#轮廓系数图
plt.subplot(122)
plt.plot(n_clusters,metrics_silhouette,'bx-')
plt.ylabel('轮廓系数')
plt.xlabel('k')
plt.title('K-Means轮廓系数(越接近1越好)')
#显示
plt.show()

'''



'''   

#模块二:
#核心代码:现在把数据和对应的分类放入聚类函数中进行聚类
#其中n_clusters 需要聚成几类,init代表初始点怎么找,max_iter代表迭代次数, n_jobs用的cpu,precompute_distances预先需不需要计算距离
n_clusters=4
clf=KMeans(n_clusters=n_clusters)
cls = clf.fit(X)

#聚类结果的显示,其中用clf和cls均可
print(cls.labels_)                         #显示每个样本所属的簇
print(clf.cluster_centers_)                #4个中心点的坐标
print(clf.inertia_)                        #用来评估簇的个数是否合适,代表所有点到各自中心的距离和,距离越小说明簇分的越好,选取临界点的簇个数
r1 = pd.Series(cls.labels_).value_counts()
print(r1)                                  #统计每个类别下样本个数

#用聚类的学习结果去预测
X1=[[121.35,26.41],[123.5,45.35]]
print(clf.predict(X1))

#保存模型,加载模型(加载后是类别标签)
joblib.dump(clf,'d:/test/km.txt')
clf = joblib.load('d:/test/km.txt')

#画图
markers = ['x','o','*','+']
colors=['b','r','y','g']
for i in range(n_clusters):
     members = cls.labels_ == i
     plt.scatter(X[members,0],X[members,1],s=60,marker=markers[i],c=colors[i],alpha=0.5)
plt.xlabel('经度')
plt.ylabel('纬度')
plt.title('K-Means聚合结果(n_clusters=4)')  
plt.show()

'''

模块一结果:

模块二结果:

更多算法可以参看博主其他文章,或者github:https://github.com/Mryangkaitong/python-Machine-learning

看到很多小伙伴私信,为了不迷路,欢迎关注笔者微信公众号:


​​​​​​​

 

  • 1
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: K-Means 聚类算法是一种常用的无监督学习算法,它可以将数据集划分为 K 个不同的类别,其中 K 是预先设定的。在 K-Means 算法中,我们需要指定 K 值和距离计算方法,然后通过迭代的方式不断调整聚类中心,直到达到某个停止准则为止。 下面我们以鸢尾花数据集为例,来实现 K-Means 聚类算法。 首先,我们需要导入数据集并进行预处理。这里我们使用 sklearn 中的 load_iris 函数来加载数据集,并使用 MinMaxScaler 对数据进行归一化处理: ``` python from sklearn.datasets import load_iris from sklearn.preprocessing import MinMaxScaler # 加载数据集 iris = load_iris() X = iris.data # 数据归一化 scaler = MinMaxScaler() X = scaler.fit_transform(X) ``` 接下来,我们需要实现 K-Means 算法。这里我们使用 scikit-learn 中的 KMeans 类来实现: ``` python from sklearn.cluster import KMeans # 设置 K 值 k = 3 # 初始化 KMeans 模型 kmeans = KMeans(n_clusters=k) # 训练模型并预测结果 y_pred = kmeans.fit_predict(X) ``` 最后,我们可以使用 Matplotlib 来可视化聚类结果: ``` python import matplotlib.pyplot as plt # 绘制聚类结果 plt.scatter(X[:, 0], X[:, 1], c=y_pred) plt.title("K-Means Clustering") plt.show() ``` 运行以上代码,即可得到鸢尾花数据的聚类结果。 ### 回答2: K-Means聚类算法是一种常用的无监督学习方法,能够对数据进行聚类。在K-Means算法中,通过计算数据点与聚类中心的距离,将数据点归类到距离最近的聚类中心,从而实现数据的聚类。 鸢尾花数据是机器学习中常用的数据集之一,包含了150个样本,每个样本有4个特征,分别是花萼长度、花萼宽度、花瓣长度和花瓣宽度。这些样本被分为三个类别,分别是山鸢尾、变色鸢尾和维吉尼亚鸢尾。 使用K-Means聚类算法对鸢尾花数据进行聚类的过程如下: 1. 随机选择K个初始聚类中心。K代表要将数据聚成的类别数,这里我们选择K=3,即将鸢尾花数据聚成3个类别。 2. 对每个数据点,计算其与各个聚类中心的距离,并将其归类到距离最近的聚类中心。 3. 更新每个聚类中心的位置,将其移动到所归类数据点的平均位置。 4. 重复步骤2和3,直到聚类中心不再发生变化或达到预定的迭代次数。 通过上述步骤,可以将鸢尾花数据聚类成3个类别。每个类别中的数据点具有相似的特征,并且与其他类别中的数据点的特征有较大的区别。 K-Means聚类算法的优点是简单易实现,计算效率高。然而,这种算法对初始聚类中心的选择较为敏感,可能会收敛到局部最优解。因此,在应用K-Means算法时,需要进行多次实验,以避免得到不理想的聚类结果。同时,K-Means算法对于离群点比较敏感,离群点可能会影响聚类结果的准确性。 ### 回答3: K-Means 聚类算法是一种常用的无监督学习算法,主要用于将数据集中的样本划分成不同的簇。下面以实现鸢尾花数据的聚类为例进行解释。 首先,我们需要加载鸢尾花数据集,该数据集包含了150个样本,每个样本有4个特征,分别是花萼长度、花萼宽度、花瓣长度和花瓣宽度。我们将这些样本表示为一个150x4的矩阵。 然后,我们需要确定簇的数量 k,即要将数据集划分成几个簇。在这里,我们可以根据经验或者领域知识来选择一个合适的值。 接下来,我们需要初始化 k 个簇的中心点。可以随机从数据集中选取 k 个样本作为初始的簇中心点。 然后,对于每个样本,我们计算其与各个簇中心点的距离,并将其分配给距离最近的簇中心点所在的簇。 接着,我们更新每个簇的中心点,即将每个簇中的样本的特征均值作为新的簇中心点。 最后,我们重复执行以上两个步骤,直到簇中心点不再发生变化,或者到达预定的迭代次数。 完成聚类后,我们可以根据簇的中心点和每个样本所属的簇来进行结果的分析和可视化。例如,可以绘制不同簇中心点的特征值分布图,以及将样本点按簇的标签进行颜色分类的散点图等。 K-Means 聚类算法能够有效地将数据集划分为不同的簇,实现了对样本的聚类。在鸢尾花数据集这个例子中,我们可以根据花萼和花瓣的特征值将鸢尾花分为不同的类别,从而更好地了解这些花的分类情况。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值