无监督学习的聚类算法及应用

K-means算法原理

K-means聚类算法以k为参数,把n个对象分为k个簇,使簇内具有较高的相似度,而簇间的相似度较低。

  1. 随机选择k个点作为初始的聚类中心。
  2. 对于剩下的点,根据其与聚类中心的距离,将其归入最近的簇。
  3. 对每个簇,计算所有点的均值作为新的聚类中心。
  4. 重复2、3直到聚类中心不再改变。

K-means算法应用

需求

通过聚类,了解1999年各个省份的消费水平在国内的情况。

使用算法

K-means聚类算法

实现过程

  1. 建立工程,导入sklearn相关包
  2. 加载数据,创建K-means算法实例,并进行训练,获得标签
  3. 输出标签,查看结果

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# -*- coding: utf-8 -*-
"""
Created on Thu Apr 18 22:59:44 2019

@author: Jiaxi Wang
"""

import numpy as np
from sklearn.cluster import KMeans


def loadData(filePath):
fr = open(filePath,'r+')
lines = fr.readlines()
retData = []
retCityName = []
for line in lines:
items = line.strip().split(",")
retCityName.append(items[0])
retData.append([float(items[i]) for i in range(1,len(items))])
return retData,retCityName


if __name__ == '__main__':
data,cityName = loadData('city.txt')
km = KMeans(n_clusters=4)
label = km.fit_predict(data)
expenses = np.sum(km.cluster_centers_,axis=1)
#print(expenses)
CityCluster = [[],[],[],[]]
for i in range(len(cityName)):
CityCluster[label[i]].append(cityName[i])
for i in range(len(CityCluster)):
print("Expenses:%.2f" % expenses[i])
print(CityCluster[i])

结果

聚成3类

聚成4类

拓展&改进

计算两条数据的相似性时,sklearn的K-means默认使用的时欧氏距离。该算法并没有设定更改距离计算方法的参数。

DBSCAN算法原理

DBSCAN算法是一种基于密度的聚类算法:

  • 聚类的时候不需要预先指定簇的个数
  • 最终的簇的个数不定

DBSCAN算法将数据点分为3类:

  1. 核心店:在半径Eps内含有超过MinPts数目的点。
  2. 边界点:在半径Eps内点的数量少于MinPts,但是落在核心点的邻域内。
  3. 噪音点:既不是核心点也不是边界点的点。

DBSCAN密度聚类算法流程

  • 将所有点标记为核心点、边界点或噪声点
  • 删除噪声点
  • 为距离在Eps之内的所有核心点之间赋予一条边
  • 每组连通的核心点形成一个簇
  • 将每个边界点指派到一个与之关联的核心点的簇中(哪一个核心点的半径范围之内)

DBSCAN算法应用

背景

现有某大学校园网的日志数据,290条大学生的校园网使用情况数据,数据包括用户ID,设备MAC地址,IP地址,开始上网时间,停止上网时间,上网时长,校园网套餐等。利用已有数据,分析学生的上网模式。

需求

通过DBSCAN聚类,分析学生上网时间上网时长的模式。

思路

  1. 建立工程,引入相关包
  2. 加载数据,预处理数据
  3. 上网时长的聚类分析、上网时间的聚类分析
  4. 分析结果

实现过程

  1. 建立工程,导入sklearn相关包
  2. 读入数据并进行处理
  3. 上网时间/上网时长聚类,创建DBSCAN算法实例,并进行训练,获得标签
  4. 输出标签,查看结果
  5. 画直方图,分析实验结果
  6. 数据分布 vs 聚类

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# -*- coding: utf-8 -*-
"""
Created on Thu Apr 18 23:35:39 2019

@author: Jiaxi Wang
"""

import numpy as np
import sklearn.cluster as skc
from sklearn import metrics
import matplotlib.pyplot as plt


mac2id=dict()
onlinetimes=[]
f=open('TestData.txt',encoding='utf-8')
for line in f:
mac=line.split(',')[2]
onlinetime=int(line.split(',')[6])
starttime=int(line.split(',')[4].split(' ')[1].split(':')[0])
if mac not in mac2id:
mac2id[mac]=len(onlinetimes)
onlinetimes.append((starttime,onlinetime))
else:
onlinetimes[mac2id[mac]]=[(starttime,onlinetime)]
real_X=np.array(onlinetimes).reshape((-1,2))

X=real_X[:,0:1]

db=skc.DBSCAN(eps=0.01,min_samples=20).fit(X)
labels = db.labels_

print('Labels:')
print(labels)
raito=len(labels[labels[:] == -1]) / len(labels)
print('Noise raito:',format(raito, '.2%'))

n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0)

print('Estimated number of clusters: %d' % n_clusters_)
print("Silhouette Coefficient: %0.3f"% metrics.silhouette_score(X, labels))

for i in range(n_clusters_):
print('Cluster ',i,':')
print(list(X[labels == i].flatten()))

plt.hist(X,24)

结果展示