Python——KMeans(k均值聚类)实战

对我国某视频APP的小镇中国区潜在会员数分布用KMeans进行聚类,通过聚类结果知道会员的分布情况。先给大家看下最后的效果图:
在这里插入图片描述
在这里插入图片描述
一、读取中国地图

import numpy as np
import cv2
import matplotlib.pyplot as plt
img_china = cv2.imread('../china.png')  #读取中国地图图片
plt.imshow(img_china,cmap="gray")   #对图像进行处理,并显示其格式
plt.xticks([]),plt.yticks([])      #去除x、y轴
plt.show()

在这里插入图片描述
二、特征提取过程
【注】用画图软件加入黑色散点(潜在会员数)(这个不需要大家做,已经用ps做好,保存在china_people.png),另存为china_people.png。

import numpy as np
import cv2
import matplotlib.pyplot as plt
img_china = cv2.imread('../china2thresh.png')    #读取上一步已经处理好的图片,这里无需看第一步的代码,第一步只是告诉如何处理图片,这里china2thresh.png就是第一步处理完成用于第二步的图片
img_china_people = cv2.imread('../china_people.png')  #读取用ps处理的会员分布散点图
img_people = img_china - img_china_people  #此处用到图像相减,两幅图像间对应像素的灰度值相减,用于目标检测
r_img_china = cv2.split(img_china)[0]     #图像颜色通道的分离,看不懂没关系,毕竟这不是重点
r_img_people = cv2.split(img_people)[2]
cv2.imwrite('../people.png',r_img_people)  #把处理后的img_people,存入people.png
print("中国大陆面积(像素数):",np.unique(r_img_china,return_counts = True)[1][1])   #获取中国地图像素大小
print("小镇中国区潜在会员数(像素数):",np.unique(r_img_people,return_counts = True)[1][1])  #获取小镇中国区潜在会员数像素大小
psw = []           #把三张图片img_china、img_china_people、img_people放入数组句柄中,当然我们最后需要的是img_people
psw.append(("china",img_china))
psw.append(("china + people",img_china_people))
psw.append(("people",img_people))
plot_number = len(psw)
cols = 3
rows = plot_number/cols + 1
for index in range(plot_number):
    plt.subplot(rows,cols,index + 1)
    plt.imshow(psw[index][1],cmap = "gray")
    plt.title(psw[index][0],fontsize =15 )
    plt.xticks([]),plt.yticks([])
plt.show()        #用for循环按要求打印出如下效果

注】subplot(n,m,x)解释:建立一个mn的绘图区域,然后分别在其x=1,2,3,4,…区域绘制图像*

在这里插入图片描述
三、从people图中提取样本作为KMeans的训练集

print(r_img_people.shape)     #打印出people图的像素范围
X = np.argwhere(r_img_people)
print(X.shape)     #小镇中国区潜在会员数分布,样本数为78739,为二维数组
X[0:10]     #打印出前10个样本所在像素点位置

在这里插入图片描述
四、训练KMeans模型(重点)

from sklearn.cluster import KMeans    #从sklearn导入KMeans算法
import copy
k = 72                      #指定簇的数目,KMeans聚类需要预先指定要聚成多少类
y_KMeans = KMeans(n_clusters=k, random_state=9)    #KMeans函数调用、传参
y_pred = y_KMeans.fit_predict(X)                   #预测样本分别属于哪些类
print(y_pred)

src_img_china = copy.deepcopy(img_china)
r_src_img_china = cv2.split(src_img_china)[0]
#根据索引赋值
for i in range(len(X)):
    index = X[i]
    src_img_china[index[0]][index[1]] = [y_pred[i]*(255/k), (255/3 + y_pred[i]*(255/k))%255, 255*2/3+(y_pred[i]*(255/k))]

注】random_state的作用是控制随机状态,固定random_state为某个固定的值后,每次构建的模型都是相同的、生成的数据是相同的、每次拆分的结果也是相同的。可以把它理解为控制变量。
效果:
在这里插入图片描述
五、可视化结果

cv2.imwrite("../result.png",cv2.cvtColor(src_img_china , cv2.COLOR_RGB2BGR)) #颜色转换,了解即可
plt.imshow(src_img_china)
plt.xticks([]),plt.yticks([])
plt.show()
plt.scatter(X[:,1],X[:,0],c=y_pred)   #把预测的结果用散点图画出
plt.xticks([]),plt.yticks([])
ax = plt.gca()
ax.invert_yaxis()
plt.show()

在这里插入图片描述

六、输出结果

num_pix_china = np.unique(r_img_china, return_counts=True)[1][1]
print('中国大陆面积(像素数):', num_pix_china)
num_all_people = np.unique(r_img_people, return_counts=True)[1][1]
print('小镇中国区潜在会员数(像素数):', num_all_people)
print('每个簇的中心点坐标(像素坐标):', y_KMeans.cluster_centers_)
print('每个簇的潜在会员数(簇内像素数):',np.unique(y_pred, return_counts=True))

#每个簇内到簇中心距离列表:
# print(X.shape)
# print(y_pred.shape)
dic_result_xy = {}
dic_result = {}
for i in range(y_pred.shape[0]):
    if y_pred[i] not in dic_result:
        dic_result_xy[y_pred[i]]=[]
        dic_result[y_pred[i]]=[]
    dic_result_xy[y_pred[i]].append(X[i])
#     print('jjjjjjjjj',i,X[i][0]-y_KMeans.cluster_centers_[y_pred[i]][0])
#     print('kkkkkkkkk',i,X[i][1]-y_KMeans.cluster_centers_[y_pred[i]][1])
    dic_result[y_pred[i]].append( np.sqrt( np.square(X[i][0]-y_KMeans.cluster_centers_[y_pred[i]][0])\
                                                  + np.square(X[i][1]-y_KMeans.cluster_centers_[y_pred[i]][1])))
    if i%5000 == 0:
        print('计算到第{}个循环'.format(i))
# print(dic_result_xy[0][:10])
# print(dic_result[0])


#每个簇内到簇中心平均距离:
tmp = []
for i in range(k):
    tmp.append(np.mean(dic_result[i]))
print('每个簇簇内所有点到簇中心平均距离(像素距离):')
print(tmp)
   
tmp = []
for i in range(k):
    tmp.append(np.median(dic_result[i]))
print('每个簇簇内所有点到簇中心中位数距离(像素距离):')
print(tmp)

tmp = []
for i in range(k):
    tmp.append(max(dic_result[i]))
print('每个簇簇内所有点到簇中心最远距离(像素距离):')
print(tmp)
print(np.mean(tmp))

actual_china = 9083674#纯陆地9,083,674平方千米
pix2km = np.sqrt(actual_china/num_pix_china)
print('最终:', np.mean(tmp)*pix2km,'km')

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Kmeans聚类算法是一种无监督学习算法,用于将数据集划分为不同的簇。它是一个迭代算法,通过计算每个数据点与簇中心的距离,将数据点分配到最近的簇中心。然后,根据分配的数据点更新簇中心。重复这个过程,直到簇中心不再变化或达到预设的迭代次数。 下面是一个使用Python实现Kmeans聚类算法的示例: ``` python import numpy as np import matplotlib.pyplot as plt # 生成随机数据 np.random.seed(0) X = np.random.randn(100, 2) # 初始化K个簇中心 K = 3 centers = X[np.random.choice(len(X), K, replace=False)] # 迭代聚类 for i in range(10): # 计算每个数据点最近的簇中心 distances = np.linalg.norm(X[:, np.newaxis, :] - centers, axis=2) labels = np.argmin(distances, axis=1) # 更新簇中心 for k in range(K): centers[k] = np.mean(X[labels == k], axis=0) # 可视化聚类结果 colors = ['r', 'g', 'b'] for k in range(K): plt.scatter(X[labels == k, 0], X[labels == k, 1], c=colors[k]) plt.scatter(centers[:, 0], centers[:, 1], marker='*', s=200, c='#050505') plt.show() ``` 在这个例子中,我们生成了一个随机数据集,然后初始化了3个簇中心。然后,我们执行10次迭代,计算每个数据点最近的簇中心,并根据分配的数据点更新簇中心。最后,我们可视化聚类结果,其中每个簇用不同的颜色表示,簇中心用星号表示。 Kmeans聚类算法是一种简单有效的聚类算法,但它有一些缺点。例如,它需要预先指定簇的数量K,这可能不是很容易确定。此外,它对初始簇中心的选择很敏感,可能会导致陷入局部最优解。因此,在实际应用中,需要对它进行改进,例如Kmeans++算法和层次聚类算法等。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值