【K-Means】基于经纬度的城市聚类


1. 项目准备

1.1. 问题导入

KMeans聚类算法是一种非层次聚类算法,在最小误差的基础上将数据划分了特定的类,类间利用距离作为相似度指标,两个向量之间的距离越小,其相似度就越高。已知中国部分二级城市的经纬度,要求利用经纬度坐标进行KMeans聚类分析。

1.2. 数据集简介

本案例的数据集包含4列351行数据,每行数据包含一个城市,其中前两列为城市所在省和市,最后两列为城市的经纬度。

这是数据集的下载链接:中国主要城市经纬度数据集 - AI Studio


2. K-Means算法

2.1. 算法特点

K-Means聚类算法是一种基于向量距离作为相似性的评价指标,即认为两个对象的距离越近,其相似度就越大。该算法认为类簇是由距离靠近的对象组成的,因此它把得到紧凑且独立的类簇作为聚类的最终目标。
综上所述,K-Means算法划分的k个聚类具有以下特点:各聚类内部的元素尽可能的紧凑,而各聚类之间的元素尽可能的分开。

2.2. 算法流程

K-Means算法的基础是最小误差平方和准则,K-Means算法具体流程如下:
(1)从n个样本对象任意选择k个对象作为初始聚类中心;
(2)根据在步骤 (1) 中设置的k个聚类中心,计算每个对象与这k个中心的距离;
(3)经过步骤 (2) 的计算,所有对象与这个k个中心的距离就计算出来了,接着把所有对象与离它最近的中心归在一个类簇中;
(4)重新计算每个类簇的中心对象的位置;
(5)重复步骤 (3) 和 (4),直到类簇聚类方案中的对象归类几乎不发生变化为止。

2.3. 算法缺陷

(1)种子点的个数要事先确定,但是我们一般很难估计它的个数。
(2)K-Means算法需要初始种子点,并且随机种子会影响计算结果。
(3)需要不断地计算调整后的类簇中心,当数据量很大时,这个计算所需的时间就会很大。

2.4. 算法改进

K-Means++算法是改进后的K-Means算法,具体算法流程如下:
(1)从数据集的点中随机选择一个点作为种子点;
(2)计算数据集中的每一个点到种子点的距离D(x);
(3)选择D(x)较大的点作为新的种子点;
(4)重复步骤 (2) 和 (3)直到新的种子被选出来。


3. 实验步骤

3.1. 前期准备

  • 导入模块
import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score, silhouette_samples
  • 设置超参数
N_CLUSTERS = 7                                     # 类簇的数量
MARKERS = ['*', 'v', '+', '^', 's', 'x', 'o']      # 标记样式(绘图)
COLORS = ['r', 'g', 'm', 'c', 'y', 'b', 'orange']  # 标记颜色(绘图)
DATA_PATH = './data/China_cities.csv'              # 数据集路径

3.2. 读入数据

df = pd.read_csv(DATA_PATH)
print(df.head())    # 展示前5行数据

前5行数据的输出结果:

     省级行政区      城市       北纬        东经
0       北京        北京市   39.904690   116.40717
1       天津        天津市   39.085100   117.19937
2       上海        上海市   31.230370   121.47370
3       重庆        重庆市   29.564710   106.55073
4  香港特别行政区    九龙    22.327115   114.17495

3.3. 数据预处理

我们需要将各城市的经纬度数据单独提取出来。

x = df.drop('省级行政区', axis=1)
x = x.drop("城市", axis=1)
x_np = np.array(x)        # 将x转化为numpy数组

3.4. 模型构建与训练

本项目使用K-Means聚类算法来对城市的经纬度特征进行聚类。

model = KMeans(N_CLUSTERS)      # 构建聚类器
model.fit(x)                    # 训练聚类器
  • 计算轮廓系数
    轮廓系数(Silhouette Coefficient)是一种评价聚类效果的方法,其值介于 [ − 1 , 1 ] [-1, 1] [1,1]之间,值越趋近于 1 1 1代表同簇点的内聚度和异簇点的分离度都相对较优。
    假设我们用K-Means算法将数据划分成 K K K个类簇,对于某簇中任意一个向量 i i i而言,其轮廓系数 S i = B i − A i m a x ( A i , B i ) S_i = \frac{B_i-A_i}{max(A_i, B_i)} Si=max(Ai,Bi)BiAi。其中, A i A_i Ai i i i到同簇中其它所有点距离的平均值,它是 i i i与同簇内其他点不相似程度的平均值; B i B_i Bi i i i到其他簇内所有点平均距离的最小值,它是 i i i与其他簇的点平均不相似程度的最小值。
    将所有点的轮廓系数求平均,就能得到该聚类结果总的轮廓系数。
labels = model.labels_      # 获取聚类标签

# print(silhouette_samples(x, labels))  # 获取所有样本的轮廓系数
print(silhouette_score(x, labels))      # 获取聚类结果总的轮廓系数

模型的轮廓系数如下:

0.40034267246878397

3.5. 导出类簇信息

  • 导出类簇中心
print(model.cluster_centers_)	# 输出类簇中心

最终的类簇中心如下:

[[ 36.30742841 105.21526409]
 [ 27.85671809 102.12971362]
 [ 41.34384438  84.09634   ]
 [ 44.01411423 124.90852352]
 [ 24.3572954  111.87362376]
 [ 29.06106948 118.51486687]
 [ 36.22217001 115.34626425]]
  • 导出类簇元素
for i in range(N_CLUSTERS):
    print(f" CLUSTER-{i+1} ".center(60, '='))
    print(df[labels == i])

各类簇包含的元素如下:

======================== CLUSTER-1 =========================
    省级行政区   城市         北纬          东经
2      上海  上海市  31.230370  121.473700
10    台湾省  台中市  24.138620  120.679510
11    台湾省  台北市  25.037798  121.565170
..    ...  ...        ...         ...
======================== CLUSTER-2 =========================
     省级行政区           城市        北纬         东经
3       重庆          重庆市  29.56471  106.55073
221    四川省          成都市  30.57020  104.06476
222    四川省          自贡市  29.33920  104.77844
..    ...  ...        ...         ...
======================== CLUSTER-3 =========================
      省级行政区     城市        北纬         东经
0        北京    北京市  39.90469  116.40717
1        天津    天津市  39.08510  117.19937
17      河北省   石家庄市  38.04276  114.51430
..      ...    ...       ...        ...
======================== CLUSTER-4 =========================
        省级行政区           城市        北纬        东经
336     西藏自治区         阿里地区  30.40051  81.14540
337  新疆维吾尔自治区        乌鲁木齐市  43.82663  87.61688
338  新疆维吾尔自治区        克拉玛依市  45.57999  84.88927
..      ...    ...       ...        ...
======================== CLUSTER-5 =========================
       省级行政区    城市         北纬          东经
4    香港特别行政区    九龙  22.327115  114.174950
5    香港特别行政区    新界  22.341766  114.202408
6    香港特别行政区   香港岛  22.266416  114.177314
..       ...   ...        ...         ...
======================== CLUSTER-6 =========================
      省级行政区        城市         北纬          东经
73      辽宁省       沈阳市  41.677180  123.463100
74      辽宁省       大连市  38.913690  121.614760
75      辽宁省       鞍山市  41.107770  122.994600
..       ...   ...        ...         ...
======================== CLUSTER-7 =========================
       省级行政区          城市        北纬         东经
267      陕西省         西安市  34.34127  108.93984
268      陕西省         铜川市  34.89673  108.94515
269      陕西省         宝鸡市  34.36194  107.23732
..       ...   ...        ...         ...

3.6. 类簇可视化

plt.figure(figsize=(9, 6))
plt.title("Major Cities in China", fontsize=22)
plt.xlabel('East Longitude', fontsize=18)
plt.ylabel('North Latitude', fontsize=18)

for i in range(N_CLUSTERS):
    members = labels == i      # members是一个布尔型数组
    plt.scatter(
        x_np[members, 1],      # 城市经度数组
        x_np[members, 0],      # 城市纬度数组
        marker = MARKERS[i],   # 标记样式
        c = COLORS[i]          # 标记颜色
    )   # 绘制散点图

plt.grid()
plt.show()

基于经纬度的城市聚类结果:


写在最后

  • 如果您发现项目存在问题,或者如果您有更好的建议,欢迎在下方评论区中留言讨论~
  • 这是本项目的链接:实验项目 - AI Studio,点击fork可直接在AI Studio运行~
  • 这是我的个人主页:个人主页 - AI Studio,来AI Studio互粉吧,等你哦~
  • 【友链滴滴】欢迎大家随时访问我的个人博客~
  • 37
    点赞
  • 228
    收藏
    觉得还不错? 一键收藏
  • 25
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值