K-means原理与算法改进及其python实现
K-means入门学习
- 一、算法概述
- 二、算法思想
- 三、算法实现步骤
- 四、算法图解
- 五、算法优缺点
- 六、k-means算法python实现
- 6.1 sklearn聚类
- 6.2 各省份消费数据聚类
- 6.3 常规方法python实现
- 七、相关参数调整
- 八、优化算法K-means++
- 8.1 kmeans不足之处
- 8.2 kmeans++
- 8.3 层次聚类
一、算法概述
K-means聚类算法也称k均值聚类算法,是集简单和经典于一身的基于距离的聚类算法。它采用距离作为相似性的评价指标,即认为两个对象的距离越近,其相似度就越大。该算法认为类簇是由距离靠近的对象组成的,因此把得到紧凑且独立的簇作为最终目标。
K-Means算法主要解决的问题如下图所示。我们可以看到,在图的左边有一些点,我们可以看出来有三个点群,但是我们怎么才能将三个点群分为图右边的三个集群,这就是k-means算法能够解决的问题。
二、算法思想
K-means
聚类算法是一种迭代求解的聚类分析算法,其步骤是随机选取K个对象作为初始的聚类中心,然后计算每个对象与各个种子聚类中心之间的距离,把每个对象分配给距离它最近的聚类中心。聚类中心以及分配给它们的对象就代表一个聚类。每分配一个样本,聚类的聚类中心会根据聚类中现有的对象被重新计算。这个过程将不断重复直到满足某个终止条件。终止条件可以是没有(或最小数目)对象被重新分配给不同的聚类,没有(或最小数目)聚类中心再发生变化,误差平方和局部最小。
三、算法实现步骤
- 指定需要划分的簇的个数K值(类的个数);
- 随机地选择K个数据对象作为初始的聚类中心(不一定要是我们的样本点,可以随机生成)
- 计算其余的各个数据对象到这K个初始聚类中心的距离,把数据对象划归到距离它最近的那个中心所处在的簇类中
- 调整新类并且重新计算出新类的中心(每个新集合质心)
- 循环步骤三和四,看中心是否收敛(不变),如果收敛或达到迭代次数则停止循环
流程图如下:
四、算法图解
首先随机选择三个聚类中心;然后重复调整聚类中心位置;最终收敛,形成三个簇。
五、算法优缺点
优点:
- 对处理大数据集,该算法是相对高效率的。
- 原理比较简单,实现也是很容易,收敛速度快。
- 当结果簇是密集的,而簇与簇之间区别明显时, 它的效果较好。
- 主要需要调参的参数仅仅是簇数k。
缺点:
- 要求用户必须事先给出要生成的簇的数目K。
- K值需要预先给定,很多情况下K值的估计是非常困难的。
- K-Means算法对初始选取的质心点是敏感的,不同的随机种子点得到的聚类结果完全不同 ,对结果影响很大。
- 对噪音和异常点比较的敏感。用来检测异常值。
- 采用迭代方法,可能只能得到局部的最优解,而无法得到全局的最优解。
六、k-means算法python实现
6.1 sklearn聚类
make_blobs
函数是为聚类产生数据集,产生一个数据集和相应的标签
make_blobs方法:
sklearn.datasets.make_blobs(n_samples=100,n_features=2,centers=3, cluster_std=1.0,center_box=(-10.0,10.0),shuffle=True,random_state=None)
n_samples:表示数据样本点个数,默认值100
n_features:是每个样本的特征(或属性)数,也表示数据的维度,默认值是2
centers:表示类别数(标签的种类数),默认值3
cluster_std:表示每个类别的方差,例如我们希望生成2类数据,其中一类比另一类具有更大的方差,可以将cluster_std设置为[1.0,3.0],浮点数或者浮点数序列,默认值1.0
center_box:中心确定之后的数据边界,默认值(-10.0, 10.0)
shuffle:将数据进行洗乱,默认值是True
random_state:官网解释是随机生成器的种子,可以固定生成的数据,给定数之后,每次生成的数据集就是固定的。若不给定值,则由于随机性将导致每次运行程序所获得的的结果可能有所不同。在使用数据生成器练习机器学习算法练习或python练习时建议给定数值。- 生成数据
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt
#参数:
# n_samples=100 样本数量
# n_features=2 特征数量
# centers=3 中心点
#返回值:
# X_train: 测试集
# y_train: 特征值
X_train,y_train = make_blobs(n_samples=100, n_features=2, centers=3)
plt.scatter(X_train[:,0],X_train[:,1],c=y_train)
plt.show()
数据展示:
3. 建立模型训练
#参数
# n_clusters 将预测结果分为几簇
kmeans = KMeans(n_clusters=3) # 获取模型
kmeans.fit(X_train) #这里不需要给他答案 只把要分类的数据给他 即可
- 预测
predict_y = kmeans.predict(X_train)
plt.scatter(X_train[:,0],X_train[:,1],c=predict_y) #预测结果
plt.show()
预测结果:
6.2 各省份消费数据聚类
- 导入数据
from sklearn.cluster import KMeans
import pandas as pd
df = pd.read_excel('data.xlsx',sheet_name="人均消费(元)")
data = df.iloc[:,1:]
print(data)
数据显示:
食品 衣着 家庭设备 医疗 交通 娱乐 居住 杂项
0 2959.19 730.79 749.41 513.34 467.87 1141.82 478.42 457.64
1 2459.77 495.47 697.33 302.87 284.19 735.97 570.84 305.08
2 1495.63 515.90 362.37 285.32 272.95 540.58 364.91 188.63
3 1406.33 477.77 290.15 208.57 201.50 414.72 281.84 212.10
4 1303.97 524.29 254.83 192.17 249.81 463.09 287.87 192.96
5 1730.84 553.90 246.91 279.81 239.18 445.20 330.24 163.86
6 1561.86 492.42 200.49 218.36 220.69 459.62 360.48 147.76
7 1410.11 510.71 211.88 277.11 224.65 376.82 317.61 152.85
8 3712.31 550.74 893.37 346.93 527.00 1034.98 720.33 462.03
9 2207.58 449.37 572.40 211.92 302.09 585.23 429.77 252.54
10 2629.16 557.32 689.73 435.69 514.66 795.87 575.76 323.36
11 1844.78 430.29 271.28 126.33 250.56 513.18 314.00 151.39
12 2709.46 428.11 334.12 160.77 405.14 461.67 535.13 232.29
13 1563.78 303.65 233.81 107.90 209.70 393.99 509.39 160.12
14 1675.75 613.32 550.71 219.79 272.59 599.43 371.62 211.84
15 1427.65 431.79 288.55 208.14 217.00 337.76 421.31 165.32
16 1942.23 512.27 401.39 206.06 321.29 697.22 492.60 226.45
17 1783.43 511.88 282.84 201.01 237.60 617.74 523.52 182.52
18 3055.17 353.23 564.56 356.27 811.88 873.06 1082.82 420.81
19 2033.87 300.82 338.65 157.78 329.06 621.74 587.02 218.27
20 2057.86 186.44 202.72 171.79 329.65 477.17 312.93 279.19
21 2303.29 589.99 516.21 236.55 403.92 730.05 438.41 225.80
22 1974.28 507.76 344.79 203.21 240.24 575.10 430.36 223.46
23 1673.82 437.75 461.61 153.32 254.66 445.59 346.11 191.48
24 2194.25 537.01 369.07 249.54 290.84 561.91 407.70 330.95
25 2646.61 839.70 204.44 209.11 379.30 371.04 269.59 389.33
26 1472.95 390.89 447.95 259.51 230.61 490.90 469.10 191.34
27 1525.57 472.98 328.90 219.86 206.65 449.69 249.66 228.19
28 1654.69 437.77 258.78 303.00 244.93 479.53 288.56 236.51
29 1375.46 480.89 273.84 317.32 251.08 424.75 228.73 195.93
30 1608.82 536.05 432.46 235.82 250.28 541.30 344.85 214.40
- 建立模型并训练数据
k=3
model = KMeans(n_clusters= k,init='k-means++')
clf = model.fit(data)
predict_y = clf.predict(data)
- 聚类结果
print(df[predict_y==0]['省份'])
print(df[predict_y==1]['省份'])
print(df[predict_y==2]['省份'])
结果显示:
2 河北
3 山西
4 内蒙古
5 辽宁
6 吉林
7 黑龙江
11 安徽
13 江西
14 山东
15 河南
17 湖北
23 贵州
26 陕西
27 甘肃
28 青海
29 宁夏
30 新疆
Name: 省份, dtype: object
1 天津
9 江苏
10 浙江
12 福建
16 湖南
19 广西
20 海南
21 重庆
22 四川
24 云南
25 西藏
Name: 省份, dtype: object
0 北京
8 上海
18 广东
Name: 省份, dtype: object
6.3 常规方法python实现
各城市消费水平聚类
import random
import pandas as pd
import numpy as np#%%
# 计算欧拉距离
def calcDis(dataSet, centroids, k):clalist = []for data in dataSet:diff = np.tile(data, (k, 1)) - centroidssquaredDiff = diff ** 2 # 平方squaredDist = np.sum(squaredDiff, axis=1) # 和 (axis=1表示行)distance = squaredDist ** 0.5 # 开根号clalist.append(distance)clalist = np.array(clalist) # 返回一个每个点到质点的距离len(dateSet)*k的数组return clalist# 计算质心
def classify(dataSet, centroids, k):# 计算样本到质心的距离clalist = calcDis(dataSet, centroids, k)# 分组并计算新的质心minDistIndices = np.argmin(clalist, axis=1) # axis=1 表示求出每行的最小值的下标newCentroids = pd.DataFrame(dataSet).groupby(minDistIndices).mean() # DataFramte(dataSet)对DataSet分组,groupby(min)按照min进行统计分类,mean()对分类结果求均值newCentroids = newCentroids.values# 计算变化量changed = newCentroids - centroidsreturn changed, newCentroids# 使用k-means分类
def kmeans(dataSet, k):# 随机取质心# random.sample(list类型数据)centroids = random.sample(list(dataSet), k)# 更新质心 直到变化量全为0changed, newCentroids = classify(dataSet, centroids, k)while np.any(changed != 0):changed, newCentroids = classify(dataSet, newCentroids, k)centroids = sorted(newCentroids.tolist()) # tolist()将矩阵转换成列表 sorted()排序# 根据质心计算每个集群cluster = []clalist = calcDis(dataSet, centroids, k) # 调用欧拉距离minDistIndices = np.argmin(clalist, axis=1)for i in range(k):cluster.append([])for i, j in enumerate(minDistIndices): # enymerate()可同时遍历索引和遍历元素cluster[j].append(dataSet[i])return centroids, cluster, minDistIndices# 创建数据集
def createDataSet():df = pd.read_excel(r"data.xlsx", sheet_name="人均消费(元)")data = df.iloc[:, 1:]return df,np.array(data)if __name__ == '__main__':df,dataSet = createDataSet()centroids, cluster, minDist = kmeans(dataSet, 3)print('质心为:%s' % centroids)print('集群为:%s' % cluster)print(df[minDist == 0]['省份'])print(df[minDist == 1]['省份'])print(df[minDist == 2]['省份'])
聚类结果:
2 河北
3 山西
4 内蒙古
5 辽宁
6 吉林
7 黑龙江
11 安徽
13 江西
14 山东
15 河南
17 湖北
23 贵州
26 陕西
27 甘肃
28 青海
29 宁夏
30 新疆
Name: 省份, dtype: object
1 天津
9 江苏
12 福建
16 湖南
19 广西
20 海南
21 重庆
22 四川
24 云南
25 西藏
Name: 省份, dtype: object
0 北京
8 上海
10 浙江
18 广东
Name: 省份, dtype: object
七、相关参数调整
以下程序来源链接: K均值算法
- 标准差
cluster_std
不相同
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt
# cluster_std 各个中心的标准差
X_train,y_train = make_blobs(n_samples=500, n_features=2, centers=3, cluster_std=[1.0,2.0,3.0])
#参数
# n_clusters 将预测结果分为几簇
kmeans = KMeans(n_clusters=3) # 获取模型
kmeans.fit(X_train)
predict_y = kmeans.predict(X_train)
plt.scatter(X_train[:,0],X_train[:,1],c=y_train) # 原结果
plt.show()
plt.scatter(X_train[:,0],X_train[:,1],c=predict_y) #预测结果
plt.show()
原始数据:
聚类结果:
2. 样本数量不同
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt
import numpy as np
# cluster_std 各个中心的标准差
X_train,y_train = make_blobs(n_samples=1500, n_features=2, centers=3)
# 创建训练集
X1 = X_train[y_train==0] # X1中的这些点 目标值都是0
X2 = X_train[y_train==1][:100] # X2中的这些点 目标值都是1
X3 = X_train[y_train==2][:10] # X3中的这些点 目标值都是2# 将三个合为一个训练集
X_train = np.concatenate((X1,X2,X3))
# 创建结果集
# 前500个为0 再来100个1 再来10个2
y_train = [0]*500+[1]*100+[2]*10
plt.scatter(X_train[:,0],X_train[:,1],c=y_train) # 原结果
plt.show()
#参数
# n_clusters 将预测结果分为几簇
kmeans = KMeans(n_clusters=3) # 获取模型
kmeans.fit(X_train)
predict_y = kmeans.predict(X_train)plt.scatter(X_train[:,0],X_train[:,1],c=predict_y) #预测结果
plt.show()
原始数据:
聚类结果:
八、优化算法K-means++
8.1 kmeans不足之处
从KmeansKmeansKmeans聚类算法的原理可知,在正式聚类之前首先需要完成的就是初始化kkk个簇中心。使得收敛情况严重依赖于簇中心的初始化状况。如果在初始化过程中很不巧的将kkk个(或大多数)簇中心都初始化了到同一个簇中,那么在这种情况下聚类算法很大程度上都不会收敛到全局最小值。也就是说,当簇中心初始化的位置不得当时,聚类结果将会出现严重的错误。
8.2 kmeans++
k-means++算法选择初始聚类中心的基本原则是:初始的聚类中心之间的相互距离要尽可能的远
。
算法描述如下:
(只对K-means算法“初始化K个聚类中心” 这一步进行了优化)
- 随机选取一个样本作为第一个聚类中心;
- 计算每个样本与当前已有聚类中心的最短距离(即与最近一个聚类中心的距离),这个值越大,表示被选取作为聚类中心的概率较大;最后,用轮盘法(依据概率大小来进行抽选)选出下一个聚类中心;
- 重复步骤二,直到选出K个聚类中心。选出初始点后,就继续使用标准的K-means算法了。
程序实现:
def get_cent(points, k):'''kmeans++的初始化聚类中心的方法:param points: 样本:param k: 聚类中心的个数:return: 初始化后的聚类中心'''m, n = np.shape(points)cluster_centers = np.mat(np.zeros((k, n)))# 1、随机选择一个样本点作为第一个聚类中心index = np.random.randint(0, m)cluster_centers[0, ] = np.copy(points[index, ]) # 复制函数,修改cluster_centers,不会影响points# 2、初始化一个距离序列d = [0.0 for i in range(m)]for i in range(1, k):sum_all = 0for j in range(m):# 3、对每一个样本找到最近的聚类中心点d[j] = nearest(points[j, ], cluster_centers[0:i, ])# 4、将所有的最短距离相加sum_all += d[j]# 5、取得sum_all之间的随机值sum_all *= random()# 6、获得距离最远的样本点作为聚类中心点for j, di in enumerate(d): # enumerate()函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同事列出数据和数据下标一般用在for循环中sum_all -= diif sum_all > 0:continuecluster_centers[i] = np.copy(points[j, ])breakreturn cluster_centers
8.3 层次聚类
参考来源:数学建模清风老师课件
层次聚类的算法流程:
- 将每个对象看作一类,计算两两之间的最小距离;
- 将距离最小的两个类合并成一个新类;
- 重新计算新类与所有类之间的距离;
- 重复二三两步,直到所有类最后合并成一类;
算法图解
程序实现:
# 调包
import matplotlib.pyplot as plt
import pandas as pd
import scipy.cluster.hierarchy as shc # 层次聚类
# 防止中文乱码
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False
# 加载数据
df = pd.read_excel('data.xlsx',sheet_name="人均消费(元)")
print(df.head())
# 绘图
plt.figure(figsize=(16,10),dpi=100)
plt.title('省份消费数据聚类树状图',fontsize=22)
dend = shc.dendrogram(shc.linkage(df[['食品','衣着','家庭设备','医疗','交通','娱乐','居住','杂项']],
method='ward'),labels=df['省份'].values,color_threshold=100)
plt.xticks(fontsize=12)
plt.savefig('树状图.png') # 保存图片
plt.show()
聚类树状图:
本文为学习过程记录,根据学习情况继续更新。
K-means原理与算法改进及其python实现相关推荐
- kmeans改进 matlab,基于距离函数的改进k―means 算法
摘要:聚类算法在自然科学和和社会科学中都有很普遍的应用,而K-means算法是聚类算法中经典的划分方法之一.但如果数据集内相邻的簇之间离散度相差较大,或者是属性分布区间相差较大,则算法的聚类效果十分有 ...
- k均值聚类算法(K Means)及其实战案例
算法说明 K均值聚类算法其实就是根据距离来看属性,近朱者赤近墨者黑.其中K表示要聚类的数量,就是说样本要被划分成几个类别.而均值则是因为需要求得每个类别的中心点,比如一维样本的中心点一般就是求这些样本 ...
- 【Python】实现二维装箱Bottom-Left算法及用人工蜂群算法改进
目录 1 题目 2 装箱算法 2.1 所有装箱算法 2.2 Bottom-Left具体算法过程 3 Python 实现 3.1 main.py主函数 3.2 overlap函数 3.3 finalPo ...
- K均值(K-means)聚类算法原理与代码详解
0. 算法原理: 上述过程简单描述: a: 初始数据 b: 选择质点 c: 根据质点划分 d: 求均值,更新质心点 e: 划分 f: 更新质心点 1. 代码实现: # K means 教程# 0. 引 ...
- 第k大的数python代码_Python实现查找数组中任意第k大的数字算法示例
本文实例讲述了Python实现查找数组中任意第k大的数字算法.分享给大家供大家参考,具体如下: 模仿partion方法,当high=low小于k的时候,在后半部分搜索,当high=low大于k的时候, ...
- 聚类算法中 K均值聚类(KMeans)的python实现
** 聚类算法中 K均值聚类(KMeans)的python实现 ** import numpy as np import matplotlib.pyplot as plt from sklearn.d ...
- KNN算法原理及简单改进
KNN算法 1. 什么是KNN算法 简单来说,就是根据周围几个邻居的类别来判断自己的类别 1.1 KNN概念 KNN算法全称K Nearest Neighbor 定义:如果一个样本在特征空间中的k个最 ...
- opencvkcf算法改进_KCF跟踪算法原理 入门详解
一.算法介绍 KCF全称为Kernel Correlation Filter 核相关滤波算法.是在2014年由Joao F. Henriques, Rui Caseiro, Pedro Martins ...
- Udacity机器人软件工程师课程笔记(二十一) - 对点云进行集群可视化 - 聚类的分割 - K-means|K均值聚类, DBSCAN算法
聚类的分割 1.K-均值聚类 (1)K-均值聚类介绍 k均值聚类算法(k-means clustering algorithm)是一种迭代求解的聚类分析算法,其步骤是随机选取K个对象作为初始的聚类中心 ...
最新文章
- java语言环境变量_JAVA语言环境变量的设置教程
- Acronis移动方案(四)
- javaweb 之javascript 结合
- Tickets HDU - 1260
- uva 11490 ——Just Another Problem
- python去年软件排行_2017年编程语言排行榜,Python位居榜首(C语言需求最大)
- (最短路)Shopping
- anaconda卸载tensorflow时,收集不到包的解决方法
- WPF学习笔记——在“System.Windows.StaticResourceExtension”上提供值时引发了异常
- MATLAB局部放大
- 4600u黑苹果 r5_黑苹果集显hd4400、hd4600显卡Clover引导驱动方法教程
- 龙芯芯片CPU的产品路线说明
- java 密码 星号显示_Java多线程 例子 cmd窗口下 实现输入密码星号显示
- 关于曼哈顿距离的最小生成树 POJ3241
- 计算机名词解释(计算机科学导论)
- 计算机上用户名怎么设置,电脑用户名,详细教您电脑用户名怎么修改
- 携手互联网企业10巨头设VC基金
- 用boot camp助理装win 7时卡在了“正在拷贝windows文件”
- 自学前端第十天 : CSS怪异盒子模型
- opencv学习日志15-统计焊点个数并输出
热门文章
- java第七封印游戏_第七封印的游戏任务
- 上次吹的牛实现后,李彦宏又在百度世界大会立了三个flag!
- 财务Financial Affairs
- 数据查询必备技能SQL调优:Mysql什么情况下不走索引
- 火焰焰心matlab,[转载]酒精灯火焰的温度真的是外焰最高吗?
- MdEditor-v3中上传照片的前后端对接(图片上传至又拍云云储存)
- 80后相亲面面观 男生找富婆不怕倒插门。80后的特点!你占几样?
- Go语言基础入门(处理JSON)
- 北师大计算机和北邮哪个好考,同在首都的,北京师范大学和北京邮电大学,哪所实力更强?...
- 这个项目把100多个知名网站都克隆出来了!